String usage fail.

First, I’ll try and explain my idea.
What I wanted to do, or I least thought that I could, was communicate with arduino by using not simple chars, like ‘d’ for running a demo, but by strings, like “set_bright” or “move_servo”, and then it does what I told it to do.
Let’s consider I typed “set_bright 255”, to give a LED maximum brightness
My initial idea to what the code would do was:

  • Getting all the data sent read(using a function Robin2 made)
  • Reading until the first blank space parsing the content to controlString(more on that later)
  • Use “if” to see if it contains “set_bright”
  • If it does, read the number and set the bright of led using that number and analogWrite

But, if I’m posting here, you probably already realised that it didn’t work…
Here is the code with comments:

int numData = 32; // used by Robin2's funciton
boolean newData = false; // used by Robin2's funciton
char dataReceived[32]; // used by Robin2's funciton
char tempData[32]; // used by Robin2's funciton
String controlString; /* I don't know if I make this
a string (char array) or a String (object)*/
int ledPin = 11; // the pin of the LED

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  recvWithEndMarker(); // Robin2's function
  if (newData == true) { // if data is received
    strcpy(tempData, dataReceived); // copy the string
    readData(); // custom function (where I think it goes wrong)
  }
}

void recvWithEndMarker() {
  //Made by Robin2
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            dataReceived[ndx] = rc;
            ndx++;
            if (ndx >= numData) {
                ndx = numData - 1;
            }
        }
        else {
            dataReceived[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void readData() {
  char * strtokIndex;
  strtokIndex = strtok(tempData, " "); // until here, okay
  controlString = *strtokIndex;
  /* This is what catches me. This could be either "strcpy(controlString, strtokIndex)"
  or "this" code above (which I think dosen't work) depending in the type of "controlString" */
  Serial.println(controlString); // debug serial.print
  if (controlString == "set_bright") { // I also think this entire "if" dosen't work, but I don't know how to replace it
    Serial.println("Function: set_bright");
    strtokIndex = strtok(NULL, " ");
    int bright = atoi(strtokIndex);
    Serial.print("Bright selected: ");
    Serial.println(bright);
    analogWrite(ledPin, bright);
  } else {
    Serial.println("ERROR: THE SRTING YOU TYPED IS NOT RECOGNISED");
    Serial.println();
  }
  controlString = " "; // this also depends on the type of "controlString"
}

What happens is that I try to type “set_bright 255” and it enters a loop of sending the ERROR messages.

Why? How to fix? Seriously what the hell is going on?

Joprp05: Why? How to fix? Seriously what the hell is going on?

I think that the hell that is going on is because you're not taking what you're doing in stages.

First thing you must do is just have a simple test code that reads the incoming serial information, and then extracts the various components.....eg, the command, and the value. Forget about doing anything else for the moment.

This means...... if you're able to extract the command eg. "set_bright" and if you're able to use serialprint to echo it on the serial monitor display, then that's a good start.

After that, you then make sure that your 'if' statement is able to detect that string. So you would use the 'if' statement, and add some kind of visual feedback indicator that puts something on the serial monitor like 'set_bright command was detected'. Do things a bit at a time.

Also, try

if (strcmp(some_string_name, "set_bright") == 0) { }

which works with char*

Also, note that "strings" contain extra stuff apart from the usual characters----- extra stuff like a null character or some ASCII termination character at the end of it. So if (controlString == "set_bright") might need to be something like if (controlString == "set_bright\0") ...... maybe.

ok thanks. That is a good starting point

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

Why are you opposed to using single characters for a command? The string "set_bright 255" conveys no additional information to the Arduino than would be conveyed by "255". All the other characters are a waste in information and processing terms (and in the time needed to write a program to interpret them).

...R

Robin2: Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

Nice info at that link.

One possible/optional edit is "Many newcomers make the mistake of assuming that something like while (Serial.available() > 0) { will pick up all the data that is sent."

Could possibly change that very very slightly to "Many newcomers make the mistake of assuming that something like while (Serial.available() > 0) { will pick up all the data that was sent (by the sending side) with a single reading (in one go) of the receive buffer." Or something along those lines.

Well, thanks guys. I am very pleased for your help. g'bye.

Southpark: Nice info at that link.

Thank you for your kind comment and your suggestion. I will keep it in mind. As the Thread is locked it is not so easy to make changes.

...R