Go Down

Topic: Parsing numbers from a serial input (Read 158 times) previous topic - next topic

phenyl

Apr 17, 2019, 09:56 pm Last Edit: Apr 17, 2019, 10:05 pm by phenyl
Hi,
I am trying to parse some ADC values that I am getting from a device via Serial1 (here simulated by an array in the header). As we have devices with different numbers of ADC, I would like to generalize my solution a bit, but I am banging my head against the different functions (strtoll seems useful...)
So at the moment I "hardcoded" the concatenation, but I am sure that there has to be a neat version based on starting position and number of bytes
Code: [Select]
uint8_t counter = 4 * nSensor;
    for (byte i = 3; i < (4 + counter); i++)


in order to generallize this mess:
Code: [Select]

  valueshex[0] = ((uint32_t)receivedBytes[3] << 24) | ((uint32_t)receivedBytes[4] << 16) | ((uint32_t)receivedBytes[5] << 8) | ((uint32_t)receivedBytes[6]);
    valueshex[1] = ((uint32_t)receivedBytes[7] << 24) | ((uint32_t)receivedBytes[8] << 16) | ((uint32_t)receivedBytes[9] << 8) | ((uint32_t)receivedBytes[10]);
    valueshex[2] = ((uint32_t)receivedBytes[11] << 24) | ((uint32_t)receivedBytes[12] << 16) | ((uint32_t)receivedBytes[13] << 8) | ((uint32_t)receivedBytes[14]);
    valueshex[3] = ((uint32_t)receivedBytes[15] << 24) | ((uint32_t)receivedBytes[16] << 16) | ((uint32_t)receivedBytes[17] << 8) | ((uint32_t)receivedBytes[18]);


I would be grateful for any help to replace that with something neat XtoY and some for{..} loops.

Follows a code that simulates a test case which I verified working:

Code: [Select]


// Example 6 - Receiving binary data
// heavily modified from http://forum.arduino.cc/index.php?topic=396450


const byte numBytes = 32;
byte receivedBytes[numBytes] = {0x31, 0x30, 0x30, 0x00, 0x81, 0x2D, 0x15, 0x00, 0x76, 0x5C, 0xB8, 0x00, 0x70, 0xDB, 0xE3, 0x00, 0x70, 0x64, 0x35};
byte numReceived = 19;

//byte receivedBytes[numBytes];
//byte numReceived = 0;

uint8_t nSensor = 4;


byte messageRaw[] = {0x02, 0x30, 0x30, 0x30, 0x03};

uint32_t valueshex[] = {0, 0, 0, 0};

float voltage[] = {0.0, 0.0, 0.0, 0.0};

boolean newData = false;

void setup() {
  Serial.begin(57600);
  Serial1.begin(57600);
  while (!Serial) {}
  Serial.println("<Arduino is ready>");

  // Serial1.write(messageRaw, sizeof(messageRaw));
  fakeNewData();

}

void loop() {
  // recvBytesWithStartEndMarkers();
  showNewData();
}
/*
  void recvBytesWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  byte startMarker = 0x02;
  byte endMarker = 0x03;
  byte rb;


  while (Serial1.available() > 0 && newData == false) {
    rb = Serial1.read();

    if (recvInProgress == true) {
      if (rb != endMarker) {
        receivedBytes[ndx] = rb;
        ndx++;
        if (ndx >= numBytes) {
          ndx = numBytes - 1;
        }
      }
      else {
        receivedBytes[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        numReceived = ndx;  // save the number for use when printing
        ndx = 0;
        newData = true;
      }
    }

    else if (rb == startMarker) {
      recvInProgress = true;
    }
  }
  }
*/

