Driver for Analog Devices' ADIS16467 Precision MEMS IMU Module.

Dependents:   ADIS16467-Tests

ADIS16467 Driver

by Rita Yang / USC Rocket Propulsion Lab

This driver supports all basic functions for Analog Devices' ADIS16467 Precision MEMS IMU Module. It supports all common functions of the chip, such as reading data from the gyroscope and accelerometer, retrieving the integrated angle and delta velocity, burst readingm and setting the sensor's polling rate.

Features

  • Support for reading of sensor data, including angular acceleration and linear acceleration via SPI.
  • Support for sensor's internal integration of angle and velocity.
  • Support for utilizing the Burst Read functionality to poll data in bulk.
  • Ability to adjust integration period.
  • Calibration function for the gyroscope.
  • Provides conversion constants to convert data to human-readable units.

Sensor Documentation

Full datasheet is available online here.

Example Code

Example for basic data polling:

#include <mbed.h>
#include <ADIS16467.h>

int main() {
	Serial pc(USBTX, USBRX);

	//Create IMU, passing in all parameters
	//All pins here are arbitrary, you will need to configure them accordingly
	ADIS16467 imu(&pc, PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_ADIS_CS, PIN_ADIS_RST);

	//Initialize the IMU
	imu.initADIS();

	while(1) {
		wait_ms(600);

		float gyroX = (float)(imu.readGyroX()) * imu.GYRO_CONV;
		float gyroY = (float)(imu.readGyroY()) * imu.GYRO_CONV;
		float gyroZ = (float)(imu.readGyroZ()) * imu.GYRO_CONV;
		float accelX = (float)(imu.readAccelX()) * imu.ACCEL_CONV;
		float accelY = (float)(imu.readAccelY()) * imu.ACCEL_CONV;
		float accelZ = (float)(imu.readAccelZ()) * imu.ACCEL_CONV;
		float intTemp = (float)(imu.readInternalTemp()) * imu.TEMP_CONV;
		uint16_t dataCount = imu.readDataCounter();

		pc.printf("Gyro X : %.2f degree/sec\r\n", gyroX);
		pc.printf("Gyro Y : %.2f degree/sec\r\n", gyroY);
		pc.printf("Gyro Z : %.2f degree/sec\r\n", gyroZ);
		pc.printf("Accel X : %.2f mg\r\n", accelX);
		pc.printf("Accel Y : %.2f mg\r\n", accelY);
		pc.printf("Accel Z : %.2f mg\r\n", accelZ);
		pc.printf("Internal Temperature : %.2f C\r\n", intTemp);
		pc.printf("Data Counter : %5d\r\n", dataCount);
		pc.printf("\r\n");
	}

	return 0;
}

Example for utilizing burst read function:

#include <mbed.h>
#include <ADIS16467.h>

int main() {
	Serial pc(USBTX, USBRX);

	//Create IMU, passing in all parameters
	//All pins here are arbitrary, you will need to configure them accordingly
	ADIS16467 imu(&pc, PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_ADIS_CS, PIN_ADIS_RST);

	//Initialize the IMU
	imu.initADIS();

	struct ADIS16467::BurstReadResult result;
	imu.burstRead(result);

	pc.printf("Gyro X : %.2f degree/sec\r\n", ((float)result.gyroX * imu.GYRO_CONV));
	pc.printf("Gyro Y : %.2f degree/sec\r\n", ((float)result.gyroY * imu.GYRO_CONV));
	pc.printf("Gyro Z : %.2f degree/sec\r\n", ((float)result.gyroZ * imu.GYRO_CONV));
	pc.printf("Accel X : %.2f mg\r\n", ((float)result.accelX * imu.ACCEL_CONV));
	pc.printf("Accel Y : %.2f mg\r\n", ((float)result.accelY * imu.ACCEL_CONV));
	pc.printf("Accel Z : %.2f mg\r\n", ((float)result.accelZ * imu.ACCEL_CONV));
	pc.printf("Internal Temperature : %.2f C\r\n", ((float)result.internalTemp * imu.TEMP_CONV));
	pc.printf("Data Counter : %5d\r\n", result.dataCounter);
	pc.printf("Checksum Value : %5d\r\n", result.checkSum);

	return 0;
}

