pulling information out of array and strtok

Hi,
I am sending the following over serial:
c1255:c2124

i am able to split this information up if i send it as
a255:b124

and split the above using

void setLED(char* data) {
 if ((data[0] == 'a') || (data[0] == 'A')) {
                int Ans = strtol(data+1, NULL, 10);
                Ans = constrain(Ans,0,255);
                analogWrite(GreenPin, Ans);
                Serial.print("Green is set to: ");
                Serial.println(Ans);
        }

this will allow me to pull the number that sits in front of ‘a’ so in this case 255, however i really want to be able to send c1255 as opposed to a255 as the data relates to a channel so ‘c1’ would be channel one ‘c2’ channel 2 etc, is there a simple way of telling the code to look for both characters, in my head it would look something like this:

void setLED(char* data) {
 if ((data[0] == 'c') && (data[1] == '1')) {
                int Ans = strtol(data+1, NULL, 10);
                Ans = constrain(Ans,0,255);
                analogWrite(GreenPin, Ans);
                Serial.print("Green is set to: ");
                Serial.println(Ans);
        }

but this doesn’t seem to work.

Hi, sscanf is your friend :wink:

Exemple: C code - 13 lines - codepad

Edit: then you use strcmp to check if s1 equal "c1" or whatever

if (!strcmp(s1, "c1"))
{
    ...
}

Thanks i have seen this floating about but can you please explain what this means

if (sscanf(str,"%2s%d:%2s%d", s1, &n1, s2, &n2) == 4)
  {
    printf("%s=%d\n%s=%d", s1, n1, s2, n2);
  }

mainly this bit

"%2s%d:%2s%d", s1, &n1, s2, &n2) == 4)

seems to make no sense to me, where as my current method makes slightly more sense.

It mean this:

Check for 2 characters (which will be stored in s1), followed by a number (which will be stored in n1), followed by ":", followed by 2 characters (which will be stored in s2), followed by a number (which will be stored in n2)

And then check if the function has stored 4 values. If not, then it mean the "command" was invalid. When in doubt, just type "sscanf" in google :slight_smile:

amazing!! thanks for that you have just taken my code from 150 lines to like 20! :smiley:

NP, and just in case you didn't know, in C/C++, arrays are always passed by reference to a function, that's why it is not necessary to put a "&" in front of s1 and s2.

also, am i correct in saying that you have already defined the string?

char str[] = "c1255:c2124";

so this will always be the value?

i will need to use the data read from serial so would i use…

char str[] = serial.read();

sorry for the noob questions but i really want to understand every piece of this rather than just copy and paste.
Thanks

Serial.read() will read only one character.

Here is the method I use for reading all characters, until a “\r” is found (so if you use this code you must setup your serial monitor to add a “\r” line ending):

void loop()
{
  if ( Serial.available() > 0 ) 
  {
    static char input[64];
    static uint8_t i;
    char c = Serial.read();

    if ( c != '\r' && i < 64-1)
      input[i++] = c;

    else
    {
      input[i] = '\0';
      i = 0;
      
      // Now input contain the whole Serial message without the last "\r", so place your sscanf code here
      Serial.println( input );
    }
  }
}

Here is a good article to read: Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking

Ok thanks again, final thing is i’m now getting an error on the return 1; this only happens when i try putting the code into void loop(){} which is how i am use to writing my sketches. Could you explain why this is?

void setup(){
}


void loop()
{
  if ( Serial.available() > 0 ) 
  {
    static char input[64];
    static uint8_t i;
    char c = Serial.read();

    if ( c != '\r' && i < 64-1)
      input[i++] = c;

    else
    {
      input[i] = '\0';
      i = 0;
      
      // Now input contain the whole Serial message without the last "\r", so place your sscanf code here
      int main();
{
  char str[] = "serial.read";
  
  char s1[3], s2[3], s3[3], s4[3], s5[3], s6[3];
  int n1, n2, n3, n4, n5, n6;
  if (sscanf(str,"%2s%d:%2s%d%2s%d:%2s%d%2s%d:%2s%d", s1, &n1, s2, &n2, s3, &n3, s4, &n4, s5, &n5, s6, &n6) == 4)
  //if (sscanf(str,"%2s%d:%2s%d", s1, &n1, s2, &n2) == 4)
  {
    printf("%s=%d\n%s=%d%s=%d\n%s=%d%s=%d\n%s=%d", s1, n1, s2, n2, s3, n3, s4, n4, s5, n5, s6, n6);
    //printf("%s=%d\n%s=%d", s1, n1, s2, n2);
  }

  return 1;
}

      Serial.println( input );
    }
  }
}

Without trying to figure out your code, the specific issue is that loop is a void function, you can’t return a value. a simple return; would compile at least.

Thanks :smiley:

if (sscanf(str,"%2s%d:%2s%d%2s%d:%2s%d%2s%d:%2s%d", s1, &n1, s2, &n2, s3, &n3, s4, &n4, s5, &n5, s6, &n6) == 4)

The Serial message is contained in input, not in str.

Also you are expecting 12 values, not 4!

Don't just copy/paste, the code I wrote on codepad wasn't meant to be copy/pasted in an arduino sketch. You copied everything, including main() and return, while you should have copied only what is between. Or do not copy at all, instead try to understand and do it yourself (as you said)