Split Values in a string

Hello forum,

I am working on a project and I am trying to split some values. The code is

#include <SoftwareSerial.h>

SoftwareSerial mySerial(0,1);
String Data = "";

void setup()  
{
    Serial.begin(9600);
    mySerial.begin(9600);
}

void loop() // run over and over
{
    while (mySerial.available() > 0)
    {
        //Serial.println("Something is available");
        char character = mySerial.read(); // Receive a single character from the software serial port
        Data.concat(character); // Add the received character to the receive buffer
        
        if (character == '\n')
        {
            //Serial.print("Received: ");
            Serial.println(Data);

            // Add your code to parse the received line here....

            // Clear receive buffer so we're ready to receive the next line
            Data = "";
        }
    }
}

and I would like to read a a pattern like 123,-34 (Data contains that). Two integers separated with a comma. How can I do that?

thank you in advance :wink:

What indicates that the first integer has started and the second one has finished ?

Do you have control of the format of the data being sent ?

NOTE : There is a difference between a String (an object created by the String library) and a string (a null terminated array of chars). The functions used to manipulate each type are not generally interchangeable.

We are two guys the other one writes code in android and i am receiving data via bluetooth. IT would be ok if i had a working method. I am controlling a robot with two sticks. One for move front and back and one for right and left. The values from the two sticks are separated witha comma. I have control of the format yes and i guess \n indicates that the second integer finished.

Read and apply the principles in Serial Input Basics - Updated

You design / implement the receiver side, the Android person has to follow suite ;)

Best solution is the start / end marker version; if you want to be able to send pure text without being limited by the chosen markers, you can use 0x02 (start of text) for the start marker and 0x03 (end of text) as the end marker.

It would be wasteful to use the String class. The following program uses 2,644 bytes. Try rewriting for use with the String class with fewer bytes. The strtok() function makes it easy to do what you want.

void setup() {
  char msg[] = "123,-34";
  char *ptr;
  int index = 0;
  int vals[2];

  Serial.begin(9600);

  ptr = strtok(msg, ",");
  while (ptr) {
    vals[index] = atoi(ptr);
    Serial.println(vals[index++]);
    ptr = strtok(NULL, ",");
  }
}

void loop() {
}

Thank you for your answers, I will check them out. Do you think that I should read something else? , is ok as a simple stream from my android? I could talk to my android guy and change that. If it is ok then I will only code whats needed. Just verify this please.

thank you

<integer>,<integer> Won’t be good enough because the order of integers may get out of step and you will not know which integer is the first.

Hello,

We have changed the android app. Now, the app sends *,&. eg. *23,-25&

Where the * is the start of the string and the & is the end. I hope this is better. This is what you guys were talking about?

thanks

More or less :wink:

Could have been a little simpler: <integer1,integer2>
‘<’ indicates the start of the message, ‘>’ the end of the message.

I am trying to parse this and get the two numbers as integers…dunno why it is so hard…I have forgotten how to program :frowning:

#include <SoftwareSerial.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

SoftwareSerial mySerial(0,1);

int LeftJoy = 0;    // Left joystick value
int RightJoy = 0;  // Right Joystick value
char *Data;
char *srcString;
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data


int i, stringLength, numb1, numb2;
            
char targetString[7];
int targetPointer = 0;

const char s[2] = ",";
char *token;

            
boolean newData = false;

void setup()  
{
    Serial.begin(9600);
    mySerial.begin(9600);
    delay(2000);
    Serial.println("Arduino is ready to receive...");
}

void loop() {
  
  while (mySerial.available() > 0)
    {
        //Serial.println("Something is available");
        char character = mySerial.read(); // Receive a single character from the software serial port
        strcat(Data, character); // Add the received character to the receive buffer
        
        if (character == '&')
        {
            //Serial.print("Received: ");
            Serial.println(Data);

            // Add your code to parse the received line here....
            
            srcString = Data;
            stringLength = strlen(srcString);
                for(i=0; i<stringLength; i++) {
                  if(srcString[i] != ' ' && srcString[i] != '\t' && srcString[i] != '\n' && srcString[i] != '*') {
                    targetString[targetPointer] = srcString[i];
                    targetPointer++;
                  }
                }
                targetPointer = 0;
                for(i=0; i<stringLength; i++) {
                  targetString[i] = ' ';
                }
            Serial.println("i am here");
            Serial.println(srcString);    
            /* Removing comma and splitting the two numbers */
            token = strtok(targetString, s);
            LeftJoy = atoi(token);
            token = strtok(NULL, s);
            RightJoy = atoi(token);
  
        Serial.print(LeftJoy);
        Serial.print("-");
        Serial.println(RightJoy);
            // Clear receive buffer so we're ready to receive the next line
            Data = "";
        }
    }

    
 
}