Polling Rate and Integration

By default, the ADIS produces samples according to its own 2000Hz internal clock. Normally, this would mean that you have to poll it at 2000Hz in order to avoid missing any data! If you think that's a bit too fast for your processor, you're not alone. The developers added the extremely useful "decimation rate" feature to remedy this problem. By setting a decimation rate, the 2000Hz samples are decimated to produce averaged samples at a slower polling rate. For example, if you set a decimation rate of 5, acceleration and gyro readings will update at 400Hz. This is much better than simply reading the 2000Hz data at 400Hz because if you did, sudden events that actually lasted one sample (0.5ms) or less will appear to have lasted five samples (2.5ms). For the delta velocity and angle measurements, the sensor will integrate the acceleration and gyro samples for you on the device. So, using a high decimation rate / slow polling rate would still perform the integration at 2000Hz without losing any accuracy.

This driver makes setting the polling rate pretty simple: just call the setPollRate() function with the polling rate you want in hertz (the sensor supports 1Hz-2000Hz). The driver will then auto-calculate the correct decimation rate value and set it.

If you are making use of the integrated angle and velocity, then setting the correct polling rate is critical. The driver must be updated at least once a polling period (via readDeltaAngles()) so that it can read the previous polling period's delta values off of the ADIS. If readDeltaAngles() isn't called fast enough, you will lose data! The driver will detect this and print an error message if it happens. Note that there is no harm in calling readDeltaAngles() multiple times per polling period, it simply won't do anything.

Here's an example for how to set the polling rate and read delta angles:

Example for polling rate and delta angles:

#include <mbed.h>
#include <ADIS16467.h>

int main() {
	Serial pc(USBTX, USBRX);

	//Create IMU, passing in all parameters
	//All pins here are arbitrary, you will need to configure them accordingly
	ADIS16467 imu(&pc, PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_ADIS_CS, PIN_ADIS_RST);

	//Initialize the IMU
	imu.initADIS();

	const float print_time = 1.0f;
	const uint16_t pollRate = 50; // hz
 
	imu.setPollRate(pollRate);

	// reset delta angles to zero and start waiting for the next delta angle update
	imu.resetDeltaAngle();
 
	Timer printTimer;
	 printTimer.start();
 
	while(1)
	{
 		// only check for updates a few times per polling period
		wait(1/ static_cast<float>(pollRate * 2));
 		
		// read new delta angles off the chip if there are any
		imu.updateDeltaAngles();
 
  		if(printTimer.read() > print_time)
  		{
   			printTimer.reset();
 
			// Read delta angles
			// This is the total angle that the IMU has rotate since the test was started.
			float deltaAngXSum = (float)(imu.getDeltaAngleXSum()) * imu.DELTA_ANGLE_CONV;
			float deltaAngYSum = (float)(imu.getDeltaAngleYSum()) * imu.DELTA_ANGLE_CONV;
			float deltaAngZSum = (float)(imu.getDeltaAngleZSum()) * imu.DELTA_ANGLE_CONV;

			pc.printf("Delta Angle X Sum: %.2f degree\r\n", deltaAngXSum);
			pc.printf("Delta Angle Y Sum: %.2f degree\r\n", deltaAngYSum);
			pc.printf("Delta Angle Z Sum: %.2f degree\r\n", deltaAngZSum);
		}
 
	}
	return 0;
}

If you want more, a comprehensive, ready-to-run set of examples is available on my ADIS16467-Tests repository.

Download repository: zip gz

Files at revision 0:73d3025fc18b

Name Size Actions
[up]
ADIS16467.cpp 28371 Revisions Annotate
ADIS16467.h 3646 Revisions Annotate