Parsing two values sent from Xbee

Hi I´m trying to parse two similar values that are recieved via XBee.

From the sending side the relevant code look like this:

double temp = thermocouple.readCelsius();
Serial1.print("a");
Serial1.print(temp);
Serial1.print("b");
Serial1.print(encoderValue);
delay(100)

On the reciever it looks like this:

void loop() {
  
  if (stringComplete) {
    lcd.clear();    
    lcd.setCursor(0,0);
    lcd.println("Set: ");
    lcd.println(inputString1);
    lcd.setCursor(0,1); 
    lcd.println("Is: ");
    lcd.println(inputString2);
    
    delay(100);
    // clear the string:
    inputString1 = "";
    inputString2 = "";
    stringComplete = false;
   
  }
}

while (Serial.available()) {
        inChar = (char)Serial.read();     
        if(inChar == 'b'){
          inChar = (char)Serial.read(); 
            while(inChar != 'a'){
              inputString1 += inChar;
              inChar = (char)Serial.read();     
    
            }   
         inputString1 += '\0'; //adding null to the end of the string to prevent errors
         stringComplete1=true; 
         }
         
         else {
         stringComplete1=false;
         }

Is this parsing correct? Will it catch whatever is after b but before a?

I have an issue when displaying the inputString1 on an LCD display. It just briefly shows the correct values and then goes on to show white rectangles. See video:
[
- YouTube ... e=youtu.be](- YouTube ...)

(I orginally posted the question here: Thermocouple Amplifier MAX31855 - Connect via Adafruit XBEE adapter ? - Page 2 - adafruit industries and I got alot of help but it seems like he is away or something :slight_smile: )

Lot easier to use Serial.readBytesUntil(character, buffer, length)
Details are available in the reference.

Hi

Thanks for the suggestion.

I have tried to use the serial.readBytesUntil but the issue is that sometimes it only reads the 2 in 23 and sometimes it also reads the 23n or 23a and other similar stuff. I reset the buffer in the main loop when I have printed what was in the buffer.

What could be wrong?

incomingByte = Serial.read();
   if(incomingByte == 'a'){  //check where I am in the stream
     
     Serial.readBytesUntil('b', buffer, 3);

       
stringComplete1 = true;     
    }

Sender (both sent values are integers with 1 to 3 digits):

Serial1.print('a');
Serial1.print(temp2);
Serial1.print('b');
Serial1.print(encoderValue);
Serial1.print('n');

Sending a start of packet marker, a value, a delimiter, and an end of packet marker makes it much easier to read two values in one packet:

.

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where it says "Process the packet", use strtok() to extract the two tokens and atoi() to convert each to an int.

What PaulS said is definitely the -definitive- way of doing this. :slight_smile:

Looks like your communication speed is an issue here. In this case, read() or readBytesUntil() are not blocking calls until they get what you want. If the serial buffer doesn't have enough data they will just return.
Just to verify it, you can check and print the return value of read() or readBytesUntil() in either version of your code. In read() you must be getting a -1.

Hi

I went with PaulS excellent solution and it works great with no lag (and I understand how it works :slight_smile: )! Thanks a million!!! But...

If I display the inData directly on the lcd there is no lag (I have a remote rotary encoder so I feel slightest lag) but if I split the inData and convert it to integers I notice some lag... Can I do anything about it?

Futhermore if I look at the inData there are no errors whatsoever. But when I add my string "splitter" (strtok) there are ocassional errors (there are more digits than it supposed to). Why is that?

Reciever:

    temp = strtok(inData,",");
    re = strtok(NULL,",");
    temp1 = atoi(temp);
    re1 = atoi(re);

    lcd.setCursor(0,0);
    lcd.print("Set: ");
    lcd.print(temp1);
    lcd.print("  ");
    lcd.setCursor(0,1);
    lcd.print("Is: ");
    lcd.print(re1);
    lcd.print("  ");

Sender:

Serial1.print('<');
Serial1.print(temp2);
Serial1.print(',');
Serial1.print(encoderValue2);
Serial1.print('>');

but if I split the inData and convert it to integers I notice some lag... Can I do anything about it?

Converting from string to int takes time. Converting from int to string takes time. If the idea is to just display the strings on the LCD, don't convert from string to int to string.

Ok.

Even though I dont touch the rotary encoder sometimes the values jump (goes from 44 to 0 or to some high random number) for one cycle... What do you think is the likely cause for that? The Xbee are close togheter (wireless link induces errors??)

wireless link induces errors?

No.

Even though I dont touch the rotary encoder sometimes the values jump

What values? You have names in the code. Use them!

Is this happening on the sender or the receiver?

Have you changed any code, on either end? Post all of the code for each end.

Sorry for not being clear.

I found out that it was alot of lcd.print() functions that made it laggy. Removed some of them and got it much faster (no lag).

I also changed the output on the LCD a bit and now it works as I want (no strange values, no lag etc). Maybe the lagginess caused the errors..?

I wanted the temp value to be shown until the rotary encoder is turned then the rotary encoder value should linger on the screen for 2s after it was last turned and then revert back to showing the temperature.

If anyone else find this helpful here is the complete code:

/*************************************************** 
  This is an example for the Adafruit Thermocouple Sensor w/MAX31855K

  Designed specifically to work with the Adafruit Thermocouple Sensor
  ----> https://www.adafruit.com/products/269

  These displays use SPI to communicate, 3 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/



#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>

#define SOP '<'
#define EOP '>'

boolean started = false;
boolean ended = false;
unsigned long timenew;
unsigned long timeold;

char inData[80];
byte index;

    char *temp, *re ;
    int temp1, re1, reold;
    int relay= 13;

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();


void setup() {

    
  Serial.begin(9600); 
  pinMode(relay, OUTPUT);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  

}

void loop() {
  
   // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
    }
  

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
        temp = strtok(inData,",");
        re = strtok(NULL,",");
        temp1 = atoi(temp);
        re1 = atoi(re);
   
  timenew = millis(); 
  
if(timenew-timeold < 2000){
  lcd.setCursor(0,0);  
  lcd.print(re1);
  lcd.print("    ");
}

else if(re1 == reold){
  lcd.setCursor(0,0);
  lcd.print(temp1);
    lcd.print("    ");
}

if(re1 != reold){
  timeold=millis();
  lcd.setCursor(0,0);
  lcd.print(re1);
    lcd.print("    ");
}

   if(temp1 < re1){
     analogWrite(relay, 255);   // turns on the relay
     
   }
    if(re1 < temp1){
      analogWrite(relay, 0);    // turns off the relay
 }
 reold = re1;


    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

I also changed the output on the LCD a bit and now it works as I want (no strange values, no lag etc).

Excellent. Thanks for letting us know.