String readString;
const size_t readString_RESERVE = 100;
// in setup
void setup() {
.. ..
readString.reserve(readString_RESERVE);
.. .
}
bool readLine() {
if (softSerial1.available()) {
char c = softSerial1.read(); //gets one byte from serial buffer
if ((c == '\n') || (c == '\r')) {
return true; // found line
}
// else
readString += c;
if (readString.length() >= readString_RESERVE) {
return true; // a long line
}
// else
}
return false;
}
void loop() {
if (readline()) {
// go a line of input do something
readString = ""; // for next line
}
}
Ok, stop printing inside the readLine method. Otherwise you will just see the char by char.
Wait until readLine returns true. Then in loop() process the line. See the code in my post,
You can print out the whole line by replacing // got a line with Serial.println(readString)
if (readline()) {
Serial.println(readString); // got a line of input do something
if (processLine(readString)) {
// valid line ...
} else {
Serial.print(F("Invalid input:")); Serial.print(readString);
}
readString = ""; // for next line
}
So add a bool processLine(String &line) method
bool processLine(String &line) {
// parse and convert line here
return true; // if valid return true else return false
}
Remember to actually send a '\n' to terminate the input. readStringUntil( ) has a time out.
The code above does not. If you want a non-blocking input timeout
my SafeString library (available from the library manager) has very convenient non-blocking input functions.
Also the String toInt() is a very sloppy conversion and will return 0 for 0.55 (and 0 for "abc" as well)
Do you expect an int or a float
My SafeString library has much better conversion routines, that you can add on
cSFP(sfStr,readString.c_str)); // short for createSafeStringFromCharPtr
int i;
if (sfStr.toInt(i) ) {
// valid int
} else {
Serial.print(sfStr); Serial.println(" is not an int");
}
For using SafeString replace char str[20] with cSF(str,20) and then use str like an Arduino String (mostly)
cSF( ) is a short cut for createSafeString( )
For char str[] = "test" use **cSF(str,10,"test") ** or use
char str[] = "test";
cSFA(sfStr,str); // wraps str in a SafeString and picks up the valid size of str
The F() stuff just saves RAM memory regardless of which approach you use.
You could also just start with Arduino Strings and then later convert to SafeStrings if you need to / want to.
To use Arduino Strings in a 'big' program see my Taming Arduino Strings tutorial for the guideline.
The basic SafeString functions are mimic Arduino String functions, very closely in V4 of SafeStrings.
The SafeString tutorial is a bit overwhelming. Is there a shorter version?
Try running some of the (many) example sketches that come with the SafeString library. They cover each feature one at time.
Drop me line if you have any problems with SafeString.
OK, looks like I am confusing you with Arduino Strings V SafeStrings,
here is some code that just uses SafeStrings and the SafeStringReader which does most of the work
/*
//https://forum.arduino.cc/index.php?topic=728131
*/
#include <SoftwareSerial.h>
#include <SafeStringReader.h>
// download SafeString library from Arduino library manager
// or from the tutorial page
// https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
SoftwareSerial softSerial1(10, 11); // RX, TX
const size_t MAX_LINE_LENGTH = 20;
createSafeStringReader(sfReader, MAX_LINE_LENGTH, "\r\n"); // use either carriage return or Newline to delimit input
cSF(xCoo, MAX_LINE_LENGTH); // create SafeString large enough to hold a whole line
const byte dirPinX = 4;
const byte stepPinX = 5;
volatile float deltaX = 0;
volatile int x_1, x_2;
volatile int hasRunXA = 0, hasRunXB = 0;
volatile int resetXcount = 0, resetYcount = 0, stepXcount = 0, stepYcount = 0;
void setup()
{
softSerial1.begin(9600); //Recieve data on pin 10
Serial.begin(19200); // <<<<<<< 115200 is a better choice
for (int i = 10; i > 0; i--) {
Serial.print(' '); Serial.print(i);
delay(500);
}
Serial.println();
Serial.println(F("SafeStringReader_rawCoo.ino"));
SafeString::setOutput(Serial); // output debug msgs
//sfReader.connect(Serial); // read from Serial for testing
sfReader.connect(softSerial1); // read from softSerial1
if (SafeString::errorDetected()) {
while (1) {
Serial.println(F("Error setting up SafeString globals."));
delay(3000);
}
}
pinMode(stepPinX, OUTPUT);
pinMode(dirPinX, OUTPUT);
}
// parse and convert line here
bool processLine(SafeString &line)
{
xCoo = line; // save input line. Why?
int i = 0;
if (line.toInt(i) ) {
// valid int
x_1 = i;
} else {
Serial.print("'"); Serial.print(line); Serial.println("' is not an int");
return false; // invalid
}
return true; // if valid return true else return false
}
void loop()
{
if (sfReader.read()) // got a line delmited by \r or \n
{
if (processLine(sfReader)) {
// valid line ... now have updated x_1
Serial.print(F("Updated x_1:")); Serial.println(x_1);
} else {
Serial.print(F("Invalid input '")); Serial.print(sfReader); Serial.println("'");
}
// no need to clear sfReader, read() does that for next line
}
}
Output is
SafeStringReader_rawCoo.ino
Updated x_1:44
'kd' is not an int
Invalid input 'kd'
'5.5' is not an int
Invalid input '5.5'
Why is SafeStringReader.h included and not SafeString.h?
Why is 115200 a better choice?
Where do you explain "F()"? On another question you mention it saves RAM memory. On the forward website it says it's a macro... I don't know how to use it.
Why is SafeStringReader.h included and not SafeString.h?
SafeStringReader.h #includes SafeString.h
But no harm if you add another #include "SafeString.h"
as well. There are 'guards' in the .h files so that .h files are only included once regardless of how many #include ".." there are in various headers. So if in doubt, just add the #include
Why is 115200 a better choice?
Serial.prints can block your loop() code if the TX buffer fills up. Using a higher baud rate lets you send more data to the Arduino Monitor without blocking your loop(). If you have a lot of output/debug msgs then you can add an extra non-blocking OutputBuffer, See my Arduino Serial I/O for the Real World for a detailed tutorial.
Where do you explain "F()"? On another question you mention it saves RAM memory. On the forward website it says it's a macro... I don't know how to use it.
If you use as char string line "test" in your code the Compiler puts it in SRAM. On Arduino boards with little memory, like the UNO, you can fill up all you memory with "..." text for output/debugging msgs.
Serial.print and Arduino Strings and SafeStrings all accept a 'special' argument of type
F("text") the F( ) is a macro that tell the Compiler to put the chars in Flash memory instead of SRAM and indicates to the print( ) method, that it needs to use some special code to retrieve the chars.
See my small writeup on What fails when you add lots of Strings to your Arduino program.