Reading Serial data into variables

Hi Everyone,

Total noob, my first post as I just started playing with Arduino.

Basically, I have a python script that sends a string to the Arduino over serial, for example:

1000=1
1000=2
1000=3
1000=4
.. and so on

So .. how do I take what is both sides of the "=" and put them into separate variables for example (name and value), so that I can do something like this :

if name = 1000 && value =1 {
then blah
}

thanks !

This assumes that you store your data in a null-terminated character string. You can use strtok or strchr.

Example for strchr; strtok might be cleaner.

// space for max 4 characters
char valA[5];
// space for one character
char valB[2];

// clear variables
memset(valA, 0, sizeof(valA));
memset(valB, 0, sizeof(valB));

char *ptr;

// find equal sign
ptr = strchr(buffer, '=');
if(ptr == null)
{
  // equal sign not found
}
else
{
  // place null character at position of equal sign; result is a shorter character string
  *ptr = '\0';
  // check size of first value
  if(strlen(buffer) > sizeof(valA) - 1)
  {
    // error; result will not fit
  }
  else
  {
    // copy to valA
    strcpy(valA, buffer);
    // increment pointer so it points to character after
    ptr++;
    // check size of second value
    if(strlen(ptr) > sizeof(valB) - 1)
    {
      // error; result will not fit
    }
    else
    {
      strcpy(valB, ptr);
    }
  }
}

Note that the above as well as strtok() will destroy your input data.

Other references
strcpy
memset

PS: not tested

There are different ways to capture the data and extract what is needed. Below is an example that looks for delimiters in the captured data ( , comma) and extracts what is between them. The data string has an * as the end of data marker.

//zoomkat 11-12-13 String capture and parsing  
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data 

String readString; //main captured String 
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
      
      Serial.println();
      Serial.print("captured String is : "); 
      Serial.println(readString); //prints string to serial port out
      
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle); 
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
      
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Below is an example that looks for delimiters in the captured data ( , comma) and extracts what is between them. The data string has an newline character as the end of data marker.
It uses roughly half the program memory of Zoomkat’s example above and less RAM, and completely avoids the use of the String class.

const int MAX_LEN = 80;
const char lineEnding = '\n'; // whatever marks the end of your input.
char inputSentence [MAX_LEN + 1];
int inputIndex;
bool newInput;

const byte MAX_TOKENS = 4;
const char* delimiters = ", "; // whatever characters delimit your input string
char* tokens [MAX_TOKENS + 1];
enum indexName {angle, fuel, speed, altitude};
#define PRINT_ITEM(x) printItem (x, #x)

void setup ()
{
  Serial.begin (115200);
}

void loop ()
{
  while (Serial.available() )
  {
    char readChar = Serial.read ();
    if (readChar == lineEnding)
    {
      newInput = true;
    }
    else
    {
      if (inputIndex < MAX_LEN)
      {
        inputSentence [inputIndex++] = readChar;
        inputSentence [inputIndex] = '\0';
      }
    }
  }

  if (newInput && strlen (inputSentence))
  {
    int tokenIndex = 0;
    Serial.println (inputSentence); // tell 'em what you've got
    tokens [tokenIndex] = strtok (inputSentence, delimiters);
    while ((tokenIndex < MAX_TOKENS - 1) && tokens [tokenIndex])
    {
      tokenIndex++;
      tokens [tokenIndex] = strtok (NULL, delimiters);
    }

    PRINT_ITEM (angle);
    PRINT_ITEM (fuel);
    PRINT_ITEM (speed);
    PRINT_ITEM (altitude);

    // reset things for the next lot.
    newInput = false;
    inputIndex = 0;
    inputSentence [0] = '\0';
  }
}

void printItem (int index, char* name)
{
  Serial.print (name);
  Serial.print (F(" "));
  Serial.println (tokens [index]);
}

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example which separates data based on the COMMA character. It would be easy to convert it to use the EQUALS character.

...R

wow .. thanks guys, will look at these. sorry for the late reply, but I didn't get any email to say someone replied to my topic. thanks again !

m0ng00se:
I didn't get any email to say someone replied to my topic. thanks again !

Much more effective just to check the Forum a couple of times a day.

...R

[quote author=AWOL link=msg=2515146 date=1449735549]
const int MAX_LEN = 80;
const char lineEnding = '\n'; // whatever marks the end of your input.
char inputSentence [MAX_LEN + 1];
int inputIndex;
bool newInput;

const byte MAX_TOKENS = 4;
const char* delimiters = ", "; // whatever characters delimit your input string
char* tokens [MAX_TOKENS + 1];
enum indexName {angle, fuel, speed, altitude};
#define PRINT_ITEM(x) printItem (x, #x)

void setup ()
{
  Serial.begin (115200);
}

void loop ()
{
  while (Serial.available() )
  {
    char readChar = Serial.read ();
    if (readChar == lineEnding)
    {
      newInput = true;
    }
    else
    {
      if (inputIndex < MAX_LEN)
      {
        inputSentence [inputIndex++] = readChar;
        inputSentence [inputIndex] = '\0';
      }
    }
  }

  if (newInput && strlen (inputSentence))
  {
    int tokenIndex = 0;
    Serial.println (inputSentence); // tell 'em what you've got
    tokens [tokenIndex] = strtok (inputSentence, delimiters);
    while ((tokenIndex < MAX_TOKENS - 1) && tokens [tokenIndex])
    {
      tokenIndex++;
      tokens [tokenIndex] = strtok (NULL, delimiters);
    }

    PRINT_ITEM (angle);
    PRINT_ITEM (fuel);
    PRINT_ITEM (speed);
    PRINT_ITEM (altitude);

    // reset things for the next lot.
    newInput = false;
    inputIndex = 0;
    inputSentence [0] = '\0';
  }
}

void printItem (int index, char* name)
{
  Serial.print (name);
  Serial.print (F(" "));
  Serial.println (tokens [index]);
}

[/quote]

Sorry for digging on old topic, but I want to ask what is the use of MAX_LEN, MAX_LEN+1, and MAX_TOKENS +1? Is it for the array or something? Then, what is the #x on #define PRINT_ITEM(x) printItem (x, #x)? And how it’s work (if can, schematically)? Sorry if you find this question to be silly, but I am a newbie here. Thank you.

I want to ask what is the use of MAX_LEN

MAX_LEN defines the number of characters that you want to store in the array. The +1 in the array definition adds 1, so there is room for the terminating NULL.

Then, what is the #x on #define PRINT_ITEM(x) printItem (x, #x)?

You should be able to look at where the PRINT_ITEM term is used, and the printItem() function, and determine that for yourself.