Lab 6 – INU

Lab 6: Inertial Navigation Unit (INU)

GPS alone is not sufficient for road vehicle localization; it has nether sufficient accuracy nor availability. Primary localization is done without GPS. With the starting position and direction known, and the intended route known, position can be plotted by tracing how far we have come. This route will become inaccurate as the wheels slip, the odometer drifts, and the vehicle deviates from its course. This information can be kept accurate by measuring the compass angle of travel, and by nulling drift errors with fixes on landmarks or GPS checks. The Kalman filter of Lab 8 will fuse all location information into a position estimate that is more accurate than any individual sensor reading.

An inertial navigation unit uses accelerometers and gyroscopes to measure vehicle motion. Ships and spacecraft use stable gyroscopes that can be large and expensive. Micro-electrical-mechanical systems (MEMS) are light, small and inexpensive. A MEMS INU can be very noisy and subject to drift, but works well when combined with other instruments.

The INU selected for Elcano is the CH Robotics UM7 or UM6-LT:

It measures nine axes: three each for an accelerometer, gyros, and magnetometer. The magnetometer is a digital compass, and is the primary objective of this lab. The UM6 contains an embedded 32-bit ARM Cortex microprocessor (more powerful than Arduino’s AVR) which runs an Extended Kalman Filter (EKF) to smooth the data. When GPS is used with an INU, the resulting measurement is more accurate than using the GPS alone. A GPS signal can be input to the UM7 on the secondary serial line, and the UM7 provides an improved GPS estimate. Lab 7 will deal with configuring GPS, and Lab 8 deals with fusing multiple location sensors.

The UM7 interface is via the main serial (UART) line or via the SPI bus. The host processor sends a command to the processor, and receives data back.


INU code was downloaded from

Test on 11/08/14: See several loop outcomes on monitor:

1) Polling the UM6… // poll_UM6_gyro()

Attempting to read IMU…

Data available // read_UM6_gyro()

Attempting to read IMU…

Data never arrived…. // if (read_UM6_gyro() == true)

2) Polling the UM6…

Attempting to read IMU…

Data available

115110112Attempting to read IMU…

Data available

3) Polling the UM6…

Attempting to read IMU…

Data available

115110112Attempting to read IMU…

Data available

1151101129225525525521808Flushing buffer…!

Picoscope shows data transmitted by Arduino (5V) and received on Arduino (3.3V). Scope shows spikes on MISO; which is the Slave Output (from INU).
In the first instance, there was data on the first read attempt, but the first character was not ‘s’. There was nothing in the buffer on the second read.

In the second instance the ASCII code (115) for s is written, followed by 110 (n) and 112 (p). On the second read attempt, ‘s’ was not the first character.

In case three the second attempt reads snp , 0xC8, 0x5C = 92, 255, 255 = 0xFFFF = -1, 255, 52 = 0xFF34 = -204, 18, 08 = 0x1208 = 4616. The code then skips two characters, and reads the checksum. It computes a checksum, but fails the checksum test and flushes the buffers.

Some improvements to the code yield:

Polling the UM6…

Attempting to read IMU…

Data available

115s110n112p,0xC8,0x56,Attempting to read IMU…

Data available

115s110n112p,0xC8,0x5C,XY,255,255,255,217,0,9,0,0,6,54,654=chksum; 256=expected;

Flushing buffer…!

Polling the UM6…

Attempting to read IMU…

Data available

115s110n112p,0xC8,0x56,Attempting to read IMU…

Data available

115s110n112p,0xC8,0x5C,XY,255,246,0,10,255,87,0,0,0×5,0xCA,0x5CA=chksum; 0x5CA=check; 0x5CA=expected;

Checksum is good. Returning true!

Can you find the “snp” in the TX data from INU on the Picoscope? “snp” = 0x736E70 = 011100110110111001110000.

Other INU software is available from

Voltage levels

The original RS232 spec for UART serial data had high anywhere from 3 to 15 V and low equal to the negative of that voltage. Microcontrollers usually use TTL levels for serial data, e.g. 5V and 0V on the Arduino. The UM6 runs on 3.3V , but can tolerate the 5V signals transmitted from the Arduino and received on the UM6. The 3.3V UART signals from the UM6 are detected as high on the Arduino, since digital logic recognizes anything above 2.7V as high.

Using the UM6

The sample code shows how to use the UM6 to obtain gyroscope rates in two dimensions. Polling the device with snp 0x48 0x5C asks for 4 bytes of data starting from register 0x5C.

Registers between 0 and 0x40 are written to set UM6 characteristics. Registers from 0x55 to 0x84 are read to obtain data. Registers 0xAA to 0xFF are used to send commands to the device.

To use the UM6 as a digital compass, the registers of most concern are:

0x5A UM6_MAG_RAW_XY Get raw data from X and Y magnetic sensors
0x60 UM6_MAG_PROC_XY Get X and Y magnetic data with various compensations.
0xB0 UM6_SET_MAG_REF Position the vehicle so that it is pointing to magnetic north, then give this command to correct for the magnetic declination.
0xAA UM6_GET_FW_VERSION Report the firmware version.

Exercise: Use the UM6 as a digital compass.

The UM6 can also be used to tell the tilt of the vehicle. This is done through the following registers.

0x62 UM6_EULER_PHI_THETA Get estimated roll and pitch angles.
0x63 UM6_EULER_PSI Get estimated yaw angle.

The UM6 is a nine-axis sensor.

  • Magnetic sensors give three axes of compass direction,
  • Gyroscopes tell roll, pitch and yaw
  • Accelerometers can give three axes of translation.

The accelerometers are noisy and subject to drift. They are best combined with other instruments. Commands related to the accelerometers include:



Get raw accelerometer data on X and Y axes.


Get raw accelerometer data on Z axis.


Get processed accelerometer data on X and Y axes.


Get processed accelerometer data on Z axis.

Open Source Autonomy