Thursday, December 17, 2009

Building and programming the IMU

A couple of months ago, I made a post discussing the inertial measurement unit that we're hoping to use on BRB. A month and change after that post, the boards arrived from BatchPCB, and finally, with Christmas upon us, I've had a chance to put the thing together. Assembly was straightforward. Hot air is a must for the gyros, since the pads on the LGA package don't actually come to the edges, and is helpful for several other components (those who have hand-soldered SMD crystals will see how hot air might help). This was my first time using hot air. It's easy enough to get the hang of, and a great tool to have around, so if you haven't got a rework station already, maybe LGA would be a good excuse to make the investment.

Anyway, the final product is shown in the bottom half of the image below. I've made just one modification relative to the schematics in the original post, removing the high pass filters from the gyros. While these may not have been a problem in the final application, with a time constant of about 4.7 seconds, they would have interfered with the calibration discussed below, and at any rate seem to be unnecessary.


Up top is a breadboarded support circuit which supplies 3.3V regulated to the IMU and reads its output via TWI, optionally logging it on the SD card and displaying it on the LCD. I had this lying around from some work I did building TWI motor controllers for another project, and it seemed like the thing to use here.

One surprise from this circuit was that the z-axis magnetic sensor seems to have an unusually large bridge offset, and the opposite polarity from that given in the datasheet. The datasheet suggests that the latter can be corrected using the set/reset straps, but I'm not sure that's possible with the set/reset circuit we've built. At any rate, the device output is within the ADC range, and the polarity can be resolved in software, so I've decided to let it be.

(As a quick note for anybody who might be planning a similar IMU, I'm considering using the HMC5843 for future units. It's digital, with an I2C interface, contains all three axes in one chip, has about the same resolution we're getting with the existing setup with a tenth the cross-axis effect, and would cost about half as much as the 1051/1052 combination. Is anybody aware of a drawback?)

The software is quite straightforward. Atmel has published application notes on using the microprocessor as an I2C master and as an I2C slave. As part of the previous project noted above, I'd built a simple messaging protocol on top of this that I've reused for this project to allow us to easily read and reconfigure the IMU on the fly. An even simpler scheme could certainly be used, perhaps similar to that used via SPI by the accelerometer.

The accelerometer operates in SPI mode 3. The interface is straightforward -- after pulling the select low, an address byte is written whose two high bits control read/write and whether the address is automatically incremented after each byte. SPI transfers data in both directions simultaneously, effectively rotating the slave's one-byte buffer into the master and the master's into the slave. Reads and writes are therefore both performed by stepping the SPI as many times as you'd like, reading or writing successive bytes. Each query is ended by letting the select pin go high again. The accelerometer is activated by writing a 1 to bit 6 or 7 of the CTRL_REG1 register. Until you've done this, you'll find it returns zeros for all axes. Once powered up, the registers at 0x28-0x2D will give you the acceleration along each axis from the device's 12-bit ADC, returned by default as a 16-bit signed integer.

In addition to reading sensor values, the current software includes a timer to ensure that once per second, a set/reset cycle is queued for the magnetic sensors. Resets are performed immediately before the next measurement of the compass value. Each reset consists of a 5 microsecond pulse to pin SR_IN in the schematics, giving a reset at SR_OUT on its rising edge, and a set on its falling edge. These pulses do not correct the bridge offset, but instead desaturate the sensors after any exposure to strong magnetic fields.

That's it! The completed IMU seems to reliably return data for all nine degrees of freedom to a host. At this point, the data is raw. It includes offsets, scale factors, and axis discrepancies unique to each sensor. The axis discrepancies deserve a little elaboration. I can think of four ways that this might creep into the design:
  • The accelerometer would have been very difficult to mount so that its axes correspond to those of the gyros. Instead, we decided to leave the conversion to the software, in favour of a simpler hardware layout.
  • As I've already noted, the z axis magnetic sensor seems to have the opposite polarity from that in the datasheet. Again, this can be easily corrected in software.
  • Because the IMU is built from individual sensors, each placed by hand, there's little reason to believe that the x axis of the gyro will coincide with that of the magnetic sensor, for example, even if they were designed to. If this is significant, it'll have to be calibrated for.
  • Magnetic sensors also exhibit what is called a cross axis effect. This effect arises from distortion of the magnetic field within and around the sensor itself, so that the actual measurement axes may not even be orthogonal.
I'd like to correct those on the IMU, returning calibrated data to the host. How can we manage that without investing in Helmholtz coils and other equipment? More on that (hopefully) in my next post.