Decoding Binary input

Hi guys, I have two microcontrollers. They are connected through standard tx/rx. Micro1 is sending a binary string to Micro2 which contains pitch, roll and yaw information. I want to decode this information on the other side but am having trouble. the code for the sending side is as follows.

//  This section outputs a binary data message
      //  Conforms to new binary message standard (12/31/09)
      byte IMU_buffer[20];
      int tempint;
      int ck;
      uint8_t tempuint;
      long templong;
      byte IMU_ck_a=0;
      byte IMU_ck_b=0;
      Serial.print("DIYd");  // This is the message preamble
      IMU_buffer[0]=0x06;
      ck=6;
      IMU_buffer[1] = 0x02;      

      tempint=ToDeg(roll)*100;  //Roll (degrees) * 100 in 2 bytes
      IMU_buffer[2]=tempint&0xff;
      IMU_buffer[3]=(tempint>>8)&0xff;
      
      tempint=ToDeg(pitch)*100;   //Pitch (degrees) * 100 in 2 bytes
      IMU_buffer[4]=tempint&0xff;
      IMU_buffer[5]=(tempint>>8)&0xff;
      
      tempint=ToDeg(yaw)*100;  //Yaw (degrees) * 100 in 2 bytes
      IMU_buffer[6]=tempint&0xff;
      IMU_buffer[7]=(tempint>>8)&0xff;
      
      for (int i=0;i<ck+2;i++) Serial.print (IMU_buffer[i]);  
      for (int i=0;i<ck+2;i++) {
          IMU_ck_a+=IMU_buffer[i];  //Calculates checksums
          IMU_ck_b+=IMU_ck_a;       
      }
      Serial.print(IMU_ck_a);
      Serial.print(IMU_ck_b);

I have written some code for the recieving side to rejoin the bytes but I am getting garbage out. Figured I must be doing something really stupid and would appreciate it if someone can point out the error in what I am doing. My code is as follows.

char buffer[100];
float pitch = 0.0;
float roll = 0.0;
float yaw = 0.0;
unsigned int newData = 0;
byte IMU_ck_a=0;
byte IMU_ck_b=0;

uint16_t temp;
      
void setup()
{
  Serial.begin(57600);

}

void loop()
{
  if(Serial.available() > 0)
  {
    buffer[0] = Serial.read();
    if(buffer[0] == 'D')
    {
      buffer[1] = Serial.read();
      buffer[2] = Serial.read();
      buffer[3] = Serial.read();
      if(buffer[3] == 'd') newData = 1;
      else newData = 0;
    }
    
    if(newData == 1)
    {
      buffer[0] = Serial.read(); //Message Length
      buffer[1] = Serial.read(); //Message ID
      buffer[2] = Serial.read(); //Roll (byte 1)
      buffer[3] = Serial.read(); //Roll (byte 2)
      buffer[4] = Serial.read(); //Pitch
      buffer[5] = Serial.read(); //Pitch
      buffer[6] = Serial.read(); //Yaw
      buffer[7] = Serial.read(); //Yaw
      buffer[8] = Serial.read(); //IMU_ck_a
      buffer[9] = Serial.read(); //IMU_ck_b
    }
    //Serial.println();
          for (int i=0;i<8;i++) {
          IMU_ck_a+=buffer[i];  //Calculates checksums
          IMU_ck_b+=IMU_ck_a; 
          //Serial.println(buffer[i],BIN);
          }
    //Serial.println();
      if (IMU_ck_a == buffer[8] && IMU_ck_b == buffer[9]) //Passed the Checksum
      {
        temp = (buffer[7]<<8);
        temp |= buffer[6];
        roll = temp/100;
        
        Serial.println(roll);
        Serial.println();
        //Serial.print(buffer[8],BIN);
        //Serial.println(buffer[9],BIN);
        
      }
    
  


  }
}

I realise that I am only trying to decode the roll in this code. I will add all the other information later as it should be exactly the same. Thanks in advance guys!!

