Here is a demo-code which uses SafeString and SafeStringReader.
The advantage of SafeStringReader is its non-blocking nature.
You could send "10|2"
and then 10 minutes later send "|3" plus a newline
and then the received data will be processed.
But as the character of SafeStringReader is non-blocking
all other code will be processed continously until the delimiter (the newline) will be received
You can see this by the blinking of the onboard-LED which again works non-blocking with non-blocking timing
unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 13; // 2 onboard-LEDESP32 / ESP8266
//const byte OnBoard_LED = 25; // 25 onboard-LED Raspberry Pi pico
//const byte OnBoard_LED = 13; // 13 onboard-LED uno, mega
// Example of NON-Blocking read commmands from the Arduino Monitor input and acts on them
// the available commands are start stop
// See the SafeStringReader_CmdsTimed.ino for an example using a struct to hold the commands and their functions
//
// Commands are delimited by space dot comma NL or CR
// If you set the Arduino Monitor to No line ending then the last command will be ignored until it is terminated by a space or ,
// Use the settings Newline or Carrage Return or Both NL & CR
//
// These commands can be picked out of a line of user input
// start stop
// The input line can be as long as you like 100's of Kb long, but only two small buffers need to parse the commands
//
// download and install the SafeString library
// with the arduino-IDE
// or from www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
#include <SafeStringReader.h>
#include <SafeString.h>
// create an sfReader instance of SafeStringReader class
// that will handle commands upto 32 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, 32, " ,\r\n");
cSF(receivedData_SS, 32); // SafeString can hold up to 32 characters
cSF(data1_SS, 8); // SafeString can hold up to 8 characters
cSF(data2_SS, 8); // SafeString can hold up to 8 characters
cSF(data3_SS, 8); // SafeString can hold up to 8 characters
int data1;
int data2;
int data3;
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
Serial.println();
Serial.println( F(" Set the Arduino IDE monitor to Newline, or Carriage return or Both NL & CR") );
Serial.println("waiting to receive 3 numbers with delimiter |");
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
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED, 250);
// becomes true if a delimiter is received
// see createSafeStringReader(sfReader, 32, " ,\r\n");
if (sfReader.read()) {
receivedData_SS = sfReader;
// print received characters for analysing purposes
Serial.print("received #");
Serial.print(receivedData_SS);
Serial.println("#");
Serial.println();
// function substring stores characters in variable named "data1_SS"
receivedData_SS.substring(data1_SS, 0, receivedData_SS.indexOf('|'));
Serial.print("data1_SS #");
Serial.print(data1_SS);
Serial.println("#");
data1_SS.toInt(data1);
Serial.print("INTEGER-Number: data1:");
Serial.println(data1);
// function substring stores characters in variable named "receivedData_SS"
receivedData_SS.substring(receivedData_SS, receivedData_SS.indexOf('|') + 1);
Serial.println();
// function substring stores characters in variable named "data2_SS"
receivedData_SS.substring(data2_SS, 0, receivedData_SS.indexOf('|'));
Serial.print("data2_SS #");
Serial.print(data2_SS);
Serial.println("#");
data2_SS.toInt(data2);
Serial.print("INTEGER-Number data2:");
Serial.println(data2);
Serial.println();
// function substring stores characters in variable named "receivedData_SS"
receivedData_SS.substring(receivedData_SS, receivedData_SS.indexOf('|') + 1);
Serial.print("receivedData_SS #");
Serial.print(receivedData_SS);
Serial.println("#");
receivedData_SS.toInt(data3);
Serial.print("INTEGER-Number data3:");
Serial.println(data3);
Serial.println();
Serial.println();
Serial.println();
Serial.println("waiting to receive 3 numbers with delimiter |");
}
}
// helper-functions
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
If you run the code and enter "10|2|3"
followed by a newline, or a carriage-return or a comma
this gets printed to the serial monitor
18:19:07.187 -> Setup-Start
18:19:07.187 -> Code running comes from file
18:19:07.187 -> C:\Arduino-Pure-Portable\arduino-1.8.19\portable\sketchbook\SafeStringReader-delimiter-to-Int-002\SafeStringReader-delimiter-to-Int-002.ino
18:19:07.187 -> compiled Mar 31 2024 18:17:19
18:19:07.187 ->
18:19:07.187 -> Set the Arduino IDE monitor to Newline, or Carriage return or Both NL & CR
18:19:07.187 -> waiting to receive 3 numbers with delimiter |
18:19:18.869 -> received #10|2|3#
18:19:18.869 ->
18:19:18.869 -> data1_SS #10#
18:19:18.869 -> INTEGER-Number: data1:10
18:19:18.869 ->
18:19:18.869 -> data2_SS #2#
18:19:18.869 -> INTEGER-Number data2:2
18:19:18.869 ->
18:19:18.869 -> receivedData_SS #3#
18:19:18.869 -> INTEGER-Number data3:3
18:19:18.869 ->
18:19:18.869 ->
18:19:18.869 ->
18:19:18.869 -> waiting to receive 3 numbers with delimiter |
best regards Stefan