CHR-6dm AHRS IMU to Mega

Hi, I am working much on quadcopters, and need a new IMU unit. I found an amazing one which is not horribly cheap implemented on a Propeller processor:
http://vrhome.net/vassilis/category/quadcopter/

Which got me fired up since I didn't get near those results with Nintendo Wii game controller IMU's.
Here's the link to the particular sensor I've got now (impulse bought it!):

http://www.chrobotics.com/index.php?main_page=product_info&cPath=1&products_id=2

Now my question is, what would be the best way to stream the data out to my Arduino Mega. As known, the Mega's got 4 hardware UART's and 1 I2C bus and 1 SPI bus.

I've read that the 200-500Hz update rates is not working good transferring the original data over UART (3V3 to arduino 5V) because it's too slow, and the code for the CHR device is open source which is really awesome.

Would it be best to also make code that streamed out I2C to the Mega or SPI? Or enhancing the UART communication somehow? I think it should work straight off since it's hardware UART's but apparently not.

Here's a thread about it but seems not so active:
http://www.chrobotics.com/forum/viewtopic.php?f=8&t=8&start=10

Please help. I think this is a LARGE improvement to the community if we could get this good IMU data straight into a REALLY easy interface as Arduino. Imagine flying copters, self balancing wheel bots such as segways and everything else you can imagine. And it does handle real Kalman or DCM really well it seems!!

No one interested? I don't get why, this is the next generation of IMU/AHRS! Got it all!

Only trouble is interfacing, and imagine accessing so great angle and heading estimates so fast yet so easy as with the Arduino's!

I set the unit to below 100Hz in broadcast mode to stream YAW PITCH ROLL and ACCEL_Z, and made this code for an arduino Mega. It sometimes in a specific interval skip over things and get really bad results... But most of the time I get good ones. I have not yet managed to check the checksum...

/*
Honk Super Test of CHR-6DM

It is set to stream YAW, PITCH, ROLL and ACCEL_Z in 100Hz (Broadcast setting 73)
*/

float CHR_yawClean;
float CHR_pitchClean;
float CHR_rollClean;
float CHR_accel_zClean;

#define CHR_MESSAGE_LENGTH 16 //in bytes

//byte 1 contains 's'
//byte 2 contains 'n'
//byte 3 contains 'p'
//byte 4 contains PT, packet type
//byte 5 contains N (the number of data bytes to expect)
//FIRST DATA BYTE IS BYTE NUMBER 6
//byte 6 and 7 contains info about active channels
//byte 8 and 9 contains YAW
//byte 10 and 11 contains PITCH
//byte 12 and 13 contains ROLL
//byte 14 and 15 contains ACCEL_Z
//byte 16 and 17 contains CHK_SUM (N+6/N+7)

#define BYTE1 0
#define BYTE2 1
#define BYTE3 2
#define PT_BYTE 3
#define N_BYTE 4
#define DATA_BYTE1 5
#define DATA_BYTE2 6
#define YAW_BYTE1 7
#define YAW_BYTE2 8
#define PITCH_BYTE1 9
#define PITCH_BYTE2 10
#define ROLL_BYTE1 11
#define ROLL_BYTE2 12
#define ACCEL_Z_BYTE1 13
#define ACCEL_Z_BYTE2 14
#define CHK_BYTE1 15
#define CHK_BYTE2 16

#define CHR_YAW_FACTOR 0.0109863F //from datasheet
#define CHR_PITCH_FACTOR 0.0109863F
#define CHR_ROLL_FACTOR 0.0109863F
#define CHR_ACCEL_Z_FACTOR 0.106812F

//transmission freq. from CHR6DM: 100Hz (73 in the Broadcast setting)

void setup() {
Serial.begin(57600);
Serial1.begin(115200);
}

void loop() {

readCHR6DM();
Serial.print("Yaw: ");
Serial.print(CHR_yawClean);
Serial.print(" Pitch: ");
Serial.print(CHR_pitchClean);
Serial.print(" Roll: ");
Serial.print(CHR_rollClean);
Serial.print(" Acc_Z: ");
Serial.println(CHR_accel_zClean);

delay(350); //unit set to 100Hz continous sending
}

