Trying to Read Specific Serial Inputs

So I'm trying to make a program that primarily runs in the Serial Monitor. So if I type "Set Mode 1", it will change mode from 0 to 1.

int Mode = 0;
String T;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.setTimeout(10);
}

void loop() {
  while (Serial.read() == 0) {
    T=Serial.readString();
  }
  if(T=="Set 1"){
    Mode = 1;
    Serial.println("Mode Set to 1");
  }
}

But for whatever reason, I cant get it to read the string it receives. I dont know if I'm doing something wrong or its just not possible. Any inputs?

First, you are trying to read from the serial port before you know that there is anything in the serial buffer to read.

The serial input basics tutorial has good robust ways to read, parse and act on serial data.

Try this, but first set the line endings in serial monitor to "No line ending".

int Mode = 0;
String T;
void setup()
{
   // put your setup code here, to run once:
   Serial.begin(9600);
   Serial.setTimeout(10);
}

void loop()
{
   if (Serial.available())
   {
      T = Serial.readString();
      if (T == "Set 1")
      {
         Mode = 1;
         Serial.println("Mode Set to 1");
      }
      else
      {
         Serial.println("invalid");
      }
   }
}

This works (tested on my Uno) but readString blocks() and Strings can cause memory trouble. I prefer the methods from Robin2's tutorial.

1 Like

Not really an issue, see my tutorial on Taming Arduino Strings

To read Serial non-blocking and parse simply using Strings see the example sketches in Arduino Software Solutions

readStringUntil_nonBlocking.ino is a good start. Set your IDE monitor to Newline ending.
There are numerous other example sketches for reading/parsing Serial each with their pros/cons
Including ones with timeouts that will work with no line endings at all. (Still non-blocking)

String T;
// read Serial until until_c char found, returns true when found else false
// non-blocking, until_c is returned as last char in String, updates input String with chars read
bool readStringUntil(String& input, char until_c) {
  while (Serial.available()) {
    char c = Serial.read();
    input += c;
    if (c == until_c) {
      return true;
    }
  }
  return false;
}

void loop() {
  if (readStringUntil(T, '\n')) { // read until find newline
    Serial.print(F(" got a line of input '")); Serial.print(T); Serial.println("'");
   if (T == "Set 1") {
    // ....  etc
    }  
    T= ""; // clear after processing for next line
  }
}

If you add the statements
T.trim();
T.toUpperCase();
after
Serial.print(F(" got a line of input '"));
and compare to "SET 1" you can ignore the case of the input and also handle Newline or both NL & CR Monitor inputs
EDIT -- "Set 1" will not match against you input "Set Mode 1"
p.s. @groundFungus setTimeout(10); nice touch to minimize the blocking :slight_smile:
p.p.s If you add T.trim(); to @groundFungus example you can use any line ending you like.

Expanding on @groundFungus good example.

This sketch works with any, or no, line ending and does not block the loop if there is nothing to read.
When reading Set Mode 1 at 9600baud it blocks for ~12mS,
at 115200 baud it blocks for ~3mS when reading Set Mode 1 which could be reduced to 2mS by setting the setTimeout(1);
So use 115200 and the rest of your loop() code will probably not notice the slight reading delay.

String input;
int Mode = 0;

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(2); // at 9600 get about 1char/1mS so when reading user input from Arduino IDE monitor can set this short timeout
  for (int i = 10; i > 0; i--) {
    Serial.print(' '); Serial.print(i);
    delay(500);
  }
  Serial.println();
  Serial.println(F("SerialReadString.ino"));
  input.reserve(80); // expected line size
}

void loop() {
  // without the if (Serial.available()) test average loop time 2024uS (2mS) and ~12000uS (12mS) when reading SET MODE 1
  // With if (Serial.available()) test average loop time 5uS (0.005mS) and ~12000uS (12mS) reading SET MODE 1
  if (Serial.available()) {
    input = Serial.readString();
    input.trim(); // strip off any leading/trailing space and \r \n
    if (input.length() > 0) {  // got some input handle it
      Serial.print(F(" got a some input '")); Serial.print(input); Serial.println("'");
      input.toUpperCase();
      if (input == "SET MODE 1") {
        Mode = 1;
        Serial.println("Mode Set to 1");
      }
    }
  }
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.