# I couldn’t let it lie!

I still feel there must be a way to get a fixed 0g offset algorithm, based on the fact off-the-shelf quads won’t have to undergo this level of faff by the user; there must be a simple setup for the manufacturer.

Here’s what I got in my latest attempt:

XY 0g offsets vs. temp change

Look’s good, doesn’t it?  Nice trend lines which the samples offsets are really tightly aligned with.

The graph X-axis shows the change in temperature since the IMU started.  The 333.87 is about 1ºC, so this is what the test plots offset changes as the chip temperature increases away from the boot temperature.

The graph Y-axis shows the 0g offsets: the accelerometers scale is configured as ±4g so the vetical axis covering -1000 ⇒ +800 is the equivalent of -0.12g ⇒ +0.10g.

The lines show the 0g offsets as the difference in temperature increases from the initial boot termperature: the green ones are the accelerometer X-axis offsets; the blue ones are the accelerometer Y-axis offsets; the paler -464 lines come from a garage estimated +10ºC test environment; the darker +1600 lines come from an indoor estimated +20ºC.

OK, with that explained, down to so positive interesting bits:

• the 0g offsets are all very close to 0 when the test starts i.e. when the temperature difference from ambient is near to 0.
• all of the samples fit a linear trend line beautifully.
• the 2 y-axis trends are very similar despite the tests being booted at very different temperatures

But there are very odd bits too:

• in contrast to the y-axis trends, the x-axes trends are virtually the opposite of each over when booted at the very different temperatures
• all of the offets are hugely different from the ones I’ve measured by the same method previously, perhaps by a factor of 10!

Net: I critically need to try to understand these oddities if I stand any chance of using these offsets in a meaningful way.  If I can, then this gives me the best possible / nigh on perfect way to allow for offsets shifting as the difference from ambient changes.

# I need a nice cold beer…

so I’ve bought a beer fridge.

I’m giving up on iterative accelerometer calibration for the moment as there are problems I’m struggling to resolve. I’ll probably invest some more time later, but for now, I’ve a deadline to meet, so I’m going to drop back to manual but refined calibration along the following lines

1. buy a beer fridge – I chose the Peltier effect one as it’s silent and so can reside in my office / “Raspberry Pi research lab”  Also the Peltier cooler is solid-state, and therefore there is no motor and compressor to add noise to any sensor readings.
2. fill the beer fridge with beer, or something else with a high specific heat capacity so that opening and closing the door doesn’t cause radical changes in temperature
3. Place a tilted platform inside the fridge, and measure / calculate the angle of tilt θ
4. remove the Raspberry Pi from Phoebe, place on said platform powered by a battery, and leave to cool
5. After a while SSH in, and read / average sensors – rotate RPi 90° between each reading.
6. Remove platform and place horizontally, and read sensors.

As long as the fridge is horizontal then

• the vertical Z-axis offset is half the difference of the sensor readings
• the vertical Z-axis gain is then one (i.e. 1g) over either of the (sensor + offset) values.

The X and Y sensors are slightly trickier; I have to use the tilted platform as the RPi doesn’t sit on it’s sides – too many sticky-out bits.  The tilt of the platform needs to be high,  > 45° if possible because the X and Y sensors are reading 1g * sin θ.  Otherwise the process is the same.

Then the beer is removed from the fridge, the fridge is turned off, and the door is left open for the fridge to rise to room temperature.  The above is repeated.  While you’re waiting for the fridge to warm up, there’s some lovely chilled beer to keep you occupied!

Both sets of samples include a temperature reading from the MPU6050, so assuming linearity across temperature (which the spec’s say is true ± 2%), then it’s straightforward to come up with gain / offset values for all three axes at any temperature.  The equations for the gain and offsets against temperature are then added to the code.

I don’t like this level of calibration, but given my deadline, I need to have correctly calibrated accelerometers regardless of how it’s done.

It ain’t rocket science, but quadcopter science still isn’t simple. I’ve got my calibration wrong for the accelerometer. I’d omitted the fact that if Phoebe is static, depending on how she is leaning, gravity can be shared across 3 axes.  Don’t get me wrong, I’ve had this covered for ages converting from Phoebe’s axes acceleration to earth axes, but not for the accelerometer calibration. Critically, this means the trend lines for acceleration vs. temperature calibration are wrong leading to drift, and odd scaling between axes – i.e. everything I’m seeing going wrong right now.

Earth calibration

