Converting data received through serial

Hello,

i have a problem receiving data and converting it to something useful for me.

I'm receiving data via softwareSerial from a peripheral that look like this: "W+00005+0000718FF" the layout stays the same, the data is variable. I only need the "00005" part of the input.

when i use the code below i can show it on my serial monitor:

  //Read input value from serial port and setpoint value through SerialMonitor 
if (serial_port.available()) {
    input_value = serial_port.parseInt();
 
    Serial.print("input_value:  ");
    Serial.println(input_value);

Via this code im getting the data like this:
image

Then im trying the code like below and i don't get any data anymore at all.
i have pretty limited knowledge, so i don't know why it isn't working.

  //Read input value from serial port and setpoint value through SerialMonitor 
if (serial_port.available()) {
    String input_string = serial_port.readString();
    String input_value = input_string.substring(2, 7); // starts at index 2 and ends at index 7
  //input_value.toInt();
    Serial.print("Input value: ");
    Serial.println(input_value);
}

could you share the delay of the replay format particularly the if it has start and end markers.

As for splitting the received string, something like this would work IMHO:

void setup(void) {
char *token;
char *mystring = "W+00005+0000718FF";
const char *delimiter ="+";
uint8_t i=0;

   Serial.begin(115200);

   token = strtok(mystring, delimiter);

   while (token != NULL) {
      if(i++ == 1){
        Serial.print(token);
        Serial.print(" if convert to integer will be ");
        Serial.println(strtoul (token, NULL, 0)); //convert string to unsigned long value
      }
      else {
        Serial.println(token);
      }
      
      token=strtok(NULL, delimiter);
   }

}

void loop(void) {

}

Output:

W
00005 if convert to integer will be 5
0000718FF

of course you would need to have completed reception of the WHOLE string before splitting it! :wink:

hope that helps...

The serial input basics tutorial shows how to read and parse serial data. Example #5 uses the strtok() function (like in the post of @sherzaad) to parse the data.

if the information always starts with "W+" you could use sscanf() which checks for a valid conversion, e.g.

void setup() {
  Serial.begin(115200);
  char text[] = "W+00005+0000718FF";
  int input_value = 0;
  if (sscanf(text, "W+%d", &input_value) == 1) {  // converted one int?
    Serial.print("input_value:  ");
    Serial.println(input_value);
  }
}

void loop() {}

when run the serial monitor displays

input_value:  5

It will make it a lot easier if you post the datasheet / communication protocol / user manual of the periheral.

One of the unknowns is if there is an endmarker (e.g. <CR> (0x0D) and/or <LF> (0x0A)) or if the amount of data after the 'W' is fixed or variable.

You should synchronise your reading of the data on the 'W' (assuming that that is fixed). You can look at Robin's tutorial mentioned above (the example with the startmarker and the endmarker) to see how you can do that; the below is another approach

void loop()
{
  // we assume a fixed length message
  static char buffer[17+1];
  static uint8_t idx;
  bool hasStartmarker = false;
  int ch = serial_port.read();
  if(ch == -1)
  {
    // nothing received so nothing to do
    return;
  }

  if(ch == 'W')
  {
    // got start marker
    Serial.print(F("Got start marker at "));
    Serial.print(millis());
    Serial.println(F(" milliseconds"));

    // indicate that we have start marker and can store in buffer
    hasStartmarker = true;
    // clear the buffer
    memset(buffer,'\0',sizeof(buffer));
  }

  // if we have a start marker, store the start marker or the data following it.
  if(hasStartMarker == true)
  {
    // add to buffer
    buffer[idx++] = ch;
  }

  // if we have all bytes
  if(idx == sizeof(buffer) -1)
  {
    Serial.print(F("received message = [");
    Serial.print(buffer);
    Serial.println(F("]");

    hasStartmarker = false;
    idx = 0;

    Serial.println(F("Process your message here before leaving loop()"));
    
  }
}

Not compiled but shoukd give you the idea.

Hi,
To facilitate our help, post your complete code.
I think you are having a delay in reading your softserial data.
What speed did you set for it? 9600?
I've tested your code here using the default serial at 115200 and it works correctly.
" Untitled project - Wokwi Arduino and ESP32 Simulator "

Enter the value W+00005+0000718FF in the input and see the result.

SoftwareSerial will not work on 115200 baud :smiley:

Hi,
thanks for the alert.
yes, I know that softserial is limited, but I used this speed to test if the problem was with the code.
I'm going to switch to 9600.
Tks.
Ok, it worked also with 9600.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.