Receiving and interpreting strings via serial

Hello people of the internet,

I was making a project where an Arduino should receive a string via serial, entered on the serial monitor for instance, and then compares it to an instruction and reacts.
(The board is currently an Uno rev3. )

I have both operated with strings and string operations and sent serial data (though no strings) with arduinos, but not the two together.

Here is my setup:

void setup() {

  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH); 

  Serial.begin(19200);
  Serial.setTimeout(200);
  Serial.println(bootConfirm);
  Serial.print(bootNotice);
  for (int k = 0; k < strlen_P(bootNotice); k++) {
    char miniBuffer =  pgm_read_byte_near(bootNotice + k);
    Serial.print(miniBuffer);
  }
  Serial.println(readyConfirm);
  Serial.flush();

}

and this is the loop

void loop() {
  if (Serial.available() > 0) {
    instruction = Serial.readStringUntil('\n'); 
    Serial.println(instruction);
    if (instruction == "LED") {
      //int a = digitalRead(2);
      //digitalWrite(2, !a);
      Serial.println("correct");
    }
    else {
      ; //do nothing
    } 
  }
}

Another odd thing that happens: there is a large character array that I print at the beginning:

char bootConfirm[] = "    Switchboard booted successfully \n";
char readyConfirm[] = "\n     System is ready to receive instructions \n";
const PROGMEM char bootNotice[] = {
  "The system is initialising \n"
  "Instructionset: \n"
  "Type \"move up () degrees\" ; \"move down () degrees\" to tilt \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"turn left () degrees\" ; \"turn right () degrees\" to pan \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"return to zero\" to return to the origin \n"
  "Type \"stop motors\" or press stop button to stop any movement \n"
};

That prints out on the serial monitor just fine, if I leave the pin toggling in the loop function commented out (as it is now), but if try to toggle the pin, the first line of bootNotice glitches out some odd square characters.
Anyone got an idea why?

This is what it looks like:

⸮⸮⸮⸮⸮The system is initialising
Instructionset: 
Type "move up () degrees" ; "move down () degrees" to tilt 
    where () is to be replaced with the desired number of degrees to move 
Type "turn left () degrees" ; "turn right () degrees" to pan 
    where () is to be replaced with the desired number of degrees to move 
Type "return to zero" to return to the origin 
Type "stop motors" or press stop button to stop any movement

I am really not the greatest of programmers, but I cannot see any reason for this to not work, except if I pulled a massive bonehead move that I don’t see; so I try to refer to the swarm of people smarter than me, because I’m running out of ideas right here.

Thanks for reading this lot and for any help you might offer.

Actually, nevermind the second bit about the serial output, that just magically resolved itself

You do not post all your code, variable declarations are omitted, so I assume that "instruction" is of type "String" - do not use the "String" class, it will cause problems sooner or later. Your PROGMEM array "bootNotice" is declared as an array of char but assigned as an array of cstring with 1 element, it should probably have been declared without "{}" in order to be correct (you may need to use "" if you want to break lines). After "Serial.begin()" you should put in a "while (!Serial) ;" statement to ensure that Serial is up before using it. Last but not least, you need to setup the Arduino UI to use the correct type of line break in the serial monitor.

Sorry for not having that in, instruction is indeed a string. Here's the variables as they were.

char bootConfirm[] = "    Switchboard booted successfully \n";
char readyConfirm[] = "\n     System is ready to receive instructions \n";
const PROGMEM char bootNotice[] = {
  "The system is initialising \n"
  "Instructionset: \n"
  "Type \"move up () degrees\" ; \"move down () degrees\" to tilt \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"turn left () degrees\" ; \"turn right () degrees\" to pan \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"return to zero\" to return to the origin \n"
  "Type \"stop motors\" or press stop button to stop any movement \n"
};

String instruction;
int instructionBuffer = 0;
int buttonBuffer = 1;

What for the bootNotice, that problem seemes to have gone by now, but I will try without the {} anyway, if that makes it better. The individual sentences have line breaks in them anyways.

So is your suggestion to make instruction a char array? Because I need to perform string operations to get the important bit out of the instruction. Can I perform string operations on char arrays?

Can I perform string operations on char arrays?

Yes you can. See here. These functions are “included” in the IDE, so you do not have to include the cstring library.

This code "const PROGMEM char bootNotice" means array of char, usually assigned with either of:

const char msg1[] = {'a','b','c','\0'};
const char msg2[] = "abc";

Both the above will yield the same output. Your code is simply wrong becuase you are declaring an array of char and assigning an array of cstring which may yield an unpredicatable result.

"What for the bootNotice, that problem seemes to have gone by now" - Oh boy, bugs fixing them selves are scary critters..

Oh, cool, I didn't know that.
But it doesn't do the string=string+"something" commands?

Just by the way, the program works now with the string, it was actually the settings on the serial monitor, I would never have considered that.
I had it set to both new line and carriage return, and I assume that it's entered as \r\n, so all my commands ended in \r.

But I will certainly try out the variant with char arrays, to see what works better in this instance.

Danois90:
This code "const PROGMEM char bootNotice" means array of char, usually assigned with either of:

const char msg1[] = {'a','b','c','\0'};

const char msg2 = "abc";




Both the above will yield the same output.

So, if it's multiple sentences like I have, should it be:

const char msg[]= "sentence\n"
"sentence2\n"

or

const char msg[]= "sentence\n sentence2\n"

or even

const char msg[]= "sentence\n
sentence2\n"

I would use this method:

char msg[] =
  "Line 1\n"
  "Line 2\n"
  "Line 3\n"
  "And so on...";

Looks nicest IMO. You cannot use operators (msg3 = msg1 + msg2) with cstrings. You need to use strcat for that. But in the arduino world you will hardly need string concatenation - just print the strings separately instead:

Stream.println(msg1);
Stream.println(msg2);

This is more efficient and uses less memory.

Thanks, much appreciated.
I was not referring to concatenation as such, but to the mathematical operators.
What I'm going to do to the string specifically is, if somebody enters, say:
"turn left 20 degrees" to filter out the 20 and put it into an int or float

You would need atoi (Ascii TO Integer) or atof (Ascii TO Float) for that :slight_smile:

@Danois90
“After "Serial.begin()" you should put in a "while (!Serial) ;”

Can you show 1 example on uno that Serial right after Serial.begin() will return false?