CMPS11 Calibration

I know it’s been a long time since my last post, but I’ve not had time to do anything with this module.

I have built a frame to check the accuracy of the compass, but It doesn’t want to work properly. When I’m turning the compass to one directon by 90 degree, the sensor show only 20 degree change, then suddenly jumps up to a very high value. It is very annoying. Has anyone had similar problem with their compass or do you guys have any idea what to do?

[<LINK_TEXT text=“http://s10.postimg.org/kkx12zxn9/WP_201 … _Pro_1.jpg”>http://s10.postimg.org/kkx12zxn9/WP_20160330_13_59_44_Pro_1.jpg</LINK_TEXT>](http://postimg.org/image/kkx12zxn9/)

Hi Tomadevil,

the frame is looking really good… but did you make the joints out of metal?

It is a very simple mistake: if there is some metal nearby, the calibration would never work properly.

I have also a CMPS11 it is not very accurate, I will try to calibrate it, but I don’t have a test device to measure the accuracy.

In case you solved your problem, plse reply!

Regards, elviß1

Old thread, but hopefully I can help.

If you are testing as shown in the picture, you are testing the compass upside down. The tilt compensation on the 11 does not go that far.

Your frame is great, but only has two degrees of freedom. If you add a third it will make an awesome tool for getting good calibration.

Ignore the comments about the joints. They will have negligible effect. You can always replace steel with copper or brass, both of which have ~zero magnetic impact.

The compass should be accurate to 2% - that’s 7.2 degrees. Mine only manages 8 degrees, even after calibration.

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

/*
*     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");


}
1 Like