void readCHR6DM() {
int CHR_yawWord, CHR_pitchWord, CHR_rollWord, CHR_accel_zWord;
unsigned int CHR_checksumWord, calculated_checksumWord;
int i, j;
unsigned char buffer[CHR_MESSAGE_LENGTH+2]; //17 bytes
unsigned long sumOfBytes;

//byte 1 contains 's'
//byte 2 contains 'n'
//byte 3 contains 'p'
//byte 4 contains PT, packet type
//byte 5 contains N (the number of data bytes to expect)
//FIRST DATA BYTE IS BYTE NUMBER 6
//byte 6 and 7 contains info about active channels
//byte 8 and 9 contains YAW
//byte 10 and 11 contains PITCH
//byte 12 and 13 contains ROLL
//byte 14 and 15 contains ACCEL_Z
//byte 16 and 17 contains CHK_SUM (N+6/N+7) //N is expected to be 10

if (Serial1.available() > 0) {
startOfRead:
i = 0;
buffer = Serial1.read();
_ if(buffer == 's') { //byte 1 element 0_
* i++;*
_ buffer = Serial1.read();
* //Serial.println(buffer[BYTE1]); //debug*
* }
else { goto startOfRead; }
if(buffer == 'n') { //byte 2 element 1
i++;
buffer = Serial1.read(); //byte 3 element 2
//Serial.println(buffer[BYTE2]); //debug*

* }
else { goto startOfRead; }
if(buffer == 'p') { //byte 3 element 2, begin getting the whole thing because 3 start bytes checked to be valid
i++;
buffer = Serial1.read(); // byte 4 element 3 (PT_BYTE)
//Serial.println(buffer[BYTE3]); //debug
}
else { goto startOfRead; }
if(buffer == 0xB7) { // byte 4 element 3 (PT_BYTE)
i++;_

buffer = Serial1.read(); // byte 5 element 4 (N_BYTE)
//Serial.println(buffer[PT_BYTE], HEX); //debug*

* //Serial.println(buffer[N_BYTE], DEC); //debug this is 10 dec!
_ }
else { goto startOfRead; }
if(buffer == 0x0A) { // byte 5 element 4 (N_BYTE) expect 10 dec checks out!
i++;_

buffer = Serial1.read(); // byte 6 element 5 (DATA_BYTE1)
//Serial.println(buffer[DATA_BYTE1], BIN); //debug this prints 1110000 checks out*

* }*
* else { goto startOfRead; }*
if(buffer == 0xE0) { // byte 6 element 5 (DATA_BYTE1) expect 70 hex this should check out
* i++;*
buffer = Serial1.read(); // byte 7 element 6 (DATA_BYTE2)
* //Serial.println(buffer[DATA_BYTE2], BIN); //debug*
* }*
* else { goto startOfRead; }*
if(buffer == 0x02) { // byte 7 element 6 (DATA_BYTE2) expect 2 hex
* i++;*
buffer = Serial1.read(); //byte 8 element 7 (YAW_BYTE1)
* i++;*
buffer = Serial1.read(); //byte 9 element 8 (YAW_BYTE2)
* i++;*
buffer = Serial1.read(); //byte 10 element 9 (PITCH_BYTE1)
* i++;*
buffer = Serial1.read(); //byte 11 element 10 (PITCH_BYTE2)
* i++;*
buffer = Serial1.read(); //byte 12 element 11 (ROLL_BYTE1)
* i++;*
buffer = Serial1.read(); //byte 13 element 12 (ROLL_BYTE2)
* i++;*
buffer = Serial1.read(); //byte 14 element 13 (ACCEL_Z_BYTE1)
* i++;*
buffer = Serial1.read(); //byte 15 element 14 (ACCEL_Z_BYTE2)
* i++;*
buffer = Serial1.read(); //byte 16 element 15 (CHK_BYTE1)
_ //Serial.println(buffer*, DEC);
i++;
buffer = Serial1.read(); //byte 17 element 16 (CHK_BYTE2)
//Serial.println(buffer, DEC);
}
//else { goto startOfRead; }_

//for(i = 0; i < CHR_MESSAGE_LENGTH; i++){ //we're still at byte 3 element 2, execution gets us to byte 4 element 3*

_ //buffer = Serial1.read(); //first time here i=3 (byte 4), i=4 (byte 5), i=5 (byte 6), i=6, i=7, i=8, i=9, i=10, i=11, i=12, i=13, i=14, i=15, i=16(byte 17), i=17(byte18 nonexistent)
* //}
}
else{ Serial.println("Sensor not connected"); }*_

// sumOfBytes = 0;
// for(i=-1;i<13;i++) { //ska gå element 0 till 14
// sumOfBytes += buffer*;*
// }
*// *
// Serial.print("sumOfBytes: ");
// Serial.print(sumOfBytes, DEC);
*// *
// CHR_checksumWord = (unsigned)buffer[CHK_BYTE1]<<8;
// CHR_checksumWord |= buffer[CHK_BYTE2];
// //CHR_checksumWord = (unsigned long)(buffer[CHK_BYTE1] + buffer[CHK_BYTE2]);

// Serial.print(" CHR_checksumWord: ");
// Serial.println(CHR_checksumWord, DEC);
*// *
* //if( ) {*

* //plMSB = Serial1.read();*
* //plLSB = Serial1.read();*
* //myInt = (int)plMSB<<8; YÄÄÄÄH!*
* //myInt |= plLSB;*

* CHR_yawWord = (int)buffer[YAW_BYTE1]<<8;
CHR_yawWord |= buffer[YAW_BYTE2];*

* CHR_pitchWord = (int)buffer[PITCH_BYTE1]<<8;
CHR_pitchWord |= buffer[PITCH_BYTE2];*

* CHR_rollWord = (int)buffer[ROLL_BYTE1]<<8;
CHR_rollWord |= buffer[ROLL_BYTE2];*

* CHR_accel_zWord = (int)buffer[ACCEL_Z_BYTE1]<<8;
CHR_accel_zWord |= buffer[ACCEL_Z_BYTE2];*

CHR_yawClean = (CHR_yawWord * CHR_YAW_FACTOR);
CHR_pitchClean = (CHR_pitchWord * CHR_PITCH_FACTOR);
CHR_rollClean = (CHR_rollWord * CHR_ROLL_FACTOR);
CHR_accel_zClean = (CHR_accel_zWord * CHR_ACCEL_Z_FACTOR);
* //}*
}

