Magnetic Field Measurement
I have always wanted to play with MEMS IMU. The magnetometer in these 9DOF IMUs is easier to use than the gyro or the accelerometer because testing it doesn't require extra mechanical hardware. The gyro, for example, needs to be spinning to generate interesting data. That means a rotating platform, and a wireless communication channel and battery.
These sensors produce lots of data so the processing will have to be done on something more powerful than a microcontroller. Getting the data from microcontroller to laptop is easy with the LUFA USB library on an Atmega32U4. I have a Python script to dump the received readings to a text file, and some MATLAB scripts to process and plot the data.
A good test to verify that it's working properly is to measure the magnetic field around magnets, since I know what the field should look like.
Moving it around two repelling magnets and take hundreds of readings over a grid:
Repeat another 273 times to get another, this time with two attracting magnets:
(plots not yet compensated for the Earth's magnetic field)
Manually moving the sensor around and taking thousands of measurement is not very scalable nor very "academically challenging" - I need to justify my expensive education somehow. I could get three motorized linear guide rails and move the sensor in Cartesian coordinate, but that's too bulky, costly and... where's the fun without the maths.
So I got some servos and (aluminium) mounting hardware off eBay, some screws and washers from a local hardware store, a piece of scrap wooden floor plank from my neighbor (they are renovating) and put together a 3-DOF arm:
With inverse kinematics, I can generate a path (a sequence of waypoints) in 3D space using MATLAB, have the robotic arm trace them with Python and measure the magnetic field along the way.
Now that everything is automated, why limit the resolution to a 11 by 11 grid:
That's 51 x 51 = 2601 data points. This is the same data set shown at the end of the video, except that the proper coordinate transform has been applied (see the "Minor Details" section at the bottom of page for details). The graph below shows the background magnetic field (without the magnet):
You can see the influence of the steel screws and servo at the base of the arm on the background magnetic field. The base of the arm is at the lower left corner, where the background magnetic field is strongest. Pretty cool.
If I can do a square, why not a cube:
11x11x11 = 1331 readings. Imagine measuring those by hand. Gotta love robots. The graph below shows the path the robot followed:
Since I've got the inverse kinematics worked out, why not have some fun with the bot:
Perhaps I should do some light painting with this arm later.
A few points I thought worth mentioning.
Since the magnetometer is mounted at the tip of a 3 DOF arm, the pose of the magnetometer changes as the arm moves through space. The readings from the magnetometer are with respect to sensor frame, so they need to be transformed back into the world frame for the readings to make sense.
The analog servo I used in the arm is too "soft" for robotic application - it doesn't hold position well even though it is advertised as "high torque" (Hitec HS-645MG). I have also experimented with the "high resolution" digital servos (HS-7966HB and HS-5485HB), but they tend to oscillate around the setpoints under load.
So What's Next?
I have a few things in mind.
Characterize and improve positioning accuracy, precision and repeatability
What if I use brushless servos? The more expensive "robot servos"? Stepper motors? Brushed DC + optical encoder? OpenServo? Digital servo hack?
Add extra redundant DOF to measure full 3D space (rather than one side of the magnet)
Have fun with the math
Made it on Hackaday.