I’m processing data sent to my Arduino Uno that is manually entered via the com port. The data is stored in a character string and by using pointers, strtok(), strcmp(), atoi() and atof() I’m able to process the data (if entered “correctly”) and get the instructions I need. I’m now trying to handle cases where the data is entered by an unsympathetic user.
I check the first part of the string for specific sets of characters, and if I don’t get an “acceptable” value, all the data gets ignored and the user is prompted to re-enter the data. I welcome any thoughts on how to handle this any “better” than I already have.
Here is where I need the help.
In some cases, there is a second part to the string that is supposed to get converted to a 16 bit integer. I have not figured out how to handle the 2nd part of the string if its characters do not result in integer when processed by the atoi() command. Basically, I want to ignore all of the strings that fall outside of the character range of -32768 to 32767. One possible way forward might be to “ignore” strings that contain non-numerical characters, but I’m stumped on how to handle cases where the numerical characters would fall outside the 16 bit int range, or if the first strtok() completely consumes the string.
In the code below, I’m trying to correct for the condition where the user incorrectly enters a single “B”, or a “B “, followed by nothing or something other than the character equivalent of a 16bit int.
const byte numChars = 32; //could be as high as 64 bytes
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
bool newData = false;
void setup() {
Serial.begin(9600);
Serial.println("type 'LIST' for valid inputs format");
delay (1000);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
checkSerial();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void checkSerial() {
static byte ndx = 0;
char endMarker = '\n'; // '\n' is for nonprintable newline, check bottom right of serial monitor and set to 'Newline' '\r' is for 'Carriage return'
char readChar;
while (Serial.available() > 0 && newData == false) {
readChar = Serial.read(); // reads a character
if (readChar != endMarker) {
receivedChars[ndx] = readChar; // writes the character to an array
ndx++;
if (ndx >= numChars) { // limits the string to 32 characters
ndx = numChars - 1;
}
}
else { // '\n' is the Enter key, and when pressed will terminate the string
receivedChars[ndx] = '\0'; // strings must be always terminated by null character
ndx = 0;
newData = true;
}
}
if (newData == true) {
strcpy(tempChars, receivedChars); // copy string to preserve original because strtok() destroys the string it works on
parseData();
newData = false;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index by declaring a pointer to a memory address
strtokIndx = strtok(tempChars," "); // get the first part of string which is terminated by null character
strcpy(messageFromPC, strtokIndx); // copy first part of string to messageFromPC
// put this strtok in an if loop so that it is only called if the correct message is received
if (strcmp(messageFromPC, "LIST") == 0){
Serial.println("LIST = returns list of all commands to serial port");
Serial.println("A = returns something");
Serial.println("B = returns an integer and expects input format 'B 1000' ");
}
else if (strcmp(messageFromPC, "A") == 0){// this ignores everything after the first string
Fonzi();
}
else if (strcmp(messageFromPC, "B") == 0){// Expects an int and NEEDS ERROR CORRECTION
strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx); // convert this part to an integer
Serial.print("B = ");
Serial.println(integerFromPC);
}
else{ //this should handle all cases where the first part of the string is invalid
Serial.println("data entered is invalid, type 'LIST' for valid inputs");
Serial.println();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Fonzi(){
Serial.println("Aaaaaaaaaaaaaa!");
}
References: I have tried to absorb as much of this thread as possible, https://forum.arduino.cc/index.php?topic=396450.0 and I have borrowed heavily from example 5. Per recommendations from this forum, I have purchased a copy of “C Programming Language 2nd Edition” by Kernighan & Ritchie, but I am an impatient beast and it has not yet arrived.
I also found this link helpful to find the functions that will convert the data into other lengths of ints. https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rtref/itoi.htm