Honk, have you made any progress on this? I am curious how this sensor makes the rest of the control code for the software. I imagine it would simplify it quite a bit.

Has either of you got anywhere with this? Im using an UNO and want to interface the CHR6DM to it to poll for pitch roll values. Im not looking for crazy update rates. If I can do it at 1Hz Ill be happy.

Hey again, Ive tried this code but all I get is 0s from on the serial output. When i plug the 6DM back into the AHRS software it reads fine so I dont think its a hardware problem. I did modifify the code a little but nothing too crazy I dont think. I only modified it because Im using an UNO and only have access to one serial line but since I was just reading from the 6DM i didnt think this would be a problem.

Any ideas?

Sample output

YAW: 0.00 Pitch: 0.00 Roll: 0.00

float CHR_yawClean;
float CHR_pitchClean;
float CHR_rollClean;
//float CHR_AccelZ;

#define CHR_MESSAGE_LENGTH 16
#define BYTE1 0
#define BYTE2 1
#define BYTE3 2
#define PTByte 3
#define NBYTE 4
#define Data_BYTE1 5
#define Data_BYTE2 6
#define YAWBYTE1 7
#define YAWBYTE2 8
#define PITCHBYTE1 9
#define PITCHBYTE2 10
#define ROLLBYTE1 11
#define ROLLBYTE2 12
#define ACCELZBYTE1 13
#define ACCELZBYTE2 14
#define CHKBYTE1 15
#define CHKBYTE2 16

#define YAW_FACT 0.0109863F
#define Pitch_Fact 0.0109863F
#define Roll_Fact 0.0109863F
//#define Z_Fact 0.106812F

void setup()
  {
    Serial.begin(115200);
    
  }
  
void loop(){
  readCHR6DM();
  Serial.print("YAW: ");
  Serial.print(CHR_yawClean);
  Serial.print(" Pitch: ");
  Serial.print(CHR_pitchClean);
  Serial.print(" Roll: ");
  Serial.print(CHR_rollClean);
  Serial.println();
  delay (350);
}


void readCHR6DM(){
  int CHR_yawWord, CHR_pitchWord, CHR_rollWord;
  unsigned int CHR_chkWord, calc_chkWord;
  int i, j;
  unsigned char buffer[CHR_MESSAGE_LENGTH+2]; //17 bytes
  unsigned long sumBytes;
  
  while (Serial.available() >0){
    start:
    i = 0;
      buffer[i] = Serial.read();
      if(buffer[i] == 's'){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if (buffer[i] =='n'){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if (buffer[i] =='p'){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if(buffer[i] == 0xB7){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if(buffer[i] == 0x0A){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if(buffer[i] == 0xE0){
        i++;
        buffer[i] = Serial.read();
      }
      else {goto start;}
      
      if(buffer[i] == 0x02){
        i++;
        buffer[i] = Serial.read();
      
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
        
        i++;
        buffer[i] = Serial.read();
      }
      
      else{Serial.println("Sensor not connected");}
      
      CHR_yawWord = (int)buffer[YAWBYTE1]<<8;
      CHR_yawWord |= buffer[YAWBYTE2];
      
      CHR_pitchWord = (int)buffer[PITCHBYTE1]<<8;
      CHR_pitchWord |= buffer[PITCHBYTE2];
      
      CHR_rollWord = (int)buffer[ROLLBYTE1]<<8;
      CHR_rollWord |= buffer[ROLLBYTE2];
      
      CHR_yawClean = (CHR_yawWord * YAW_FACT);
      CHR_pitchClean = (CHR_pitchWord * Pitch_Fact);
      CHR_rollClean = (CHR_rollWord * Roll_Fact);
  }
}