Processing values from incoming strings and transferring values to variables

First post, going to do my best on clarity.

Doing work on a robotic crawler with very simple functions such as commanding 2 drives with servo commands, and turning on 2 separate lights. There are also 4 sensors onboard.

All the coding for the drives and sensors is finished, however, now I’ve got to send a constant stream of data to a client, and use the arduino as a webserver which will receive commands from a pc. What I’m trying to do is have a constant string be sent to the arduino with various commands, then analyze that string, and place the values into different variables.

I’ve been provided with code that does this however, I can’t quite understand how it achieves it’s task, and it also is built to carry information for several variables, but I believe I only need 4 pieces of information to be sent so I can control: front drive, rear drive, light 1, light 2.

I want the arduino to also send a string to the pc in the same fashion containing the sensor values and battery level.

I’ve done several hours of research, and have looked at just about every string command, but haven’t had much luck on my own.

Okay on to the code, here is an example string provided with the code I was given:

// $PCPO,D,189502.3,M,S,31818.8,M,B,0* ← String to display
($PCPO is a header used to determine beginning of string.)

My thoughts are: is there not a really simple way to accomplish this? I’ve tried working with arrays, and I feel like my knowledge is lacking because I’m not getting the results I’d like, and as I’ve mentioned I can almost figure out how this code works but not quite, I don’t understand how it captures info between commas, and I don’t know how to take info from string and place into my variables.

Here is the code used to process this string:

// ----------------------- PROCESS SERIAL INPUT --------------------------------------

void SerialData(){
  
  int index[10];
//  float rawIn;
  char StrInput[10] = "";
  char HdrStr[6] = "PCPO";


  DataIN[DataCount] = byteIN;	  // If there is serial port data, put in the buffer
  DataCount++;

  if (byteIN == 36){		  // If the received byte is = to 36 ($), beginning of transmission
    DataCount = 0;
    DataIN[0] = byteIN;
  }
 
  if (byteIN == 13){              // End of transmission, start processing 
      
    int HdrCnt = 0;
    int count = 0;
    
    for (int i=0; i<5; i++){          // Check characters of string to verify if the received command starts with $PCPI
      if (DataIN[i] == HdrStr[i]){
      HdrCnt++;      		    //increment a flag for every correct character in the string
      }
    }


    if(HdrCnt == 4){				 // if 4 it is a match, continue and process the data
      for (int j=0; j<40; j++){         // parse the string
        if (DataIN[j] == ','){		         // check for the position of the  "," separators
          index[count] = j;
      	  count++;
        }
        if (DataIN[j]=='*'){		          // ... and the "*"
          index[9]=j;
	  count++;
        }
      }

      strncpy(StrInput,DataIN+index[1]+1,index[2]-index[1]-1);	         //copy the section between the indices to Str1

      StrInput[strlen(StrInput)+1]='\0';				 // add \0 to keep C programming language happy
      meters = atof(StrInput);					
     // meters = rawIn;                                                    // load payout value
      //Serial.println(meters);

      strncpy(StrInput,DataIN+index[4]+1,index[5]-index[4]-1);	         //copy the section between the indices to Str1

      StrInput[strlen(StrInput)+1]='\0';				 // add \0 to keep C programming language happy
      rate = atof(StrInput);					
     // rate = rawIn;       // load payout value
      
           
    }
    
    
    for (int i=0;i<40;i++){	         // Initialize a buffer for received data
      DataIN[i]=' ';
    }
    DataCount = 0;
  //  meters = meters + 1; 
    
  }
}

I’m providing the entire file that contains the string processing named CounterOverlay_v1_2 and my program that I wrote named Crawler_I_O_Webserver. Any help is much greatly appreciated, I’ve tried my best and just can’t get there myself.

Thanks again.

CounterOverlay_v1_2.ino (4.63 KB)

Crawler_I_O_Webserver.ino (8.06 KB)

Read about strtok(). Load an example in, add some print statements until you understand how it works. You can then pull your string apart and use the string conversion utilities (e.g., atoi(), atol(), etc.) to move them into variables.

Thanks a ton for your reply, I'll do what you suggested and hopefully this clarifies things for me. Thanks again. :slight_smile:

Got what I wanted out of strtok, thanks again.

Figured it out at this site : http://jhaskellsblog.blogspot.ca/2011/06/parsing-quick-guide-to-strtok-there-are.html

Here is my code for anyone wondering the same as I was: how to make a simple rudimentary way of reading a string and turning it’s various values into useful information for being fed into variables.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

char instring [] = "$:7, 120, 0, 1";  //input string                                                
char delimiters[] = "$:,";          // characters to skip over
char* valPosition;                // array
int angle[] = {0, 0, 0, 0};          // array to hold integer values after processing


// initializes strtok with our string to tokenize

valPosition = strtok(instring, delimiters);


for (int i= 0; i<4; i++){
  angle[i] = atoi(valPosition);          // place values from string into buffer
  Serial.println(angle[i]);
  
  
  // here we pass null which tells strtok to continue working with the previous string
  valPosition = strtok(NULL, delimiters);
  
}

Serial.println(""); // space between array values and variable values

//-------------------------------Move array values into variables-------------------


 int servo1 = angle[0];
 Serial.print("Servo angle 1: ");
 Serial.println(servo1);
 
 int servo2 = angle[1];
  Serial.print("Servo angle 2: ");
 Serial.println(servo2);
 
 int light1 = angle[2];
 Serial.print(" Light 1 reads binaray 1 or 0: ");
 Serial.println(light1);
 
 int light2 = angle[3];
 Serial.print ("Light 2 reads binary 1 or 0: ");
 Serial.println(light2);
}

// I can put an if statement for lights to check if 0 or 1






void loop() {
  // put your main code here, to run repeatedly:

Hello and welcome,

sscanf is also very useful for doing exactly this.

guix is correct: sscanf() can do the string conversions for you. However, sscanf() is very powerful and can convert just about anything you throw at it. As a result, it can bloat your code quite a bit, especially if you are just doing one type of conversion (e.g., string to int). In most cases, using the ato?() conversions will use less memory.