Search This Blog

Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

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..).

Wednesday 24 October 2012

Raspberry PI - Interfacing with an IMU

I picked up a dirt cheap I2C capable 10-DOF "IMU" breakout board with from e-bay ( this one here ) just to see how hard it would be to get some motion sensing capability for my Raspberry Pi. I know that we've had all these sensors built into phones for years now but it's still amazing that I can now buy a 3-DOF Accelerometer, 3-DOF Gyro, 3-DOF Digital compass and have a temperature\barometric pressure sensor thrown in for €20. 

After a bit of minor soldering a quick test proved that all the parts were visible over the I2C bus but I could only find Python libraries for the pressure sensor. This was not a surprise, and frankly I wanted to have to work a bit to get sensible data and I really wanted to have a project that I could use to learn Python. 

The breakout board has these sensors:


The extremely useful AdaFruit Learning System has a basic tutorial, complete with a working interface library for the BMP085. I already had one of those working ( it's on a second Pi that I bought because my first one was taking so long, so now it's monitoring the temperature and pressure in my attic - you can see that data here: https://cosm.com/feeds/80617 ) . That sample gives me enough of a framework to try building up the necessary libraries for the other three sensors. 

I've had a couple of evenings to hack away at this and I've now got sensible, if uncalibrated, data from both the accelerometer and magnetometor via Python. AdaFruit's Raspberry Pi WebIDE has been a joy to use for this sort of learning exercise - it's clean and simple (which I need right now) and its integration with Bitbucket means I can easily point people at the code I've managed to hack together so far:
This stuff just about works and I'm sure anyone who has any sort of Python skills will find a ton of newbie errors and bad practices in there but hey, they work and I will be cleaning them all up as I learn how to do all this properly. And hopefully I'll have the L3G4200D Gyro in there over the next couple of days.