could anyone help me out ? :confused:

Use sterretje suggestion to simplify the code. You had a couple of hiccups in the code (e.g., no need for multiple Serial objects, strtok()). See if this will work for your needs:

#include <SoftwareSerial.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//SoftwareSerial mySerial(0, 1);

int LeftJoy = 0;    // Left joystick value
int RightJoy = 0;  // Right Joystick value
char *Data;
char *srcString;
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data


int i, stringLength, numb1, numb2;

char targetString[7];
int targetPointer = 0;

const char s[2] = ",";
char *token;


boolean newData = false;

void setup()
{
  Serial.begin(9600);
  //    mySerial.begin(9600);
  delay(2000);
  Serial.println("Arduino is ready to receive...");
}

void loop() {
  int charsRead;
  while (Serial.available() > 0)
  {
                                             // Using test input data: <123,456>

    charsRead = Serial.readBytesUntil('>', receivedChars, sizeof(receivedChars) - 1); // Read until '>' or 31 chars
    receivedChars[charsRead] = '\0';    // Overwrite '>' to make it a string
    
    token = strtok(receivedChars, s);
    if (token != NULL) {
      LeftJoy = atoi(token + 1);
    }
    token = strtok(NULL, s);
    if (token != NULL) {
      RightJoy = atoi(token);
    }

    Serial.print(LeftJoy);
    Serial.print("-");
    Serial.println(RightJoy);
    // Clear receive buffer so we're ready to receive the next line
    receivedChars[0] = NULL;
  }
}

There are some redundant variables left in the code.

Plenty errors; it does not compile.

First thing that caught my eye

    strcat(Data, character); // Add the received character to the receive buffer

'character' is not a character array so you can't use strcat().

Digging further, 'Data' is a pointer but you never initalise it so it points to NULL. You definitely lost your skills ;)

sterretje: Plenty errors; it does not compile.

My code or his?

@econjack yes it is working, really thank you. I have removed variables that are not necessary. Could anyone tell me why sometimes i don’ t get right values?

as you can see instead of getting 180 i get 0 or 1 or 18 or 10…

any ideas?

thanks

econjack: My code or his?

Sorry, his ;) You should have given me a chance to post first :D So there would not have been confusion ;) Anyway, I doubt that you would have used an non initialised character pointer.

xmarkx: @econjack yes it is working, really thank you. I have removed variables that are not necessary. Could anyone tell me why sometimes i don' t get right values?

... ...

as you can see instead of getting 180 i get 0 or 1 or 18 or 10...

any ideas?

thanks

If you add a Serial.println with full received data before parsing, you can see if it's the Arduino code or the Android code that makes the mistake.

Okey i have done that and its the arduino code. Does anyone have a script that removes whitespaces and * from a string?

My test string does NOT use the whitespace or the *. Read the code carefully and learn from it…don’t just use it, understand it.

EDIT:

Why do you think I put this line in the post:

                                             // Using test input data: <123,456>

xmarkx: Okey i have done that and its the arduino code. Does anyone have a script that removes whitespaces and * from a string?

You don't have spaces in your input.

Hello I have studied the code, I am not just using it my friend. I am trying 2 days now to figure out what is going on. The problem is on strtok as far as the kernel of my operating system concern OR something about the arduino. Maybe I have to add some delay or something like that. It messes up everything.

I would appreciate if anyone could help me out.

/*
* The following sketch reads the stream coming from an android phone via bluetooth at 9600 baud rate.
*/

#include <SoftwareSerial.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const byte numChars = 32;
char receivedChars[numChars];   // Store the received data

char *Rtoken, *Ltoken;

boolean newData = false;

void setup() {
    Serial.begin(9600);
    delay(3000);                
    Serial.println("Arduino is ready to receive...");
}

void loop() {
    int charsRead;
        while (Serial.available() > 0) {

            charsRead = Serial.readBytesUntil('&', receivedChars, sizeof(receivedChars) - 1);
            receivedChars[charsRead] = '\0';

            Serial.print(receivedChars);
            
            /* Grab the first number from the string */
            Rtoken = strtok (receivedChars,"*");
            if (Rtoken != NULL) {
                Serial.print("\tR: ");
                Serial.print(Rtoken);
            }
            
            delay(30);
            
            /* Grab the second number from the string */
            Ltoken = strtok (NULL,",");
            if (Ltoken != NULL) {
                Serial.print(" L: ");
                Serial.println(Ltoken);
            }
            
            // Clear receive buffer so we're ready to receive the next line
            receivedChars[0] = NULL;
            
            delay(50);
        }
}