Here’s a diagram of Phoebe’s sensor readings from the rear in red; her left side is tilted down by a negative roll angle θ.  Her pitch angle is 0 (horizontal). The only force is gravity shown in green as a positive value which is how the sensors measure it.  Hence the combination of the the qay and qaz sensors combines together to make up 1g of gravity.  Likewise, a different combination of qay and qaz cancel each other out to make 0g horizontal acceleration. The same applies to the X-axis and pitch angles, but using the Y-axis / roll angles is easier to visualize, and she does have a cute bum!

The result is the following ‘matrix’ for conversion from Phoebe’s accelerometer readings to earth coordinates:

```eax = qax * cos(pitch) + qaz * sin(pitch)
eay = qay * cos(roll) + qaz * sin(roll)
eaz = qaz * cos(pitch) * cos(roll) - qax * sin(pitch) - qay * sin(roll)```

If Phoebe is not accelerating, then the only force is vertical gravity, so eax and eay are both 0g and eaz is 1g. So assuming the accelerometer readings are perfect, and she’s sitting on the 21° tilt test rig with the fore-aft axis horizontal…

```0 = qax * cos(0°) + qaz * sin(0°)
0 = qay * cos(-21°) + qaz * sin(-21°)
1 = qaz * cos(-21°) - qay * sin(-21°)```

The calibration then involves calculating the offset and gain to convert accelerometer raw reading to ‘perfect’ qax, qay and qaz readings so that conversion to the earth axes leads to desired (0, 0, 1) as above Accurate calibrated Z axis offset and gain already exists from the previous calibration testing.  So together the equations collapse down to

```0 = qax
0 = qaygain(qayraw - qayoffset) * cos(-21°) + qaz * sin(-21°)
1 = qaz * cos(-21°) - qaygain(qayraw - qayoffset)sin(-21°)```

The Y offset can be calculated from the raw Y sensor readings with port and starboard pointing down on the rig – any difference between the two gives the offset:

`qayoffset = (qayport down + qaystarboard down) / 2`

As a result, the calculations collapse further to…

```qaygain(qayraw - qayoffset) = -qaz * tan(-21°)
qaygain(qayraw - qayoffset) = (qaz * cos(-21°) - 1) / sin(-21°)```

And now I’m bemused / confused.  qayoffset is known which means I have, what seems to me, 2 none equivalent equations for the qazgain Help!  Where have I gone wrong?

# Why did I choose autonomous flight control?

Right at the beginning of this project, 18 months ago, I assumed autonomous control was a necessary precursor to introducing a human into the mix for safeties sake.  18 months later I have just realized it’s the replacement for the human.  As I mentioned in yesterday’s post, none of the PIDs shown in a google image search have an integrated accelerometer velocity PIDs – they use a human with an RC transmitter and eyes to provide the outer most feedback loop.

The replacement for the human needs a motion sensor which can also measure distance travelled.  There are off-the-shelf solutions here and here and projects based on some google phone technology (cheers Jeremy).

What they share if you look hard enough is the fact they are being used as PhD or above papers in some of the best Universities in the world.

I’d looked at motion detection previously and the RaspberryPi forums did offer DIY ideas and commercial solutions, based upon static orf video image processing using image change processing to produce motion detection.  But again it all seemed too tricky based upon the fact off-the-shelf drones don’t do it.

I’d also tried accelerometer calibration using temperature trends to ensure regardless of temperature, the accelerometer offset / gain was known.  But I abandoned these for the same reason: nobody else bothers.

But now I finally understand why nobody else bothers – they have a human included in their feedback loop, still using an optical positioning system but with a much more powerful processor to control drift.

I really don’t want to introduce a human into the control loop – that was never part of my original plan.

So where to next? My short term target is only a 20 – 30s flight with minimal drift.  I would hope that the combination of trend-line accelerometer offsets and gains, combined with a few fixes applied since then may be able to achieve it.

Once more, we shall see.

# Groundbreaking news…

although probably not what you want to hear.  I think I’m biting off more than anyone else has ever chewed before: autonomous (self-contained) flight control.  I was watching a normal guy’s first flight of his DIY quad.  I’ve no idea of it’s build, but the first test flight was in his 4m x 4m lounge (my estimate) full of furniture, and it went better than Phoebe had ever achieved.

Then I started thinking back through all the other YouTube videos of quads in flight, and they all share the same piece that I am missing – an external PID feedback system whether it’s a human with a transmitter or the external monitoring system as shown by Raffaello D’Andrea’s video.

So I started looking at quadcopter PID images on Google, and they show the same thing: they all have an external feedback system (usually a user with an RC transmitter) where I have my velocity PIDs. This is why I’m having so much trouble with drift control: untuned acceleromer integration to produce drift feedback simply cannot work due to offset / gain inaccuracies; for completely autonomous control, the accelerometer tuning with trend lines to incorporate temperature shifts may well be the only solution until drift becomes large enough for GPS to take over.

