Arduino Forum

Using Arduino => Programming Questions => Topic started by: phenyl on Apr 17, 2019, 09:56 pm

Title: Parsing numbers from a serial input
Post by: phenyl on Apr 17, 2019, 09:56 pm
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
Title: Re: Parsing numbers from a serial input
Post by: phenyl on Apr 18, 2019, 08:54 am
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)));
      }
    }
Title: Re: Parsing numbers from a serial input
Post by: knightridar on Apr 18, 2019, 09:25 am
Hi, Robin2's guide on parsing serial data was really usefull for me.
Serial Input Basics - Parsing Data (http://forum.arduino.cc/index.php?topic=396450)

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 (https://forum.arduino.cc/index.php?topic=495822.msg3407839#msg3407839)

Hopefully it may be of help.
Title: Re: Parsing numbers from a serial input
Post by: Robin2 on Apr 18, 2019, 09:38 am
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
Title: Re: Parsing numbers from a serial input
Post by: PaulS on Apr 18, 2019, 12:52 pm
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?