Reputation: 1
I implemented a buffer on Arduino Mega 2560 using Code of Dan Royer as a base. The code runs perfectly fine on the Mega, but I wanted to use the enhanced features and power of the Arduino Due (which uses an ARM instead of the standard Atmel microprocessor).
On the Due I always get into an infinite loop while processing the buffer content due to it not exiting when the end of the buffer is reached. Does anyone know why this might happen? And do you have ideas on how to prevent this?
The commands given would be GCodes such as : "G01 X20.5 Y30;"
This is how the buffer is filled:
char buffer[MAX_BUF]; // where we store the message until we get a ';'
int sofar; // how much is in the buffer
while(Serial.available() > 0) { // if something is available
char c=Serial.read(); // get it
if(sofar<MAX_BUF-1) buffer[sofar++]=c; // store it
if(c==';') {
// entire message received
// we got a message and it ends with a semicolon
buffer[sofar]=0; // end the buffer so string functions work right
processCommand(); // do something with the command
}
The processCommand() then calls a function that searches the buffer for specific characters and returns the float that is directly behind this character:
/**
* Look for character /code/ in the buffer and read the float that immediately follows it.
* @return the value found. If nothing is found, /val/ is returned.
* @input code the character to look for.
* @input val the return value if /code/ is not found.
**/
float parsenumber(char code,float val) {
char *ptr=buffer;
while(ptr && *ptr && ptr<buffer+sofar) {
if(*ptr==code) { // if /code/ is found
return atof(ptr+1); // return the float behind it
}
ptr=strchr(ptr,' ')+1; // else increment pointer to next char after a space
}
return val; // if the end of the buffer is reached, return the default value
}
Now, this code works perfectly fine on the Arduino Mega, but on the Due the while loop is never exited for some reason.
This is how it works on the Mega:
GCode: G1;
Parsenumber: code:F val:288.46
####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 0.00
String at ptr:
String at buffer end:
#####
End of Parse: return 288.46
But this is how it is on the Due:
GCode: G1;
Parsenumber: code:F val:288.46
#####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 8.00
String at ptr:
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q
String at buffer end:
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q
String at buffer end:
#####
and so on...
Thus, it seems to me that the exit condition ptr<buffer+sofar
is never met. Unfortunately I have not been able to print memory addresses with the Arduino.
Does anyone know anything?
Upvotes: 0
Views: 328
Reputation: 154169
Insure buffer
is a valid string before the while loop. (Maybe arduino initializes values to 0 by default - IDK. C does not and an infinite loop may result and cause "while loop is never exited".)
char buffer[MAX_BUF];
// int sofar;
int sofar = 0; // Initialize to 0.
buffer[0] = 0; // Add
During the while loop, append a null character after each time a character is appended. This is especially important should a ;
is not found or the buffer is long. Is is not posted what happens to buffer
after the while
loop.
if (sofar<MAX_BUF-1) {
buffer[sofar++] = c;
buffer[sofar] = 0; // Add
}
Upvotes: 0
Reputation: 16243
I post my comment to allow to close the question:
Incrementing pointer with ptr=strchr(ptr,' ')+1;
is undefined behaviour, because of strchr doesn't find the char it return NULL
.
You should check strchr
return, before to assign it to ptr.
Probably on Atmel platform, there is a 0x00
at address NULL+1
that make your code work well.
Another possibility (I'm very noob on Arduino) is that strchr
implementation in Atmel library is not returning NULL
if the char is not found. I saw strchr
implementation where, in case of char not found, the returned value was last char of string.
Upvotes: 0