I think I may have to return to the tedious trend line tuning to get better trends and hence better drift control.

Still, it’s motivationally exciting to think I may be breaking new ground.  Shame it’s taken me so long to come to this conclusion.

# Finally…

with the offset / gain in place, and a tweak of the horizontal velocity PIDs, I finally can see drift control working.  It’s still there, but so much better than ever before.

It also confirmed I need to do some temperature trend-lining for accelerometer offsets and gains – I did the offset / gains indoors at about 20°C.  Outside it’s only 10°C and that definitely had a significant effect on vertical velocity, and to a lesser extent horizontal too.

I almost daren’t say it, but it really does now feel I’m on the downhill run and the finish line is finally in sight – still in the distance – but visible at last.  Phew!

# Is 0.1% accelerometer error good enough?

I spent a fair proportion of today and yesterday tweaking and tuning the offsets out of the accelerometer and gyro. Gyro was a doddle as expected, and I’ve now got a process to reduce the accelerometer tune to a hour rather than a day, though it does start early in the morning before the sun rises. I suspect it won’t work well in a mid-summer heatwave where the temperature doesn’t drop much at night.

All I do it move Phoebe outdoors to the coldest spot I can find (the garage) and leave her for a while to cool down. While that’s going on, I move indoors and spend the time making the test platform as horizontal as possible – I even bought a super-spirit level a while back just for this job. When all’s ready, I whisk her indoors, power her up, and run her calibration code which reads the accelerometer, gyro and temperature sensors, writing the output to file. How often I do this depends on how rapidly the temperature rises – every few seconds at first, increasing to perhaps every 1/2 hour at the end, aiming for 0.5°C rise per sample. I’m aiming for an even spread as this will give me the most accurate trendline to use in the code. Phoebe is powered from the micro-USB port rather than the battery as this leaves the ESCs / motors unpowered and so noise is minimized.

Net result 0.001g accuracy in all 3 accelerometer axes, i.e. instead of reading (0, 0, 1)g, they read (0.001, 0.001, 1.001)g or roughly (0.01, 0.01, 10.01)ms-2. Previously the raw sensor output was more like (0.04, 0.036, 1.06)g so a 40 – 60-fold improvement.  Vertically, that’s probably OK, but horizontally, I’m less confident. Over 10s that 0.001g equates to 0.5m horizontal drift, which is not good enough for my ultimate goal of a 1 minute flight with drift < 10cm – i.e. demo’s in schools and Jams.

Still, I’ll give it a shot tomorrow to see if my unpowered tuning holds up in powered testing. Only time will tell.

# Trends

Gyro and accelerometer trends

Just a quicky: I spent yesterday gathering these higher quality trends mapping gyro and accelerometer offsets to temperature.

The trend lines are a lot more closely tied to the data points, so hopefully that’ll mean more accuracy.  I’ll give it a try today or tomorrow – I’m hoping that the net result will be even more limited drift, plus longer flight (different sides of the same coin essentially).

# A lovely day for sunbathing

Just done yet another Phoebe rebuild – new motors, new props, replacement legs – none of which are truly necessary but I thought I’d treat her. As a result, a fresh gravity calibration was necessary. The results came out ±1% compared to the previous reading as per usual, but that got me thinking.

The MPU6050 has a temperature sensor, and the specifications show variance of accelerometer and gyro output against temperature.  The gyro is calibrated prior to every flight as part of the start-up sequence so not a problem, but I calibrate gravity at home in my 20°C office before taking her out to play in the 10°C park – I wonder how much difference that makes?  According to the spec, there’s a ±35mg (milli-g’s) in the X and Y axes offsets, and a ±60mg in the Z axis offsets over a 0°C to 70°C temperature range.  Given that my calibration values can easily vary by ±10mg, it’s certainly worth some further investigation.

The forecast for today lay between 5°C first thing in the morning, rising to 12°C mid-afternoon ambient.  There’s also the factor of the MPU6050 self-generated heat.  So Phoebe spent the day initially in the cold garage, and then moved onto a horizontal sun-bed basking in the spring sunshine in the back-garden under her own green-house cover, and periodically, I’d recalibrate gravity and check her temperature.

Phoebe’s greenhouse

Here’s what I found:

Accelerometer offsets vs. temperature

Temperature ranges from about 7°C in the garage to 40°C in the greenhouse.  And as you can see from the plots, there is non-trivial variation.  Given how critical accelerometer readings are for both angle and drift calculations, it only makes sense to update the code to use the trend line equations (courtesy of Excel) instead of the fixed in-office calibration numbers.  I’ll give it a go and see if there’s any obvious effect.