Saturday 10 November 2012

More adventures with Raspberry Pi and an IMU

Buying a cheap IMU is definitely a good way to learn about working with sensors. When I last posted about this I'd managed to get some sensible data out of 3/4 of the sensors but hadn't realised all the fun I had ahead of me.

Right now I think I'm about 25% of the way through getting to a stage where I'll be confident about working with this thing but at least I'm now getting good data from all of the components and my Raspberry Pi can tell me this sort of information with a refresh rate of around 100hz:


Accelerometer xyz  g: 0.008,0.023,1.005                                         
Gyroscope xyz    dps: -0.061,0.166,-0.674                                       
Mag xyz        gauss: 0.002,0.055,-0.074                                        
Bearing          deg: 2.045                                                     
Gyro Temp      deg C: 28.000                                                    
Temp           deg C: 25.900                                                    
Pressure      Pascal: 99334.000                                                 
Bar Alt  m (sea lvl): 167.353


That might not look like much but getting this far has involved a lot of work with documents like this beauty, from Freescale.

I'm not finished with the Compass\Magnetometer yet, the bearing data I'm getting right now is only roughly calibrated and not tilt compensated but I now know what I need to do to get that properly corrected. The Gyro Temp sensor doesn't work but that's not a big deal, the barometric sensor gives me a good temperature reading.

The next challenge is getting these properly calibrated and establishing how accurate\noisy the particular components are. The compass and gyro are the big headaches on this front, the gyro because it is inherently a noisy signal and the compass because I need to actually code solid routines for handling both hard iron interference ( ie magnetic interference fixed with respect to the reference frame of the sensor ) and soft iron interference ( magnetic interference that varies with position ).

After a couple of days failing to understand the sensor data I had thought the compass ( a Honeywell HMC5883L ) was broken. When I thought I should be getting numbers that would vary between +-(something) in each axis as I rotated the sensor I was getting something very different:

Bearing             X              Y                     Z
0 -683 -473 -442
45 -773 -420 -436
90 -800 -311 -433
135 -749 -222 -436
180 -647 -194 -441
225 -561 -258 -447
270 -545 -354 -451
315 -589 -436 -449
360 -683 -472 -442


I blame the amount of time I have to work with PowerPoint for the fact that I couldn't see a pattern in that. In any case I thought I should simply be able to apply a tilt transform to make this better but that actually made things a lot worse. I really should have read the Freescale white paper earlier.

Anyway I got led on a number of wild goose chases as a lot of people seem to have issues with this sensor but none of the code that I found helped. I even tried switching over to an Arduino and testing code from a number of sources for that. The code worked, the values still didn't.

The light bulb moment came from a comment on a blog post about the HMC5883(L) from a guy called Cory who worked on a similar IMU that gave me the clue I needed to solve the problem. The comment wasn't actually about the IMU that I have but he said that the BMP085 pressure sensor they used was actually magnetic to some degree and my IMU also uses that pressure sensor. That meant that that there was probably a fairly significant hard iron interference issue on my little board and a quick graph of the above sample data showed me a smoking gun. Ideally, on a calibrated compass with no interference, the data below would have been a circle around the origin but the fact that what I was seeing was vaguely circular was enough to tell me that it was working and all I needed to do was to sort out the interference problem if I wanted it to be useful.


The really important lesson in this is it is always worth trying something visual if you are trying to make sense of data. I think that needs to go into The Rules, preferably with a number somewhere high up the list, just after the bit where you actually pay attention to things like calibration and sources of interference.

A slightly larger data set has given me a baseline transform for the hard iron interference - this is simply an x,y,z offset so it's only trivial code and while it is not as accurate as I want to get to it's more than enough to tell me that the sensor is working correctly. It now reliably indicates that North, East, South, and West are approximately 90deg apart at any rate.

All code is up on Bitbucket ( I seem to be having some sync issues with this right now, that should be sorted out shortly Fixed..).

4 comments:

city said...

thanks for sharing.

Kyle Berry said...

The link you have provided results in an access denied. I don't think your project is available to the public

Joe Mansfield said...

Should be sorted now - the AdaFruit IDE seems to really want to set it to private, this is the second time it's been reset.

John said...

That is also giving me an access denied message..