p.s All baud rates and that obvious stuff are correct, I am sure its just that I dont have a good enough understanding of bitwise opperations.

You shouldn't call Serial.read() unless you've confirmed that there's data in the buffer with Serial.available(): if you don't, it may bite you by returning -1.

I believe I have used serial.available() there???

Is the baud rate the same on both sides?

I believe I have used serial.available() there???

Yes, just the once, but then read four characters, three of which might not have arrived yet.

What if you've received a 'D'?

if(Serial.available() > 0)
  {
    buffer[0] = Serial.read();
    if(buffer[0] == 'D')
    {
      buffer[1] = Serial.read();
      buffer[2] = Serial.read();
      buffer[3] = Serial.read();
      if(buffer[3] == 'd') newData = 1;
      else newData = 0;
    }

buffer[1], [2] and [3] could all be -1.

ok, I see. Thanks for pointing that out. I will change it and try it again tomorrow.

Hi guys, Im still having trouble. I fixed that Serial.available() bug people mentioned but Im still not getting the correct values. Here is my new code.

char buffer[100];
float pitch = 0.0;
float roll = 0.0;
float yaw = 0.0;
unsigned int newData = 0;


uint16_t temp;
      
void setup()
{
  Serial.begin(57600);

}

void loop()
{
  byte IMU_ck_a=0;
  byte IMU_ck_b=0;
  int i = 0;
  newData = 0;
  if(Serial.available() > 0)
  {
    wait_for_bytes(1);
    buffer[0] = Serial.read();
    if(buffer[0] == 'D')
    {
      wait_for_bytes(3);
      buffer[1] = Serial.read();
      buffer[2] = Serial.read();
      buffer[3] = Serial.read();
    }
    else
    {
     newData = 0;
    }
    
    if(buffer[1] == 'I')
    {
      if(buffer[2] == 'Y')
      {
        if(buffer[3] =='d')
        {
          newData = 1;
          wait_for_bytes(10);
          buffer[4] = Serial.read(); //Message Length
          buffer[5] = Serial.read(); //Message ID
          buffer[6] = Serial.read(); //Roll
          buffer[7] = Serial.read(); //Roll
          buffer[8] = Serial.read(); //Pitch
          buffer[9] = Serial.read(); //Pitch
          buffer[10] = Serial.read(); //Yaw
          buffer[11] = Serial.read(); //Yaw
          buffer[12] = Serial.read(); //ck_a
          buffer[13] = Serial.read(); //ck_b
        }
      }
    }
  }

  
      //Serial.println();
      if(newData == 1)
      {
            for (i=4;i<=11;i++) {
            IMU_ck_a+=buffer[i];  //Calculates checksums
            IMU_ck_b+=IMU_ck_a; 
            //Serial.println(buffer[i],BIN);
            }
            //Serial.println();
    
        if (IMU_ck_a == buffer[12] && IMU_ck_b == buffer[13]) //Passed the Checksum
        {
          
         
          temp = ((buffer[7]<<8)&0xff);
          temp |= ((buffer[6]>>8) &0xff) ;
          roll = temp/100;
        
          Serial.println(roll);
          Serial.println();
          //Serial.print(buffer[8],BIN);
          //Serial.println(buffer[9],BIN);
        
        }
      }
  
  
}

void wait_for_bytes(byte number)
{
  while(Serial.available() <= number);
}

Thanks in advance.

while(Serial.available() <= number);

should be

while(Serial.available() < number);

Dunno whether that's the cause of your problem (hint: how 'bout telling us what you are getting instead of the correct values?), but it's definitely a bug.

Hi there. Im kind of new to Arduino, and started to work on quadrotor project. Is this the code to get pitch / roll / yaw values from ardu imu via serial ports (tx rx) ? I see the values on Imu test demos, and tryin to get x,y,z values from imu but i couldnt get the correct values. Any suggestions ?