I use this code constantly. It basically packages serial data for strtok_r to split into pieces paced on predefined deliminators. Each bit of data is separated by a “,” and the end of the set of data is a “.”
If you send in a string like:
1 |
10,50,100. |
You can split it into three varaibles that equate to those different values. In this case:
1 |
int x = atoi(subStr(serialbuf, ",", 1)) |
The Variable x would equate to 10.
Here’s the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
const char EOPmarker = '.'; //This is the end of packet marker char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming. #include <SoftwareSerial.h> #include <string.h> // we'll need this for subString #define MAX_STRING_LEN 20 // like 3 lines above, change as needed. SoftwareSerial SoftSer(11, 10); // RX, TX void setup(){ Serial.begin(9600); SoftSer.begin(9600); } void loop() { if (SoftSer.available() > 0) { //makes sure something is ready to be read static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read char inchar = SoftSer.read(); //assigns one byte (as serial.read()'s only input one byte at a time if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read. } else { //once the end of package marker has been read serialbuf[bufpos] = 0; //restart the buff bufpos = 0; //restart the position of the buff /* THIS IS WHERE THE CODE HAPPENS */ } } } char* subStr (char* input_string, char *separator, int segment_number) { char *act, *sub, *ptr; static char copy[MAX_STRING_LEN]; int i; strcpy(copy, input_string); for (i = 1, act = copy; i <= segment_number; i++, act = NULL) { sub = strtok_r(act, separator, &ptr); if (sub == NULL) break; } return sub; } |
Here’s an example.
Say you have a serial device hooked up to your softserial port and in inputs “10,50,100.” to the arduino to be split up. If you want to set each of these numbers to separate integers and then print them to the serial console, you’d do it like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
const char EOPmarker = '.'; //This is the end of packet marker char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming. #include <SoftwareSerial.h> #include <string.h> // we'll need this for subString #define MAX_STRING_LEN 20 // like 3 lines above, change as needed. SoftwareSerial SoftSer(11, 10); // RX, TX void setup(){ Serial.begin(9600); SoftSer.begin(9600); } void loop() { if (SoftSer.available() > 0) { //makes sure something is ready to be read static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read char inchar = SoftSer.read(); //assigns one byte (as serial.read()'s only input one byte at a time if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read. } else { //once the end of package marker has been read serialbuf[bufpos] = 0; //restart the buff bufpos = 0; //restart the position of the buff int x = atoi(subStr(serialbuf, ",", 1)); int y = atoi(subStr(serialbuf, ",", 2)); int z = atoi(subStr(serialbuf, ",", 3)); Serial.print("The first number, x is: "); Serial.print(x); Serial.print(" - The second number, y is: "); Serial.print(y); Serial.print(" - The third number, z is: "); Serial.print(z); Serial.println(); } } } char* subStr (char* input_string, char *separator, int segment_number) { char *act, *sub, *ptr; static char copy[MAX_STRING_LEN]; int i; strcpy(copy, input_string); for (i = 1, act = copy; i <= segment_number; i++, act = NULL) { sub = strtok_r(act, separator, &ptr); if (sub == NULL) break; } return sub; } |
hi sir,
sir i have a problem i try your code the and my data coming from serial port is in decimal how do i edit your code so that i can read the whole decimal form of the data that arduino reads
thank
Hi!
Yeah, unfortunately this doesn’t work with sending decimals back and forth. Could you try changing up your data? Sending the integer part and the decimal part separately?
Devon
Hi,
thank you very much for this great “subStr”function 🙂
i am new in arduino programming so a am sorry for this silly question, but if i get something like that 180 0 0 90 90 180, wherе for end i have space how i need to form my code???
Hi, you should use a different terminator character