Hi all, code below which may help someone. This has calibration, default calibration and heading ability.
This CMPS11 IMU in Tasmania has up to +-6 degrees heading error at 30 degree tilt, +-9 degrees at 45 degree tilt, at worst heading, unusual in that it is on approx Easterly heading.
Very good stationary repeat ability <= +- 0.4 degrees.
Very good around the compass rose linearity at worst 6 degrees error (using IMU's 0 degrees as being North).
Above results were with Manual Calibration, which gave slightly better results than the default bias(by 1-2 degrees less tilt error, linearity was about the same).
IMHO this is an over priced IMU for its tilt error performance but has the advantage of having on board fusion, the Adafruit NXP Precision does a better job (tilt error) for the price, but it suffers from a stationary heading (not very stationary) movement of up to +-2 degree.
Regards Kevin
Code: Select all/*
* CMPS11 I2C example for Arduino *
* By James Henderson, 2014 *
*
* Calibration, Manual and Default *
* By Duckman1961, 2017 *
*
* Heading,Caliibration (manual or default) All need to be either commented or uncommented out to operate (ONLY 1 can be uncommented to operate at any time), then load to board
* Manual Calibration time period to do movements can be altere at line 97
* Video on how to cal, https://www.youtube.com/watch?v=gB3Tt1eQQLQ
*
*/
#include <Wire.h>
#define CMPS11_ADDRESS 0x60 // Address of CMPS11 shifted right one bit for arduino wire library
#define ANGLE_8 1 // Register to read 8bit angle from
unsigned char high_byte, low_byte, angle8;
char pitch, roll;
unsigned int angle16;
void setup(){
Wire.begin();
Serial.begin(9600);
// calibrate();//Uncomment this line to do own calibration, uncomment only 1
//default_calibrate();// Uncomment this line to reset IMU back to default cal data, uncomment only 1
}
void loop()
{
Heading_loop();// Comment out to do either Cal modes, uncomment to display heading, uncomment only 1
}
void Heading_loop() //Below gives heading data in Serial Monitor, uncomment in loop() to use
{
Wire.beginTransmission(CMPS11_ADDRESS); //starts communication with CMPS11
Wire.write(ANGLE_8); //Sends the register we wish to start reading from
Wire.endTransmission();
// Request 5 bytes from the CMPS11
// this will give us the 8 bit bearing,
// both bytes of the 16 bit bearing, pitch and roll
Wire.requestFrom(CMPS11_ADDRESS, 5);
while(Wire.available() < 5); // Wait for all bytes to come back
angle8 = Wire.read(); // Read back the 5 bytes
high_byte = Wire.read();
low_byte = Wire.read();
pitch = Wire.read();
roll = Wire.read();
angle16 = high_byte; // Calculate 16 bit angle
angle16 <<= 8;
angle16 += low_byte;
Serial.print("roll: "); // Display roll data
Serial.print(roll, DEC);
Serial.print(" pitch: "); // Display pitch data
Serial.print(pitch, DEC);
Serial.print(" YAW: "); // Display 16 bit angle with decimal place
Serial.print(angle16 / 10, DEC);
Serial.print(".");
Serial.println(angle16 % 10, DEC);
delay(100); // Short delay before next loop,(100) 10hz update
}
void calibrate()//Below used to do manual mag/accel calibration, uncomment in setup to use
{
Serial.println(" Calibration Mode ");
delay(2000); //2 second before starting
Serial.println(" Start ");
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0xF0);
Wire.endTransmission();
delay(25);
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0xF5);
Wire.endTransmission();
delay(25);
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0xF6);
Wire.endTransmission();
delay(180000);//(ms)Alter this to allow enough time for you to calibrate Mag and Accel
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0xF8);
Wire.endTransmission();
Serial.println(" done ");
}
void default_calibrate()//Below resets factory default cailbration, to use uncomment in setup loop
{
Serial.println(" Default Calibration Mode ");
delay(2000); //2 second before starting
Serial.println("Start");
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0x6A);
Wire.endTransmission();
delay(25);
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0x7C);
Wire.endTransmission();
delay(25);
Wire.beginTransmission(CMPS11_ADDRESS);
Wire.write(0); //command register
Wire.write(0xb1);
Wire.endTransmission();
Serial.println("done");
}