Saving Serial.Read() to a String (Class)

I want to use the Serial Monitor and give commands to the Arduino, so I can control the OUTPUT pins.

I am using if/else statements. Which works fine for single character char variables. But when I use multiple characters, I can not compare anything in the statements.

char data[] = 'a'; //this would work, I can compare this.
char data[] = {"arduino"}; //this I can not compare

So I wanted to use the String Class. But I can not save Serial.Read() to a String. No problem for character strings but for String class it warns me that I can not save an intiger to a String. ('int' to 'String' is ambiguous)

Any ideas how I can save Serial.Read() to a String?

Here is my code:

#include <LiquidCrystal.h> //LCD liblary
// LCD connection rs  E   do d1 d2 d3
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//pin nomenclature
int aAft = 10;
int aFwd = 9;
int bFwd= 8;
int bAft = 7;

//control inputs for the motor
String ctrl1 = "A FWD"; //A motor FWD
String ctrl2 = "A AFT"; //A motor AFT
String ctrl3 = "B FWD"; //B motor FWD 
String ctrl4 = "B AFT"; //B motor Aft
String ctrl5 = "STOP"; //Stop motors


void setup() {
  
  lcd.begin(16,2); //specify the dimensions of the LCD
  Serial.begin(9600); //initialize serial port
  
  //pin 10-7 are set as OUTPUT 
  int pinModes[5] = {10, 9, 8, 7};  
  for(int i= 0; i < 4; i++)
  {
  pinMode(pinModes[i], OUTPUT);  
  }  
  
}

void loop() {
  //check if serial is available
  if(Serial.available())
  {
  //read serial and save it to control variable as char type
  String control = Serial.read();
    
  //If 1, A motor FWD
  if (control.equals(ctrl1)){
  lcd.clear();
  lcd.print("A motor FWD");
  digitalWrite(aAft, LOW);
  delay(500);
  digitalWrite(aFwd, HIGH);
  
  }
  //If 2, A motor AFT
  else if (control.equals(ctrl2)){
  lcd.clear();
  lcd.print("A motor AFT");
  digitalWrite(aFwd, LOW);
  delay(500);
  digitalWrite(aAft, HIGH);  
  }
  
  //If 3, B motor FWD
  else if(control.equals(ctrl3)){
  lcd.clear();
  lcd.print("B motor FWD");
  digitalWrite(bAft, LOW);
  delay(500);
  digitalWrite(bFwd, HIGH); 
  }
  
  //If 4, B motor AFT
  else if (control.equals(ctrl4)){
  lcd.clear();
  lcd.print("B motor AFT");
  digitalWrite(bFwd, LOW);
  delay(500);
  digitalWrite(bAft, HIGH);  
  }
  
  //If 5, all motors stop
  else if (control.equals(ctrl5)){
  lcd.clear();
  lcd.print("Stop all motors");
  digitalWrite(aFwd, LOW);
  digitalWrite(aAft, LOW);
  digitalWrite(bFwd, LOW);
  digitalWrite(bAft, LOW);
  delay(1000);
  lcd.clear();
  lcd.print("Enter command");  
  }
  
}
}

But when I use multiple characters, I can not compare anything in the statements.

Why not? What went wrong when you used strcmp()?

But I can not save Serial.Read() to a String.

String crap = "";

crap += Serial.read();

I can save Serial.read() to a regular string array. And with strcmp(), I did make another program than this to compare if it is true. The program does not give an error but it also doesn't work.

So I tried using the String Object or so called String Class. And I am trying to figure out a way for making Serial.read(); work with String Objects. Serial.write works fine with Strings but when I do this, it gives an error:

String data = Serial.read();

or

String data = {Serial.read};

neither works. First one gives an "'int' to 'String' is ambiguous" error.

String crap = "";

crap += Serial.read();

This code works fine without an error. But Notting happens to the output pins which are in an if/else statement.

