Zoe with latest Pi Zero using mailbox PWM:
She did some brilliant lawn mowing too, along with picking up the daisies, but I think I’ll be doing the rest of the lawn tomorrow with a proper mower!
It’s been a bit of a “Bah Humbug” few days.
RPIO.PWM needs upgrading to use mailboxes to find the memory mapping from the video cortext to the RPi for Zoe. I needed to merge the ServoBlaster code into RPIO.PWM which although not hard, was going to need care and time; the latter of which is hard to find in my house.
The LEDDAR integration worked well, but for some completely unrelated reason, the asynchronous code I use for catching hardware interrupts stopped working – it was only catching the first. That meant there was no protection mid-flight for a FIFO overflow and the commensurate dodgy data and resultant crash.
And then in the last two hours, today turned into a “Mint Humbug” day. Mint Humbugs are my favourites sweets; I have two bags of them in the office right now. What was the source of the turnaround, you may ask?
I realised while cycling back home after buying some beers that I didn’t need the asynchronous callbacks any more; they date from the pre-FIFO era when I needed to know a batch of data was ready. Simply polling the interrupt pins was a better solution. That’s now implemented and tested passively in my ‘lab’; live testing starts tomorrow.
And while I was finishing this up, I got an email from a friend in China who started building his quad based loosely on my code a few months ago; he got in touch regularly asking advice and I happily gave it. But a while back the tables turned; today he sent me his latest flight video of 35s of stable hover. The flights are in an underground concrete car-park, and he’s using LiDAR technology for obstacle avoidance and position stability, and it works beautifully. Sadly, I don’t think I can share his video due to the Chinese Wall between us.
Shortly after his first e-mail arrived, a second e-mail from him arrived in my inbox containing his mailbox version of the RPIO.PWM code which he uses on his RPi 2 & 3. I couldn’t believe my luck. Thank you so much Reik Hua!
And to finish the day off, I’ve subscribed to another 6 months of the MagPi magazine, which means I have another free Pi Zero plus camera cable on the way.
Now, where is that bag of mint humbugs – it’s time to celebrate!
I’ve found out that fixing the RPIO.PWM code for the new PiZero (and a B2 and B3) shouldn’t be that hard. From ‘joan’ on the RPi forum and Chris who wrote the RPIO.PWM code, I’ve found out that the right way to access DMA for PWM is via a ‘mailbox’ instead of building a page map, and even better, Chris pointed me at the ServoBlaster code changes it made to swap from the pagemap to the mailbox method. RPIO.PWM is derived from ServoBlaster, and so the upgrade to ServoBlaster is almost a direct fit for the required update to RPIO.PWM.
So once more, I now have the key I can start with. But for now, it’s back to testing the merge of the new LEDDAR code into Phoebe’s HoG code.
Here’s the heating circuit I plan to use snaffled from here:
The Load is an SMD resistor about the same size as the MPU6050 chip, attached to it with thermally conductive sticky tape. It needs to run near its power capacity (= melt down) when loaded with ≈ 5V. SMD resistors of the right physical size have max. power settings ≈ 1W meaning 0.2A will trigger meltdown. A resistance ≈ 5 / 0.2 = 25Ω will serve the purpose perfectly
The mosfet needs to have a low internal resistance itself, so the heat is generated primarily by the resistor. The 2N7000 shown has a wide range of specifications depending on the manufacturer. The best I’ve found is 2Ω, so the mosfet will drop 5V * 2 / (2+25) = 370mV and 0.37 * 0.2 ≈ 0.075W. That’s about 12% of the chip’s maximum power rating of 625mW.
Alternatively, a BS170 has a 1.2Ω source gate resistance, dropping ≈ 240mV and ≈ 0.05W – 6% of BS170 specified 830mW.
The GPIO is PWM driven so that resistor meltdown is avoided with feedback from the MPU-6050 internal temperature sensor.
There are a few niggles left:
I guess I’ll just suck it and see.
After a very useful conversation on the Raspberry Pi Forum, it turns out all I need to temperature manage the MPU-6050 is a resistor. Instead of using the Peltier to heat or cool the IMU to a mid-range arbitrary temperature, you use a resistor to heat the IMU to a safe above-ambient temperature – say 40°C (104°F, 313K).
Many SMD resistors will sit on the 4mm x 4mm top plate of the MPU-6050. They tend to be rated at up to 1W max power rating and roughly 70°C at max power.
Taking power direct from the 5V battery means the current to supply max power to the resistor is (P = VI)
1W/5v = 0.2A
That’s a resistor of the order of (V = IR)
5V/0.2A = 25Ω
With that, PWM will prevent the resistor melting, and the MPU-6050 temperature sensor will provide feedback to maintain the chip at 40°C
Then all I need is a mosfet to switch 5V through the 25Ω resistor based on the GPIO pin 3.3v PWM.
Google “crystal oven” – this uses an op-amp, thermistor and resistor to do analogue temperature control of oscillator crystals which also drift with temperature. In my case, the op-amp is replaced by a PID driving PWM output, the thermistor by the MPU-6050 temperature sensor, and the resistor stays the same.
I’ve seen a few on-line conversations adamantly stating that quadcopter control needs a real-time OS (RTOS) or microcontroller to ensure accurate timing but with zero solid evidence to back it up. I’ve always been adamant this is just viral hearsay, and I’m being the heretic by coding in Python on Linux.
Of course the PWM signal to the ESCs needs absolute accuracy, but luckily the Raspberry Pi does provide hardware PWM.
Anyway, yesterday, I got to do some testing on the newly restructured code, and the results were underwhelming. Not terrible but not the radical change I was expecting. The only possible cause I could see in the stats was noise swamping accelerometer data.
I’m now not sure how exactly that led to a train of thought about fine-tuning time in my code, but it did.
The net result now is that there is a single time-stamp in the code taken immediately after I read a new batch of sensor data. From that point onwards, time effectively stops for the processing of that data by the rest of the code. All integration, averaging, and PID integration and differential processing uses that single timestamp. That makes for best accuracy in all three(ish) areas. It also has speeded the code up by another 5% (all 7 PIDs had their own time tracking which has now been removed). This means I can also reduce noise by including more sensors samples in the integration and averaging code before feeding it to the PIDs at the same rate as before. So beneficial in lots of ways.
Timing innaccuracy probably wasn’t the cause of the accelerometer noise, but at the same time, improving it has to be “a good thing”TM. My best guess as to the cause of the noise is a dodgy motor which if spun manually, sounds like it has muck in its bearings. Also the new high power props spin slower bringing more prop noise in under the MPU6050 dlpf.
I’m now hoping the timing rework, combined with lower dlpf and a new motor will cut the noise down significantly allowing me to see the results of the code rework.
As you may have read previously, all my testing was plagued with noise. It was corrupting the Euler angles enforcing a very low DLPF of 5Hz which then means important data was lost; the most obvious symptom of which was corrupting the vertical speed – Phoebe was rising to twice her programmed height because the accelerometer data was being clipped.
I’d speculated that the noise could well be generated by Phoebe herself by feeding the PWM signals too frequently creating broad-spectrum jitters in the motors. As a solution I was considering adding a rolling average for the PWM output. But a comment from David in that post suggested a much easier approch – just let Phoebe sleep each loop.
By adding sleep, she updates the PWM less frequently, reducing the number of PWM pulse width changes per second, and thereby reducing the noise – nothing as complex as rolling averaging was needed.
So I tried it just now: I set the sleep delay to 14ms which combined with the processing time of 6ms leads to a 50Hz update. First flight looked much better with the 10Hz DLPF, so I upped it again to 20Hz and it was perhaps the best flight ever: vertical takeoff to 1m as requested, hover over the takeoff point, landing back to the take-off point. No drift because no wind. So many problems resolved by a little sleep.
Time to update GitHub with this radical imrpovement! GitHub updated. I’ve updated the default parameters to match what I was using so all you need to run the same test is
sudo python ./qc.py -f
I’ll produce a video next time I head off down the park – better scenery than the back garden.
although it’s actually more like an ultrasonic scan.
Slightly off-topic, but there was a comment conversation about whether ESC PWM input pulse width ratio was linear wrt output motors RPM.
I used the Audio Spectrum Analyzer app, combined with running tests at various PWM speeds. Oh, and some Blue-Tak to keep Phoebe on the floor as she went over take-off speed.
Here’s what you get – make of it what you will, but it’s definitely not linear – although there are linear sections – the samples are at 5% PWM intervals and it is linear between 20 and 25%, 25 and 45% and finally between 45% and at least 60%. I daren’t take the test further just in case the blue-tak let go and she whizzed up to the ceiling. So the ESC microcontroller is doing some sort of logarithmic approximation – also not shown on the graph is that the motors RPM climbs steadily up to the PWM spin rate; the ESC is playing a role there to soften changes in desire spin rate. I’m guessing the non-linearity of the ESC is to adjust / compensate for non-linearity of the power delivered by each blade for a given rotation speed.:
I guess if I have time to kill another day, I could attach my iPad iMSO digital ‘scope and see what the ESC output PWM looks like – but, as I say, that’s for another quiet day. Now back to PID tuning, where depending on the weather, the next steps are to rerun the Z-N PID tuning with a better (nearer centre of gravity) hang of Phoebe, or a test flight with a lot lower Ki gain.
I’ve been PID tuning for the past couple of days, and it’s been very tricky (for that read “effing PITA”).
When Phoebe had her centre of gravity dangling between her legs (Gentlemen, behave!), she was virtually self levelling – equal power to all blades and gravity would do the rest.
But with the rebuild, her centre of gravity, though still below the plane of the propellers, isn’t much below. And that does make her very sensitive – a good thing as her reaction to disturbances will be super quick but only once I’ve got the PIDs tuned..
Thankfully, one of the reader’s, David, commented about mathematical tuning called the Ziegler-Nichols method. It’s not perfect as this “we have a chip-on-our-shoulder about Z-N PID tuning and suggest you pay us for our tuner instead” article describes in detail. However, the systems they name which should work match the dynamics of a quadcopter. The Z-N algorithm takes away two thirds of the tuning, and makes very clear and simple what you’re looking for in the remaining “third”. I strongly recommend you read it before carrying on reading here – it’s only a very small Wiki stub article.
The aim is to find the magical Ku, the ultimate gain, and the frequency of stable wobbles @ Ku. From that you can determined Kp, Ki and Kd for whatever kind of behaviour you might be looking for – mellow, jumpy or normal. Sounds too good to be true, doesn’t it!
And indeed it is, but it’s no fault of Ziegler-Nichols that it doesn’t work reliably. As my testing progressed, and the battery voltage reduces as a result, so do the resulting Ku values, and that can only be blamed on the ESC for not increasing the pulse widths of the PWM signal feeding the motors to compensate as it detects the reducing supply voltage of its battery.
The reducing supply voltage does change the speed of rotation since that driven directly by the PWM switching between the 3 phases of the motors coils. But it does affect the power applied to those coils.
The ESC should be able to compensate for the reduced power based upon the fact motors have a manufacturer Kv value relating rpm to voltage supplied linearly. The ESC PWM signal to the motors is effectively dividing the input voltage from the batteries to a lower voltage. So if the ESC tracked the input voltage, it could increase the PWM pulse width to the motors to compensate. But I suspect my ESCs don’t do that leading to the every decreasing Ku values I’m seeing.
Now I’ve never liked the idea of a microcontroller ESC sitting between the Raspberry Pi and the motors – I don’t like the separation of control – it’s like Dalek’s serving tea to Winston Churchill in the second World War – you just can’t trust them. And I think now I understand enough about what’s going on that I could make my own ESCs that are better. Here’s the ingredients list:
The one missing piece of the puzzle is the connection between the ESC to motor PWM used to ‘reduce’ the power supplied. But, again, thanks to another comment conversation with David, it should be possible through a combination of audio spectrum analysis to determine rpm, combined with the motor’s Kv to infer the ESC to motor PWM power on / off ratio.
I’m really quite excited about this, thanks David. Having written all this up, I definitely owe you a couple of beers.
Sadly, I do still need to sort out the PID tuning for the tetchy Phoebe, but this was an interesting diversion, and has got me thinking about how to make Phoebe the 100% Raspberry Pi Quadcopter controller I’d always hoped to achieve. And that’s very exciting!
P.S. Just realized that the home grown ESC will need 2 PWM feeds per motors – the first provide the 3 phase output to a given motor at the required rotation speed, and the second uses Kv combined with the rotation speed to ensure the right voltage is supplied to the motors to run at that speed effectively / efficiently.
I ran a quick test indoors playing with the audio spectrum analyser for my iPad. Quite a cool piece of kit, though I did pay for a decent one.
The plot shows peaks at about ~65Hz, 126Hz and multiples of ~65Hz thereafter suggesting an RPM of about 3780. Kv for my motors is 980 rpm / V which suggests 3.86 volts.
The PWM was set up with 1400us pulses – given the range is between 1000us and 2000us, this suggests 40% power from a freshly charged (12.2V) battery => 4.88V
To be honest, it doesn’t surprise me these two values don’t match. In fact, I think Kv is as good as irrelevant for use with brushless motors, and in fact provides just another obfuscating factor to confuse the user:
Brushless DC motors work much like stepper motors. They are fed a 3 phase signal at a given frequency, and depending on the number of coils / magnets on the stator / rotor, the motor spins at a fraction of that 3 phase signal frequency. The amount of voltage driving the current they draw simply provides the power level required to drive the motors with a load (i.e. propellers) at the frequency defined by the 3-phase signal.
These days, the ESC uses a microcontroller to interpret the input PWM, and uses that simply as a factor to scale the motor rate from 0 to 100% motor spin rate. The ESC drives the motors with 3-phase PWM-like digital signals. They use inductive feedback from the motors to track how much power (i.e. the width of the 3-phase PWM pulses) needs to be applied to the motors to make them spin at the desired rate, regardless of the load (i.e. propeller size / weight).
In the world of brushed motors where the magnets are stationary and the coils spin, I can see how Kv is relevant: the rate the motor spins is directly proportional to the voltage applied. But brushed motors generate huge amounts of electrical noise, and wear out quickly, and so simply aren’t suitable for UAV’s (Unmanned Autonomous Vehicles – i.e. RC boats, planes, cars) of any kind.
IMHO, in the world of brushless motors, the mathematical value of Kv is frankly utterly meaningless, and only provides an arbitrary measure of what kind of battery can be used to provide suitable spin speeds for a given set of motors / propellers:
Kv of the order of 700 – 1000 are suitable for 3 cell / 11.1V LiPo’s with small propellers (8 – 10″)
As the Kv value drops into the say 300 – 700 range, then more cells are required to provide the same RPM – typically though, motors with these Kv values are intended for use with very big blades, where the required rpm to produce the same force is much less.
Obviously all the above is based upon my opinion, so may be utter bollox – I’m more than happy to be proven wrong.
P.S. On the plus side, the single sharp peaks at 65Hz intervals does suggest that all of my motors are rotating at the same speed, and none are obviously duff, which annoying means I still have no idea why yaw compensation is still plaguing Phoebe’s flights.