V3.0.0 of the SafeString library (available from the Arduino Library manager) includes a replacement for Arduino Serial Text I/O that works in real world applications. A detailed tutorial is here
The Quick start is: -
- Install the SafeString library (V3 +) from the Arduino Library Manager or the zip file
- For text input use a SafeStringReader - a non-blocking robust high level reader for reading lines of data or general text with delimiters, with optional echo and optional non-blocking timeout
- For text processing use the SafeString methods - what Arduino Strings was meant to be, but with out the memory problems and odd errors and with detailed error messages.
- For text output write to a BufferedOutput - the non-blocking replacement for Serial print, so your debug msgs and results do not delay the rest of the loop and cause missed input.
- For testing use a SafeStringStream - stress tests your sketch's text processing.
- If you need a larger input buffer use a BufferedInput - for when the sketch processing delays the reading of the input and chars are lost
Arduino Serial is not suitable for handling Text I/O in Real World applications.
You should avoid using any Serial methods in your loop() code and any code it calls. This is because almost all Serial methods will block the rest of your loop() code from running so you will miss real world inputs and your outputs will be delayed. Print() statements are the primary means of debugging Arduino sketches, but adding Serial.print()s adds more delays and often causes more problems then they find.
The tutorial covers reading text input, parsing for commands, parsing text to numbers, e.g. GPS data, and outputting results and debugging messages. All without blocking the rest of the sketch so that your Arduino won't miss the real world inputs and be able to reliably control real world devices, stepper motors, relays etc.
For a stepper motor example see Simple Multitasking in Arduino
SafeStringReader provides a high level non-blocking read() method that simplifies handling Serial Text input and returns the results in SafeStrings so avoiding the user programming errors that are common when working with char[]s
For example this code recognizes two user commands from an unlimited length input stream, using only two small SafeStrings. It can be easily extended to handle more/different commands and numeric input. See the stepper motor example in Simple Multitasking in Arduino.
#include "SafeStringReader.h"
// create an sfReader instance of SafeStringReader class
// that will handle commands upto 5 chars long
// delimited by space, comma or CarrageReturn or NewLine
// the createSafeStringReader( ) macro creates both the SafeStringReader (sfReader) and the necessary SafeString that holds input chars until a delimiter is found
// args are (ReaderInstanceName, expectedMaxCmdLength, delimiters)
createSafeStringReader(sfReader, 5, " ,\r\n");
void setup() {
Serial.begin(9600);
for (int i = 10; i > 0; i--) { // pause a little to give you time to open the Arduino monitor
Serial.print(i); Serial.print(' '); delay(500);
}
Serial.println();
SafeString::setOutput(Serial); // enable error messages and SafeString.debug() output to be sent to Serial
sfReader.connect(Serial); // where SafeStringReader will read from
sfReader.echoOn(); // echo back all input, by default echo is off
sfReader.setTimeout(2000); // 2000mS = 2sec timeout
}
void handleStartCmd() {
// handle start cmd here
}
void handleStopCmd() {
// handle stop cmd here
}
void loop() {
if (sfReader.read()) {
if (sfReader == "start") {
handleStartCmd();
} else if (sfReader == "stop") {
handleStopCmd();
} // else ignore unrecognized command
} // else no delimited command yet
// rest of code here is executed while the user typing in commands
}
}
SafeStringReader has options for echo and timeout.
The BufferedOutput class included in V2.0.6 provides non-blocking Serial Text Output. A practical example of processing GPS data is provided which overcomes the problem of missing part of the GPS messages while handling user input and outputting debugging and other messages.
Typical use is
#include "BufferedOutput.h"
createBufferedOutput(output, 66, DROP_UNTIL_EMPTY); // modes are DROP_UNTIL_EMPTY, DROP_IF_FULL or BLOCK_IF_FULL
void setup() {
Serial.begin(BAUD_RATE);
output.connect(Serial); // <<<<< connect the buffered output to Serial
}
void loop() {
output.nextByteOut(); // <<<<<<<<<< need to call this each loop to release next bytes from buffer
. . .
// replace Serial.print() with output.print() in the loop() code
}
Finally the SafeStringStream class provides a simple means of testing of sketches that require text input without having to type in the input every time the sketch is run.