Arduino串行数据解析

时间:2012-08-28 14:41:37

标签: arduino

我正在编写一个应用程序,用我的Android手机通过蓝牙控制我的机器人,一切顺利,数据得到回应和验证,但我在协议上遇到了一些问题,特别是我想要我的当我发送s,10,100s,-30,-10等命令时,机器人的轮子会转动......(以百分比表示的值)。

我的问题是,当我想在我的Arduino上解析轮速命令时,我必须将从最多4个解析为bytesint,例如{{ 1}}让我的机器人全速后退,但我如何解析这个问题,以便s,-100,-100 setSpeed(left, right);left等于-100?{/ p>

我知道我可以单独分析每个字节并将它们放在一起得到一个整数,但它不是很优雅,而且可能已经有了更好的解决方案,不幸的是我没有'找到了它。

修改

这是我用于解析命令的Arduino函数:

right

在解析类似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; } (必须s,100,-100终止)的内容时,您会这样称呼它:

\0

2 个答案:

答案 0 :(得分:9)

只需逐个字符地读入状态机。它简单而有效。

要逐位读取数字,请执行以下操作:从零开始。对于每个数字,将数字乘以10并添加数字的值。因此,例如,阅读97将如下工作:

  1. 您读取的数字没有先前的数字,您从0开始。

  2. 您在9中阅读并计算(0 * 10)+9 - > 9

  3. 您在7中阅读并计算(9 * 10)+7 - > 97

  4. 您以非数字读取,输出97。

  5. 这是一个更全面的例子s,10,100

    1. 您从“准备读取命令状态”开始。

    2. 你读“s”,“s”是命令。您切换到“准备好先读取逗号”状态。

    3. 你读了第一个逗号,你切换到“准备找出第一个参数的符号”状态。

    4. 你读了一个数字。由于这不是“ - ”,因此第一个参数是正数。您将第一个数字设置为数字的值,1。您现在处于“读取第一个数字”状态。

    5. 您读取了一个数字,0。您将第一个数字设置为1 * 10 + 0 - > 10.你仍处于“读第一号”状态。

    6. 你读了一个逗号。您现在处于“准备找出第二个参数的状态”状态。

    7. 您阅读1.第二个数字是正数(因为这不是“ - ”)。您将第二个数字设置为1.您处于“读取第二个数字”状态。

    8. 您阅读0.第二个数字现在设置为1x10 + 0 - > 10.你仍处于“读第二号”状态。

    9. 您阅读0.第二个数字现在设置为10x10 + 0 - >你还处于“读第二号”状态。

    10. 你读到了行尾。执行结果:命令为“s”,第一个数字为正数,第一个数字为10,第二个数字为正数,第二个数字为100。

    11. 您切换回“准备读取命令”状态。

答案 1 :(得分:4)

我喜欢David Swartz的答案,但我认为我会扮演魔鬼的拥护者。

以二进制形式读取数据可能很优雅,它只取决于你需要做什么。

在以下示例中,数据从串行读取,直到看到二进制分隔符0X7F。读取的字节存储在inData char数组中。请查看Serial.readBytesUntil()

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

然后可以将此字节转换为整数或以其他方式操纵。请记住,最大值为+/- 126,因为这是一个有符号的字符(127是分隔符,不会被视为值)。

您可以使用以下内容访问这些值:

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]);

我使用以下bash命令对此进行了测试(在确保正确设置了串行速度之后):

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

我写的一些粗略示例代码可以找到 Here