if(Serial.available())
  {
  
  String control = "";
  control += Serial.read();
      
  //If 1, A motor FWD
  if (control.equals(ctrl1)){
  lcd.clear();
  lcd.print("A motor FWD");
  digitalWrite(aAft, LOW);
  delay(500);
  digitalWrite(aFwd, HIGH);

PaulS:

But when I use multiple characters, I can not compare anything in the statements.

Why not? What went wrong when you used strcmp()?

But I can not save Serial.Read() to a String.

String crap = "";

crap += Serial.read();

Some String based serial code that uses a comma , as a data delimiter.

//zoomkat 06-02-14 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi LEDs 

String readString;
int ledPin2 = 2;    // LED connected to digital pin 2
int ledPin3 = 3;    // LED connected to digital pin 3
int ledPin4 = 4;    // LED connected to digital pin 4
int ledPin5 = 5;    // LED connected to digital pin 5

void setup() {
  Serial.begin(9600);
  Serial.println("multi-LED-delimit-test-06-02-2014"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 20a, or 150c, or 200d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >0) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        Serial.print("writing LED value: ");
        Serial.println(n);
        if(readString.indexOf('a') >0) analogWrite(ledPin2, n);
        if(readString.indexOf('b') >0) analogWrite(ledPin3, n);
        if(readString.indexOf('c') >0) analogWrite(ledPin4, n);
        if(readString.indexOf('d') >0) analogWrite(ledPin5, n);
        Serial.println();

        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}
  if (control.equals(ctrl1)){

What IS in control at this time? You've read exactly one character, so unless ctrl1 contains exactly one character, I would expect the equals() method to return false.

control is Serial.Read() which is longer than a character. ctrl1-ctrl5 are the 5 possible commands. If any of them equals control,the statement is processed. ctrl1-ctrl5 are also longer than a character.

So what can I do to compare if Strings that are longer than a character are equal or not?

PaulS:

  if (control.equals(ctrl1)){

What IS in control at this time? You've read exactly one character, so unless ctrl1 contains exactly one character, I would expect the equals() method to return false.

control is Serial.Read() which is longer than a character.

It is NOT.

So what can I do to compare if Strings that are longer than a character are equal or not?

The equals() method works just fine.

You must read and store a whole packet, though, and THEN call the equals() method.

Sending serial data without some kind of end of packet marker is simply an exercise in frustration or time wasting. There is no need to go there.

I finally have found the solution. By using the read.String() function as Serial.readString(), I was able to save Strings from the Serial which are longer than a character. Using Serial.read() and saving it as a String Object was not possible, when using char arrays, I was only able to get one character by Serial.read() so that didn't work when I gave commands over the serial monitor longer than a character.

By using Serial.readString() function, I can now save a String and compare that String in an if/else statement and do that I desire to do.

Below is my code, I have 5 diffrent commands to control two DC motors which are connected to a dual motor controller.

String ctrl1 = "A FWD"; //A motor FWD
String ctrl2 = "A AFT"; //A motor AFT
String ctrl3 = "B FWD"; //B motor FWD
String ctrl4 = "B AFT"; //B motor Aft
String ctrl5 = "STOP"; //Stop motors

If I type any of the above commands to the serial monitor, I am able to control the motors.

Here is the full code:

#include <LiquidCrystal.h> //LCD liblary
// LCD connection rs  E   do d1 d2 d3
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//pin connections to motor contoller
int aAft = 10;
int aFwd = 9;
int bFwd= 8;
int bAft = 7;

String ctrl1 = "A FWD"; //A motor FWD
String ctrl2 = "A AFT"; //A motor AFT
String ctrl3 = "B FWD"; //B motor FWD 
String ctrl4 = "B AFT"; //B motor Aft
String ctrl5 = "STOP"; //Stop motors

void setup() {
  lcd.begin(16,2); //specify the dimensions of the LCD
  Serial.begin(9600);
  lcd.print("Enter a command");

//pin 10-7 are set as OUTPUT 
  int pinModes[5] = {10, 9, 8, 7};  
  for(int i= 0; i < 4; i++)
  {
  pinMode(pinModes[i], OUTPUT);  
  }  
}

void loop() {
  //check if serial is available
  if(Serial.available())
  {  
    //read serial and save it to control variable as String
    String control = Serial.readString();  
  
    //Compare Strings, If "A FWD", A motor FWD
    if(control == ctrl1){
    lcd.clear();
    lcd.print("A motor FWD");
    digitalWrite(aAft, LOW);
    delay(500);
    digitalWrite(aFwd, HIGH);
    }
    
    //Compare Strings, If "A AFT", A motor AFT
    else if (control == ctrl2){
    lcd.clear();
    lcd.print("A motor AFT");
    digitalWrite(aFwd, LOW);
    delay(500);
    digitalWrite(aAft, HIGH);  
    }
  
    //Compare Strings, If "B FWD", B motor FWD
    else if(control == ctrl3){
    lcd.clear();
    lcd.print("B motor FWD");
    digitalWrite(bAft, LOW);
    delay(500);
    digitalWrite(bFwd, HIGH); 
    }
    
    //Compare Strings, If "B AFT", B motor AFT
    else if (control == ctrl4){
    lcd.clear();
    lcd.print("B motor AFT");
    digitalWrite(bFwd, LOW);
    delay(500);
    digitalWrite(bAft, HIGH);  
    }
    
    //Compare Strings, If "STOP", All motors stop
    else if (control == ctrl5){
    lcd.clear();
    lcd.print("All motors STOP");
    delay(5000);
    digitalWrite(aFwd, LOW);
    digitalWrite(aAft, LOW);
    digitalWrite(bFwd, LOW);
    digitalWrite(bAft, LOW);
    delay(1000);
    lcd.clear();
    lcd.print("Enter a command");  
    }   
    
  }  
}

I finally have found the solution. By using the read.String() function as Serial.readString(), I was able to save Strings from the Serial which are longer than a character. Using Serial.read() and saving it as a String Object was not possible, when using char arrays, I was only able to get one character by Serial.read() so that didn't work when I gave commands over the serial monitor longer than a character.

By using Serial.readString() function, I can now save a String and compare that String in an if/else statement and do that I desire to do.

You could also use the Serial.readBytesUntil() or Serial.readBytes() methods to get more than one byte. NULL terminate the char array yourself (it's really simple), and tell the resource-wasting String class to take a hike.

I will also try that.

Another problem I had was, when I tried to use the same code with Xbee Series 2. I have configured my two Xbee modules and they are able to communicate. But when I use the serial monitor of XCTU or Arduino, I am not able to have anything done.

I even changed the code with 1 character char data instead of String data, but it still does not work. Xbee receives the code but the arduino doesn't do anything.

PaulS:

I finally have found the solution. By using the read.String() function as Serial.readString(), I was able to save Strings from the Serial which are longer than a character. Using Serial.read() and saving it as a String Object was not possible, when using char arrays, I was only able to get one character by Serial.read() so that didn't work when I gave commands over the serial monitor longer than a character.

By using Serial.readString() function, I can now save a String and compare that String in an if/else statement and do that I desire to do.

You could also use the Serial.readBytesUntil() or Serial.readBytes() methods to get more than one byte. NULL terminate the char array yourself (it's really simple), and tell the resource-wasting String class to take a hike.

Xbee receives the code

You know this because?

but the arduino doesn't do anything.

I'd expect that from the code you posted. Or failed to.

I know that Xbee receives the code because the RX led blinks on the wirelessshiled.

I code works with USB connection of the arduino via serial monitor. But when I try to make it work with Xbee, there is a problem.

To day I tried something else. When I type the commands from the serial monitor which the xbee is connected, normally the xbee-arduino doesn't do anything again, but when I type the comamand several times, It does work for sometime. But later it doesnt work again.

PaulS:

Xbee receives the code

You know this because?

but the arduino doesn't do anything.

I'd expect that from the code you posted. Or failed to.

I code works with USB connection of the arduino via serial monitor. But when I try to make it work with Xbee, there is a problem.

I suggest you remove the xbees and just use wired serial communication between the tx/rx/gnd until you get things working. Once the communication works, then add the xbees back.