Splitting an string coming from Serial

Hi everyone,

I don't know how to split a string to get the different values from it. I'm receiving data signal from Serial, something like : C322
I have 4 LED (A,B,C,D) and 255 PWM values for each one and I want to know which LED is the one that has to change its value.

int message = 0;     //  This will hold one byte of the serial message
int PinBlue = 11; 
int PinRed = 10;
int PinYellow = 9;
int pingNumber = 0;
int value;

void setup() {  
  Serial.begin(9600);  
}
void loop(){
    pingNumber = 0;
    if (Serial.available() > 0) { 
                while (Serial.available()){ 
                        message = Serial.read();
                        //Now it has to split somehow...
                }
    }
}

Hope that someone can help me :slight_smile:

thanks

So if I'm understanding correctly, you want the string

a100b200c0d255

to set LED A to 100
B to 200
C Off (0)
D On (255)

I found this sketch a while ago (I didn't write it):

int val=0;
int tempval=0;
char axis;
int xval=0;
int newx=0;
int yval=0;
int newy=0;
int zval=0;
int newz=0;

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

void loop()
{
  newx=xval;
  newy=yval;
  newz=zval;

  while(Serial.available() > 0)
  {
    tempval=Serial.read();
    if (tempval=='x' || tempval == 'X')    {
      axis='x';
      val=0;
    }
    else if (tempval=='y' || tempval == 'Y')    {
      axis='y';
      val=0;
    }
    else if (tempval=='z' || tempval == 'Z')    {
      axis='z';
      val=0;
    }
    else if (tempval >='0' && tempval <= '9')    {
      val=val * 10;
      val=val + (tempval - '0');
      delay(5);

      if (axis=='x'){
        xval=val;
      }
      else if (axis=='y'){
        yval=val;
      }
      else if (axis=='z'){
        zval=val;
      }
    }
    else    {
     delay(5);
    }
  } 
 
  if (xval!=newx && yval!=newy && zval!=newz) {
  Serial.print(" x is: ");
  Serial.println(xval);
  Serial.print(" y is: ");
  Serial.println(yval);
  Serial.print(" z is: ");
  Serial.println(zval);
  }

}

If you upload it and open the serial monitor, then type in, for example, x100y200z300 it should say x is 100, y is 200 and so on. You can adapt that to fit your needs.

Good Luck!

Uhm.. your specification is a bit vauge, and I dont wnat to explain the wrong answer :~

I understand we are getting an intensity value between 0 and ? which is given on the Serial as a 4 character string (without a terminator?). You define red/green/blue pins and say you have 4 LEDs? No, I dont get it. Please give a list of examples of what commands to interpret and what LED should light up.

Otherwise to continue your code example, the first byte you recieve is the letter A..D byte, so you store that in a char LEDchar variable (not message) and then you read more bytes converting '0'..'9' to the integer value. When you have the value, you do

switch (LEDchar) {
case 'A' : analogWrite(pinBlue,value) ; break ;
case 'B' : analogWrite(pinRED,value) ; break ;
  :
}

See reference switch case

Ok sorry if I didn't explain myself good.

I've got 3 sliders in processing. Each one has to be link with one led in a range between 0 and 250.
Processing code:

void draw() {
  int value = int((fader[numfader]*1000)/4); // This is to get the value from 0 to 250 from each fader.
 
  if (numfader==1) { 
  arduinoPort.write('b'+value); // Send via serial.....

  }
    if (numfader==2) {
  arduinoPort.write("v"+value);
  }
    if (numfader==3) {
  arduinoPort.write("g"+value);
  }

Then in arduino code: I need to split up the string and get which is the value of the led that I have to increase o decrease the PWM output.

I tried with Baum user sketch but I don't know why it doesn't get the values at real time. I just made a test with the blue led. The code is that:

int pinBlue = 11;
int val=0;
int message=0;
char led;
int ledBlue=0;
int newledBlue=0;

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

void loop()
{
  newledBlue=ledBlue;

  while(Serial.available() > 0) {
    message=Serial.read();
    if (message=='b') {
      led='b';
      val=0;
    } else if (message >='0' && message <= '9')    {
      val=val * 10;
      val=val + (message - '0');
      delay(5);

      if (led=='b'){
        ledBlue=val;
        analogWrite (pinBlue,ledBlue);
      }
    
    } 
  } 
}

I hope that now I've explained myself better.

Why didn't it work?

I've got perfect data signal coming out from processing. ( I can see it in the processing debugger). But then the LED is doing weird things. I don't know why.

Now forget the LED. have the arduino print the 3 values from processing in the serial monitor.

But then the LED is doing weird things

"weird" to me means it is speaking Tibetan, or counting up in base e.

What does it mean to you?

I have 3 sliders and need to vary them with processing. You will never vary the sliders at the same time so there will always be a separate signal for each slider.
For example:
b124
g12
g13
g14
v203
v202
v201

I mean with weird that the LED is not doing what the processing signal is sending.

[Cough]

Try this:

Now forget the LED. have the arduino print the 3 values from processing in the serial monitor.

I can't print anything in the Arduino Serial monitor when the processing serial is running.

I can't print anything in the Arduino Serial monitor when the processing serial is running

Time to simplify things.

You may make things easier by providing a delimiter at the end of each slider transmission. You could capture each slider string and evaluate the contents for what to do. Below is some test code you can experment with using the serial monitor. Also, in your processing code, only send out values if the value has changed from the previous value sent.

// zoomkat 10-29-10 simple delimited ',' string parce 
// from serial port input (via serial monitor)
// and print result out serial port
// CR/LF could also be a delimiter
// for IDE 0019 and later

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial-delimit-21"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
  while (Serial.available()) {
    delay(1);  //small delay to allow input buffer to fill

    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      break; //breaks out of capture loop at ,
    }  
    readString += c; //makes the string readString
  }   

  if (readString.length() >0) {
    Serial.println(readString); //prints string to serial port out
    // do other stuff with string here

    readString=""; //clears variable for new input
  }
}

