I put together one of the SRF02 ultrasonic range finders onto my prototyping Pi:
Prototype range finder
Knocked together some simple code…
An it all just worked! Ranges detected accurately to large objects, while ignoring little things in the way.
Next step is to install this on Chloe once her new arms turn up.
So the remaining problem to be solved was to prevent the duff I2C reads and writes. These caused completely random configuration failures, and also random sensors outputs.
The problem is simply that the Adafruit I2C SMBus python code would sometimes hit an Exception, I assuming due to timing in hardware. Certainly it’s not the Python code at fault. So the obvious solution is to simply retry the I2C read or write if the IOError Exception was hit; simples! And it seems to have worked. Yes, the exceptions are still being hit, but are now retried until the exception isn’t hit. This seems to be infrequently, and only needs this second chance.
So finally, I’ve run out of problems to solve on the ProtoPi setup. New MPU6050 is deployed, the RPIO PWM is deployed. Time now to move the hardware and software changes over to the drone! Reality bites time!
I can feel a Eureka moment coming soon!
I can see at least two more problems to be fixed, but I can also see that unless my drone breaks the laws of physics, the number of problems really has to be nearing 0.
So the latest problem to be solved is how to avoid the junk / garbage data read from the MPU6050 sensors shown in the previous post. That’s an answer for another day, as I need to understand and fix it first. The problem is due to bad I2C interface reads, meaning the sensors appear to return values of -1, leading to the spikes you can see on the previous post.
Today’s fixed problem (I think) is how to ensure you only read data from the sensors when you can get your grubby mits on it safely?
- the MPU6050 has two sets of sensor registers – ones that it fills in, and ones that are read by software
- The software registers are updated periodically from the internal registers based upon a timer, and when that happens, the data ready interrupt gets triggered
- The sample rate for the readable register updates depends on both the DLPF (1kHz if enabled, 8kHz if not used), and the configured sample rate divisor allowing user configuration of how often the sensor samples are updated.
So to read a full set of sensors, they need to be read in less time than the next sample gets pushed to the register. This means I need to change my readSensorRaw code as follows
- read the interrupt status register to clear any outstanding interrupts
- spin waiting for a fresh interrupt
- start a timer
- read the sensors
- stop the timer
And finally reconfigure the sample rate divider (in code) so that the elapsed time measured above is less than the sampling period.
In the quick tests I did, the reading of the sensors took ~6ms, so with the DLPF on, the internal sample rate is 1kHz, so I’ve set the sample divider to 10 so that the external registers change every 10ms which should be more than enough time to read the sensors.
The MPU6050 is the gyro + accel sensor. I have a new version (same chip, different breakout board) which should mean it’s better pinned to the breadboard.
ProtoPi with new MPU6050 + RPIO PWM
I’ve incorporated the code change to make sure the DLPF (digital low pass filter) takes effect…
and actually, the results are looking a lot better, except for this…
Vertical acceleration and integrated speed
So the prototype (ProtoPi) was sitting on the desktop, going nowhere. The accelerometer looks very good – the acceleration (navy blue) is integrating to a flat line vertical speed (pink), which means the sensors are nicely balanced. Except of course when one of those whopping spikes appears which throw the vertical speed integration way out (meaning that the drone thought it started travelling at 0 cm/s vertically, then dropped at 20cm/s before descending further to 80cm/s. If this was a live run, the PIDs would try to counteract these dodgy readings, powering up the motors and slapping the drone head-first into the ceiling!!!
I have to assume these are garbage reads from the MPU6050, even though the code now has interrupt handling to only read the data when it’s ready and waiting.
So I’m throwing this out to the world at large for suggestions…please, I beg you!
Once I got the Raspberry Pi (aka ProtoPi from now on) installed, imported RPIO, wired it up to my iPad mini tablet via an iMSO digital oscilloscope, it took just a few mins to write the code to prodoce 4 PWM gpio outputs, each using the same PWM channel, but each with their own set of pulses.
RPIO PWM, 1 channel, 4 GPIO outs each with their own pulses
Here’s the code used to do this:
Even better there was 0 CPU used while the pulses were running.
Next step depends on the delivery of the breakout for the MPU6050 to pin it firmly to the breadboard.