Go Down

Topic: Parsing Strings in Arduino (Read 3852 times) previous topic - next topic

Bicycler

I am trying to modify a sketch to read a serial string and parse the data disply the values using two integers, zone & warn. An example of the string that will be coming into the arduino would be A001002, where 001 would be the zone and 002 would be the alarm. The sketch runs ok if I send the just 001002, but it does not work correctly if I use the A or F. Any ideas what I'm doing wrong? I want to read the data using the A or F delimiter to distinguish a correct data string. The code I'm using is.
Code: [Select]
// this program decodes a zone/alarm string sent via remote located PLC
// control
// the result is two integer variables that hold the current zone &    
// priority alarm.
// the zone/alarm string is in the following format:
// A000000 or F000000
// where the first three characters are the zone and the second three
// characters are the priority alarm
//
// by Rob Faludi modified by bsr
// http://www.faludi.com



int zone;
int alarm;
int warn;

void setup() {
  // start up the serial connection with 9600-8-n-1-true (non-inverted):
 Serial.begin(9600); // start hardware serial process
  // blink the status LED
  //blinkLED(ledPin, 2, 200);
 for (int thisPin = 2; thisPin < 7; thisPin++) {
       pinMode(thisPin, OUTPUT);
     }

 }


void loop() {
 Serial.flush(); // clear the serial buffer before reading new data
 char alarmString[7]; // create a string to hold the alarm value when it's read
 memset(alarmString,'\0',7); // initialize that string to all NULL characters
 boolean alarmStringValid = false; // declare and initialize a variable to track whether the string has all valid characters
 
 byte inByte = '\0'; // declare and initialize a byte to read in serial data
 while(inByte = 0); {
   inByte = Serial.read(); // read data and wait for an A or F character
 }
 
 Serial.println("starting..."); // show startup on the debug port
 Serial.println("GET");
 
 if (inByte == 'A'||'F'  ) { // if we got the correct start character
       while(Serial.available() < 6) ; {
     //wait for enough data to be available (6 characters of alarm
      //string), while doing nothing else
   alarmStringValid = true; // declare and initialize a variable to track whether the string has all valid characters  
   }
   if (alarmStringValid = true);
   for (int i=0; i < 6; i++) {
     alarmString[i] = Serial.read(); // read each time string character into a character array
     if(alarmString[i] < '0' || alarmString[i] > '9') {
       alarmStringValid = false;  // if any character is bad then the //whole string is bad
     }
     }
   Serial.println();  // do a linefeed on the debug port  
   Serial.print("Alarm: ");
   Serial.println(alarmString);
 }

 if (alarmStringValid == true)
 {
   char zoneString[4];  // create a string to hold the zone part of the string
   memset(zoneString,'\0',4); // initialize that string to all NULL //characters
   strncpy( zoneString, alarmString, 3); // copy the first three //characters of alarmString into the zone string
   zone = atoi(zoneString); // convert ASCII zone string to integer and //store in the zone integer variable
   Serial.print("Zone: ");
   Serial.println(zone, DEC);

   char warnString[4]; // create a string to hold the warning part of the //string
   memset(warnString,'\0',4); // initialize that string to all NULL //characters
   strncpy( warnString, alarmString+3, 3); // skip three characters, then //copy the next two of alarmString into the warn string
   warn = atoi(warnString);  // convert ASCII warn string to integer and store in the warn integer variable
   Serial.print("Warn: ");
   Serial.println(warn, DEC);
   
}

 Serial.println(""); // print a blank line
 
}  


PaulS

#1
Jan 16, 2011, 08:50 pm Last Edit: Jan 16, 2011, 08:51 pm by PaulS Reason: 1
Code: [Select]
 if (inByte == 'A'||'F'  ) { // if we got the correct start character
This should be
Code: [Select]
 if (inByte == 'A'||inByte == 'F'  ) {
There are no shortcuts like you are trying to take.

Code: [Select]
while(Serial.available() < 6) [glow];[/glow] {
     //wait for enough data to be available (6 characters of alarm
      //string), while doing nothing else
   alarmStringValid = true; // declare and initialize a variable to track whether the string has all valid characters  
   }

The block of code in the braces is execute only when  there is enough serial data. If should not start on the same line as the while statement, and does not need to be in curly braces. Either that or the semicolon does not need to be there. It seems more likely that the block belongs on a new line, and need not be a block.

Code: [Select]
   if (alarmStringValid = true)[glow];[/glow]
If alarmStringValid, do nothing. Why bother? The = should be ==, too.

Bicycler

I made the following changes to the sketch, but it still doesn't recognize the A or F.
Code: [Select]
if (inByte == 'A'||inByte =='F');
    // if we got the correct start character
   while(Serial.available() < 6)
   {
     //wait for enough data to be available (6 characters of alarm
      //string), while doing nothing else
   alarmStringValid = true; // declare and initialize a variable to track whether the string has all valid characters  
   }
   if (alarmStringValid = true)
   for (int i=0; i < 6; i++) {
     alarmString[i] = Serial.read(); // read each time string character into a character array
     if(alarmString[i] < '0' || alarmString[i] > '9') {
     alarmStringValid = false;  // if any character is bad then the //whole string is bad
     }

PaulS

Code: [Select]
 Serial.flush(); // clear the serial buffer before reading new data

Unless you REALLY now what you are doing, DO NOT DO THIS.
Code: [Select]
 while(inByte [glow]=[/glow] 0)[glow];[/glow] {

Go Up