void fakeNewData() {
  newData = true;
  // receivedBytes =
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in (HEX values)... ");
    for (byte n = 0; n < numReceived; n++) {
      Serial.print(receivedBytes[n], HEX);
      Serial.print(' ');
    }
    Serial.println();
    for (byte n = 0; n < numReceived; n++) {
      Serial.write(receivedBytes[n]);
      Serial.print(' ');
    }
    Serial.println();
    uint8_t counter = 4 * nSensor;
    for (byte i = 3; i < (4 + counter); i++)
    {
      Serial.print(receivedBytes[i], HEX);

    }
    Serial.println();
    valueshex[0] = ((uint32_t)receivedBytes[3] << 24) | ((uint32_t)receivedBytes[4] << 16) | ((uint32_t)receivedBytes[5] << 8) | ((uint32_t)receivedBytes[6]);
    valueshex[1] = ((uint32_t)receivedBytes[7] << 24) | ((uint32_t)receivedBytes[8] << 16) | ((uint32_t)receivedBytes[9] << 8) | ((uint32_t)receivedBytes[10]);
    valueshex[2] = ((uint32_t)receivedBytes[11] << 24) | ((uint32_t)receivedBytes[12] << 16) | ((uint32_t)receivedBytes[13] << 8) | ((uint32_t)receivedBytes[14]);
    valueshex[3] = ((uint32_t)receivedBytes[15] << 24) | ((uint32_t)receivedBytes[16] << 16) | ((uint32_t)receivedBytes[17] << 8) | ((uint32_t)receivedBytes[18]);

    Serial.println(receivedBytes[3], HEX);
    Serial.println(receivedBytes[4], HEX);
    Serial.println(receivedBytes[5], HEX);
    Serial.println(receivedBytes[6], HEX);
    Serial.print("Val0 ");
    Serial.println(valueshex[0]);
    Serial.print("Val1 ");
    Serial.println(valueshex[1]);
    Serial.print("Val2 ");
    Serial.println(valueshex[2]);
    Serial.print("Val3 ");
    Serial.println(valueshex[3]);

    Serial.println();
    newData = false;

    for (uint8_t i = 0; i < 4; i++)
    {
      voltage[i] = (((float)(valueshex[i]) / (16777216)) * 1856) - 928;
      Serial.println(voltage[i]);
    }


  }
}



The example should output:
Code: [Select]

<Arduino is ready>
This just in (HEX values)... 31 30 30 0 81 2D 15 0 76 5C B8 0 70 DB E3 0 70 64 35
 //one line of ASCII garbage//
0812D150765CB8070DBE307064350
0
81
2D
15
Val0 8465685
Val1 7756984
Val2 7396323
Val3 7365685

8.53
-69.87
-109.77
-113.16

phenyl

I have managed to put the hardcoded calculations in a loop, generalizing it, so I can change the number of sensors. However, I still think there would be an even easier way?

Code: [Select]

    for (byte i = 0; i < nSensor; i++)
    {
      valueshex[i] = 0;
      for (uint8_t j = 0; j < 4; j++)
      {
        valueshex[i] = valueshex[i] | (((uint32_t)receivedBytes[3 + (i * 4) + j]) << (24 - (8 * j)));
      }
    }

knightridar

Hi, Robin2's guide on parsing serial data was really usefull for me.
Serial Input Basics - Parsing Data

I was not using an array.
I used software serial to wirelessly transfer 4 analog values to another arduino by parsing the serial data:

Please see post #32 for transmitter and receiver code:
HC-12 TRANSMITTER TO HC-12 RECEIVER, CONVERT ANALOG VALUES BACK TO INTEGER

Hopefully it may be of help.
Useful CAD/ 3D model files for
Arduino, hobbyist, and engineering projects

https://grabcad.com/has-2

Robin2

#3
Apr 18, 2019, 09:38 am Last Edit: Apr 18, 2019, 09:39 am by Robin2
The example should output:
And what does it actually output?

Maybe you have the bytes for a multi-byte value in the wrong order?

If you create a struct with the proper datatypes then you can copy the array of received bytes directly into the struct and then just access the values in the struct. Something like (I may not have the syntax exactly correct)
Code: [Select]
memcpy(&structInstance, &receivedBytes, sizeof(structInstance))

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PaulS

Quote
However, I still think there would be an even easier way?
Is that a question or a statement?

If it is a question, how do you expect us to know what you think?

If it is a statement, why did you use a question mark?
The art of getting good answers lies in asking good questions.

Go Up