So what I am doing is receiving serial commands on my Arduino and try to parse them into the functions my Arduino runs.
So in this part it is about switching chanels in the connected switching matrix.
What works fine:
Sending "setChanel+" switches the chanel up, "setChanel-" switches it down.
But I want to parse also comands like "setChanel5" to switch to chanel 5.
While "setChanelx" should return an error.
So this is my partial code for this (I think I sould not bother you with 900 lines of code:
//Check for Serial Input
if (Serial.available() > 0) {
SerialRead = Serial.readString();
SerialRead.trim();
// Serial.println("The following derial input had been received:"); //for debugging
Serial.println(SerialRead); //for debugging
if(SerialRead.substring(0,9) == "setChanel"){
if(SerialRead.substring(9,10) == "+") {
if(SerialRead.length() < 11){
Serial.println("Serial_received_Chanel+");
ChanelPlus();
}
else {
Serial.println("'" + SerialRead + "' is not a valid setChanel command!");
}
}
else if(SerialRead.substring(9,10) == "-") {
if(SerialRead.length() < 11){
Serial.println("Serial_received_Chanel-");
ChanelMinus();
}
else {
Serial.println("'" + SerialRead + "' is not a valid setChanel command!");
}
}
else {
int ChanelParser = 9999;
ChanelParser = SerialRead.substring(9).toInt();
Serial.println(ChanelParser);
}
}
}
My situation is that as long as I set a number after "setChanel" I can proceed absolute fine.
But if there is anything that is not a number, ChanelParser is ending up as 0.
I mean I could code a workaround to handle the value 0 as an error state (actually my code knows a chanel 0, so it is not a sexy way), but is there a way to detect if SerialRead.substring(9) contains others as a number?
That's entirely reasonable. Given this is "simplified C++", it's not going to throw an exception, return an error object, or something like that.
Since you are checking the character after setChanel, you might as well do it like
char c = SerialRead.charAt(9);
if (c == '+') {
//...
} else if (c == '-') {
//...
} else if (c >= '0' && c <= '9') {
// There's at least one digit
int ChanelParser = SerialRead.substring(9).toInt();
//...
} else {
// none of the above
}
I think the verification from kenb works the easiest for me, since I don't know what channel numbers mitht be used in the future.
I assume to be less than 10 but who knows...
I know that I just checking the fist charakter of the possible numbers, but honestly, this is the not about catching all that anyone might fool with the serial interface...so if it is setChanel40bla, it will simply ignore the bla after the number.
//Check for Serial Input
if (Serial.available() > 0) {
SerialRead = Serial.readString();
SerialRead.trim();
// Serial.println("The following derial input had been received:"); //for debugging
Serial.println(SerialRead); //for debugging
if(SerialRead.substring(0,9) == "setChanel"){
char CanelPreParser = SerialRead.charAt(9);
if(SerialRead.substring(9,10) == "+") {
if(SerialRead.length() < 11){
Serial.println("Serial_received_Chanel+");
ChanelPlus();
}
else {
Serial.println("'" + SerialRead + "' is not a valid setChanel command!");
}
}
else if(SerialRead.substring(9,10) == "-") {
if(SerialRead.length() < 11){
Serial.println("Serial_received_Chanel-");
ChanelMinus();
}
else {
Serial.println("'" + SerialRead + "' is not a valid setChanel command!");
}
}
else if(CanelPreParser >= '0' && CanelPreParser <= '9') {
int ChanelParser = 9999;
ChanelParser = SerialRead.substring(9).toInt();
Serial.println(ChanelParser);
if (ChanelParser >= '0' && ChanelParser <= maxstatelevel) {
statelevel = ChanelParser;
ProcessStateLevel();
}
else {
Serial.println("There is no chanel " + String(ChanelParser) + " avalable in this config.");
}
}
else {
Serial.println("'" + SerialRead + "' is not a valid setChanel command!");
}
}
}
}
I just now ended up in the issue that even this returns a valid channel number:
Serial.println(ChanelParser);
(Max Statelevel is defined as:
int maxstatelevel = 5;
)
It will always go into else instead of:
if (ChanelParser >= '0' && ChanelParser <= maxstatelevel) {
so setChanel4 will not be catched, even if masstatelevel is 5.
I could not try your code now, but I assume you refer to the point that it compares an Int with a Char, right?
But in my code Maxstatelevel is an Int and also ChanelParser is an Int (filled with the toInt function).
ChanelParser could already be compared with an Int a few rows above.
It’s not
because you can’t know if you read a real 0 value or it’s an error. So if 0 is a reasonable expected number then this function should not be used.
My recommendation would be strtol() (or its variations depending on the expected type) or sscanf() but it has a larger memory impact.
You don’t need an OS to throw exceptions in C++, it works on bare metal MCUs and is self contained to your code but they are memory- and compute-intensive.
Exception handling relies on stack unwinding, which increases code size and execution time and adds some heavy libraries (libgcc, libstdc++,…)
If there is no OS and an uncaught exception occurs in C++ after propagating through the stack, the program will call std::terminate(), which by default calls std::abort(). In a bare-metal environment, this typically results in an infinite loop, a CPU halt, or a system reset, depending on how std::abort() is implemented in the runtime library. If the microcontroller has a watchdog timer enabled, it may eventually reset the system.
On microcontrollers, exceptions work if the compiler provides support (which ours does), but they consume flash and RAM, so many IDE disable them with -fno-exceptions and use error codes instead where possible.
Oh, sorry. If you want to throw exceptions and not risk crashing, you only need to provide some sort of code system to deal with that, and we do have libraries that do that for us.... but don't call that an OS.
Right you are!