Hi all,
I recently purchased an Allbot robot kit to play around with and to get back into programming.
The provided code for a 4-legged, 8-servo robot doesn't seem to play nice in one specific aspect; when converting parts of a command (stored in a String) using .toInt(), the conversion isn't done properly and I'm left with a bunch of garbage.
This is the part of the provided code that gets and parses a received command:
void getcommand( void )
{
int space1 = 0;
int space2 = 0;
if( Serial.available() )
{
rawcommand = Serial.readString();
// Checking for and deleting garbage data at the beginning of received command
if( ( rawcommand.indexOf( '<' ) != 0 ) && ( rawcommand.indexOf( '<' ) != -1 ) )
{
rawcommand.remove( 0, rawcommand.indexOf( '<' ) );
}
// Checking for and deleting garbage data at the end of received command
if( rawcommand.length() > ( rawcommand.indexOf( '>' ) + 1 ) )
{
rawcommand.remove( ( rawcommand.indexOf( '>' ) + 1 ), ( rawcommand.length() - 1 ) );
}
if( receivelog )
{
Serial.println( "\n\n..:: START:" + rawcommand + ":END ::.." + "\r\n" );
}
// Check if received command is properly formatted
if( ( rawcommand.charAt( 0 ) == '<' ) && ( rawcommand.indexOf( '>' ) <= 12 ) &&
( rawcommand.indexOf( '>' ) != -1 ) && ( rawcommand.length() > 7 ) )
{
if( receivelog )
{
Serial.println( "Recieved command is VALID\n" );
}
// Parse command received via IR into its parts
command = rawcommand.substring( 1, 3 );
// Finding the spaces to save the times and speed
for( int i=0; i <= rawcommand.length(); i++ )
{
if( ( rawcommand.charAt( i ) == ' ' ) && ( space1 == 0 ) )
{
space1 = i;
}
else if( ( rawcommand.charAt( i ) == ' ' ) && ( space2 == 0 ) )
{
space2 = i;
}
}
// Number of times to execute the command
times = rawcommand.substring( ( space1 + 1 ), space2 ).toInt();
// String version of above
timesStr = rawcommand.substring( ( space1 + 1 ), space2 );
// Speed in milliseconds
speedms = rawcommand.substring( ( space2 + 1 ), rawcommand.indexOf( '>' ) ).toInt();
// String version of above
speedmsStr = rawcommand.substring( ( space2 + 1 ), rawcommand.indexOf( '>' ) );
if( receivelog )
{
Serial.println( "Parsed command components are: " );
Serial.flush();
Serial.println( "Command code = " + command );
Serial.flush();
Serial.println( "Number of times to execute command = " + times );
Serial.flush();
Serial.println( "Speed (in milliseconds) = " + speedms );
Serial.flush();
}
}
else
{
if( receivelog )
{
Serial.println( "Command is NOT valid\n" );
}
resetserial();
}
}
}
Which yields the following output:
To make sure that the individual substrings were being formed properly, I did this:
if( receivelog )
{
Serial.println( "Parsed command components are: " );
Serial.flush();
Serial.println( "Command code = " + command );
Serial.flush();
Serial.println( "Number of times to execute command = " + timesStr );
Serial.flush();
Serial.println( "Speed (in milliseconds) = " + speedmsStr );
Serial.flush();
}
Which gave the expected results:
I read up on the documentation for .toInt(); and found that this method requires a null-terminated string to function correctly.... so down the rabbit hole I went.
I tried appending the substring with a '\0', I also tried the suggestion from one forum of first converting the substring into a character array (to make sure the '\0' was in fact at the end of the substring) then using atoi(); on the character array. I tried many different approaches to converting these substrings to integers.
Maybe I'm not doing something correctly, maybe the standard library for whatever it is Arduino uses was updated (I found varying statements on what it actually is; C++ wrappers around C, some sort of modified C++, etc.) or maybe there's just a simpler way of doing this that I'm not seeing.
Any help or pointing in the right direction would be much appreciated!