Arduino Series Data Analysis

I am writing an application to control my robot with my Android phone via Bluetooth, everything is fine, the data is repeated and checked, but I have some problems with the protocol, in particular, I want my robot wheels to turn when I send a command, such like s,10,100 or s,-30,-10 ... (percentage values).

My problem is that when I want to parse the wheel speed command on my Arduino, I have to parse up to 4 separate bytes to int , for example s,-100,-100 makes my robot return at full speed, but how to parse this so that I could call setSpeed(left, right); with left and right equal to -100?

I know that I can separately analyze each byte and put them together to get an integer, but this is not very elegant, and probably the best solution for all this already, unfortunately, I have not yet found.

EDIT

Here is my Arduino function for parsing my commands:

 void parseCommand(char* command, int* returnValues) { // parsing state machine byte i = 2, j = 0, sign = 0; int temp = 0; while(*(command + i) != '\0') { switch(*(command + i)) { case ',': returnValues[j++] = sign?-temp:temp; sign = 0; temp = 0; break; case '-': sign = 1; break; default: temp = temp * 10 + *(command + i) - 48; } i++; } // set last return value returnValues[j] = sign?-temp:temp; } 

You call it that when analyzing something like s,100,-100 (should be \0 completed):

 char serialData[16]; void loop() { if(Serial.available() > 0) { Serial.readBytesUntil('\0', serialData, 15); switch(serialData[0]) { case 's': int speed[2]; parseCommand(serialData, speed); setSpeed(speed[0], speed[1]); break; } // always echo Serial.write(serialData); // end of message is maked with a \0 Serial.print('\0'); // clear serialData array memset(serialData, 0, sizeof(serialData)); } } 
+4
source share
2 answers

Just read the character by character in the state machine. It is simple and effective.

To read a number by number, do the following: Start from scratch. For each digit, multiply the number by ten and add the value of the digit. So, for example, reading 97 will work as follows:

  • You read a digit without the previous digit, you start at 0.

  • You read at 9 and calculate (0 * 10) +9 → 9

  • You read at 7 and calculate (9 * 10) +7 → 97

  • You are not reading a number; you are outputting 97.

Here's a more complete example of s,10,100 :

  • You start with a “ready-to-read command state”.

  • You read s, s is a command. You switch to the "ready to read first comma" state.

  • You read the first comma, you switch to "readiness to determine the state of the first parameter".

  • You are reading a figure. Since it was not a "-", the first parameter is positive. You set the first number to the value of the digit, 1. Now you are in the "reading first number" state.

  • You read the digit 0. You set the first number to 1 * 10 + 0 → 10. You are still in the "read first number" state.

  • You are reading a comma. Now you are in the state of “readiness to recognize the state of the second parameter”.

  • You read 1. The second number is positive (since it was not a "-"). You set the second number to 1. You are in the "read second number" state.

  • You read 0. The second number is now set to 1x10 + 0 → 10. You are still in the "reading second number" state.

  • You read 0. The second number is now set to 10x10 + 0 → 100. You are still in the "reading second number" state.

  • You read the end of the line. You fulfill your results: the "s" command, the first number is positive, the first number is 10, the second is positive, the second is 100.

  • You will return to the readiness state for reading the command.

+9
source

I like David Swartz's answer , but I thought I would play the devil's lawyer.

Reading data as a binary can be elegant, it just depends on what you need to do with it.

In the following example, data is read from the serial number until it sees the binary delimiter 0X7F . Reading bytes is stored in an inData char array. Take a look at the documentation for Serial.readBytesUntil()

 char inData[16]; int bRead; bRead = Serial.readBytesUntil(0x7F,inData,4); 

This byte can then be discarded as an integer or otherwise processed. Remember that the maximum value for this would be +/- 126, because it is a signed char (127 is a delimiter and will not be considered a value).

You can access these values ​​using the following:

 Serial.print("Bytes Read: "); Serial.println(bRead); Serial.println("First Byte"); Serial.println((int)inData[0]); Serial.println( map((int)inData[0],0,126,0,1024) ); Serial.println("Second Byte"); Serial.println((int)inData[1]); 

I tested this with the following bash command (after the correct sequential speeds were set):

 echo -ne '\x01\x02\x7F' > /dev/ttyACM0 

An example of the crude code I wrote can be found here.

+4
source

All Articles