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

  • Your byte array is 3 bytes length, while you're assuming it's 4 bytes ! – Ikbel Nov 11 '15 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 '15 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 '15 at 23:46
  • @KiraSan Yep, tried it, gives me not a single correct reading :/ – Dario Nov 12 '15 at 7:21
  • I have edited my answer since that time. please check it out. – Ikbel Nov 12 '15 at 7:22
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

| improve this answer | |
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);
| improve this answer | |
  • 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 '15 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 '15 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 ...
  }
}
| improve this answer | |
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

| improve this answer | |
  • 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 '15 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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