This is going to sound weird again. Now I tried to work only with a the value of 1 led

Processing code:

void draw() {
arduino.Write(value)
}

Arduino code:

int message;
int pinBlue = 11;
void setup()  {
      serial.Begin (9600);
}
void loop() {
     if (Serial.available() > 0) {
             message = Serial.Read();
             analogWrite (pinBlue,message);
      }
}

Like this works perfectly!!!!! But I can only control one LED :(.

Any idea of why is happening this?

Any idea of why is happening this?

Why is what happening? You send one value. You read one value, and set the PWM level for one LED, and

Like this works perfectly!!!!!

What is the problem?

Ahh.. your mixing up sending it as an ASCII and sending a binary byte.

The last attempt the Write(Value) sends a single byte with something between 0 and 255. This you pick up in the Arduino with the Read, and that fits nicely directly into the analogWrite.

In your earlier Processing you wrote arduinoPort.write("v"+value); - the Processing makes this into a string of several bytes, writing the value in decimal-ASCII like "A23" (which is what you wanted, but so far have been unable to decode at the receiving end)

I suggest you decide on a two byte format. Your Processing does two Arduinowrite; "A", "B" ... for which LED and then, the last bit that worked fine, Write(value).

Your Arduino does two (2) Serial.Read (each waiting for available() ). The first gets the letter A, B ... the second the value.
Then your code decides which LED and sends the value.

There is the potential problem that if you miss a byte somewhere the code will be out of synch (ie reading the wrong byte into the variables) at which point you have to press the reset button so it starts properly again. There are ways around that (using a defined synch/terminator character) but maybe much later.

Hi MSquare, your idea sounds good, but I tried and it doesn´t work (maybe because I don´t know how to do it)

My processing code is:

void draw () {
   int value = int((fader[n)umfader]*1000)/4); // this is to get the value for each slider and convert it from float to int.
   switch (numfader) {
       case 1 : // slider blue
             arduino.write('b');
             arduino.write(value);
             break;
       case 2 :  //slider red
             arduino.write('v');
             arduino.write(value);
             break;
       case 3 : //slider yellow
             arduino.write('g');
             arduino.write(value);
             break;
      }
}

And on arduino I have:

int messageNumber = 0;
int messageValue =0;
int ledNumber;
void setup () {
     Serial.begin (9600);
}
void loop () {
    if (Serial.available() > 0) {
        messageNumber = Serial.read();
          switch (messageNumber) {
               case 'b' :
                    ledNumber = 11;
                    break;
               case 'v' :
                    ledNumber = 10;
                    break;
               case 'v' :
                    ledNumber = 9;
                    break;  
        }
    }
    if (Serial.available() > 0) {
        messageValue = Serial.read();
        analogWrite(ledNumber,messageValue);
   }
}

When the program starts all the LEDs are off. Then when I press the first slider the correct led lights but it doesn't do the fading. And it happens the same with the other LEDs.

int((fader[n)umfader]*1000)/4);

?

Take a look at your "loop" code.
What happens if after reading the first character, there is no second character available yet?

int value = int ((fader[numfader]*1000)/4);

I've got the values inside a float array. But I can't send floats to arduino.write().I have to multiply per 1000 because I don't want to lose the values (the float goes from 0 to 1) and then divide the result by 4 to get a value between 0 and 250. And after this I convert the float to an integer.

int value = int ((fader[numfader]*1000)/4);

That's not what you posted first time.