2

The serial port on my Arduino Mega is receiving 3 floats as bytes (total of 12 bytes, 4 per float) over serial. Unfortunately I cannot assemble the 4 Bytes in a float, as the serial monitor only displays

0.00

0.00

0.00 etc.

Here is the code:

void serialEvent2() {
  if (Serial2.available() > 11) {
    byte yawData[3];
    yawData[0] = Serial2.read();
    yawData[1] = Serial2.read();
    yawData[2] = Serial2.read();
    yawData[3] = Serial2.read();
    float yawAngle = *((float*)(yawData));
    Serial.println(yawAngle);

    byte pitchData[3];
    pitchData[0] = Serial2.read();
    pitchData[1] = Serial2.read();
    pitchData[2] = Serial2.read();
    pitchData[3] = Serial2.read();
    float pitchAngle = *((float*)(pitchData));

    byte rollData[3];
    rollData[0] = Serial2.read();
    rollData[1] = Serial2.read();
    rollData[2] = Serial2.read();
    rollData[3] = Serial2.read();
    float rollAngle = *((float*)(rollData));
  }
}

I made sure the data coming to Serial2 is not 0.

UPDATE: The initial mistake was my byte array not being sized correctly. I fixed it. The values I print are fine until after about a second, they get totally weird. Dropped bits/Bytes maybe? Seems odd because a sample sketch written in Processing works perfectly while taking the exact same input.

enter image description here

10
  • Your byte array is 3 bytes length, while you're assuming it's 4 bytes !
    – Ikbel
    Nov 11, 2015 at 14:51
  • @KiraSan Thanks for the hint! Made an edit because of a new problem... Maybe you know some more magic tricks? ;)
    – Dario
    Nov 11, 2015 at 23:31
  • Did you try the code in my answer? maybe you should inverse the bytes order to get the correct values.
    – Ikbel
    Nov 11, 2015 at 23:46
  • @KiraSan Yep, tried it, gives me not a single correct reading :/
    – Dario
    Nov 12, 2015 at 7:21
  • I have edited my answer since that time. please check it out.
    – Ikbel
    Nov 12, 2015 at 7:22

4 Answers 4

3

I tried the code below and it worked for me, don't miss the delay() part:

Sender Code:

void setup() {
  Serial.begin(9600);
}

void loop() {
    float yaw = 10.5;
    float pitch = 20.15;
    float roll = 100.10;
    float ypr[3];  
    ypr[0] = yaw;
    ypr[1] = pitch;
    ypr[2] = roll;
    Serial.write((byte*) ypr, 12);  // No new-line
    delay(1000);

}

Receiver Code:

void setup() {
  Serial.begin(9600);
}

void loop() {

}

void serialEvent() {
    if (Serial.available() == 12){
      byte yawData[4];
      yawData[0] = Serial.read();
      yawData[1] = Serial.read();
      yawData[2] = Serial.read();
      yawData[3] = Serial.read();
      float yawAngle = *((float*)(yawData));
      Serial.println(yawAngle);

      yawData[0] = Serial.read();
      yawData[1] = Serial.read();
      yawData[2] = Serial.read();
      yawData[3] = Serial.read();
      float yawPitch = *((float*)(yawData));
      Serial.println(yawPitch);

      yawData[0] = Serial.read();
      yawData[1] = Serial.read();
      yawData[2] = Serial.read();
      yawData[3] = Serial.read();
      float yawRoll = *((float*)(yawData));
      Serial.println(yawRoll);
    }
}

Results:

enter image description here

2

If you must do it that way I'd recommend using a union:

typedef union {
    float val;
    uint8_t bytes[4];
} floatval;

floatval v;
v.bytes[0] = Serial2.read();
v.bytes[1] = Serial2.read();
v.bytes[2] = Serial2.read();
v.bytes[3] = Serial2.read();
Serial.println(v.val);

A better solution is to just write and read the raw float data:

// Sender:
Serial.write((const char *)&myfloat, sizeof(float));

// Receiver
Serial2.readBytes((char *)&myfloat, sizeof(float));

Even better still is to define a struct which is the packet of data you wish to send:

typedef struct {
    float yaw;
    float pitch;
    float roll;
} attitude;

attitude myatt;
myatt.yaw = 14.9;
myatt.pitch = 23.4;
myatt.roll = 11.49;

Serial.write((const char *)&myatt, sizeof(attitude));

// receive:

attitude myatt;
Serial2.readBytes((char *)&myatt, sizeof(attitude));
Serial.println(myatt.yaw);
Serial.println(myatt.pitch);
Serial.println(myatt.roll);
2
  • First of all, thanks! I tried the method with a struct and it works for about a second until the data seems to be corrupted. Maybe a few bits are being dropped from time to time? How can I prevent this?
    – Dario
    Nov 11, 2015 at 18:48
  • For that you need to construct a proper packet. I have a good library that can help. Google "Arduino ICSC"
    – Majenko
    Nov 11, 2015 at 21:42
0

try use memcpy, i think it might work:

void serialEvent2() {
  if (Serial2.available() > 11) {
    byte yawData[4];
    float yawAngle = 0;
    yawData[0] = Serial2.read();
    yawData[1] = Serial2.read();
    yawData[2] = Serial2.read();
    yawData[3] = Serial2.read();
    memcpy(&yawAngle, &yawData,sizeof(float));
    Serial.println(yawAngle);

    // same for others ...
  }
}
0

What if you write

yawData[3] = Serial2.read();
yawData[2] = Serial2.read();
yawData[1] = Serial2.read();
yawData[0] = Serial2.read();

i.e. you change the endianness of the representation

1
  • I already told him about it, but it turned out that it's not the problem, by looking at the sender's code, the bytes are in the same order as expected by the reader code.
    – Ikbel
    Nov 12, 2015 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.