Arduino串口数据解析 [英] Arduino serial data parsing

查看:162
本文介绍了Arduino串口数据解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing an app to control my robot with my Android phone over Bluetooth, everything is goes well, data is echoed and verified, but I'm having some trouble with the protocol, specifically I want my robot's wheels to turn when I send a command such as s,10,100 or s,-30,-10... (values in percent).

我的问题是,当我想在我的 Arduino 上解析我的车轮速度命令时,我必须将 从多达 4 个单独的 bytes 解析为 int,例如 s,-100,-100 使我的机器人全速倒退,但我如何解析它以便我可以调用 setSpeed(left, right); leftright 等于 -100?

My problem is that when I want to parse my wheel speed command on my Arduino I must parse from up to 4 separate bytes to int, for example s,-100,-100 makes my robot go backwards at full speed, but how do I parse this so I can call setSpeed(left, right); with leftand right equal to -100?

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

I know I can separately analyse every byte and put them together to get an integer, but it's not very elegant and there's probably a better solution to all this already, unfortunately I haven't found it yet.

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

Here's 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;
}

在解析诸如 s,100,-100(必须以 \0 终止)之类的内容时,您可以这样称呼它:

You call it this way when parsing something like s,100,-100 (must be \0 terminated):

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

推荐答案

只需将一个字符一个字符地读入一个状态机.它简单而高效.

Just read character by character into a state machine. It's simple and efficient.

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

To read in a number digit by digit, do this: Start with zero. For each digit, multiply the number by ten and add the value of the digit. So, for example, reading 97 would work like this:

  1. 你读入一个没有前面数字的数字,你从 0 开始.

  1. You read in a digit with no prior digit, you start with 0.

你读入 9 并计算 (0*10)+9 -> 9

You read in 9 and compute (0*10)+9 -> 9

你读入 7 并计算出 (9*10)+7 -> 97

You read in 7 and compute (9*10)+7 -> 97

你读入一个非数字,你输出的是 97.

You read in a non-digit, you output the 97.

这是一个更完整的例子 s,10,100:

Here's a fuller example s,10,100:

  1. 您从准备读取命令状态"开始.

  1. You start in the "ready to read command state".

你读s",s"是命令.您切换到准备阅读第一个逗号"状态.

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

你读了第一个逗号,然后切换到准备找出第一个参数的符号"状态.

You read the first comma, you switch to the "ready to figure out the sign of the first parameter" state.

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

You read a digit. Since this wasn't a "-", the first parameter is positive. You set the first number to the value of the digit, 1. You are now in "reading first number" state.

您读了一个数字,0.您将第一个数字设置为 1*10+0 -> 10.您仍处于读第一个数字"状态.

You read a digit, 0. You set the first number to 1*10+0 -> 10. You are still in "reading first number" state.

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

You read a comma. You are now in the "ready to figure out sign of the second parameter" state.

你读到了 1.第二个数字是正数(因为这不是-").您将第二个数字设置为 1.您处于读取第二个数字"状态.

You read 1. The second number is positive (since this wasn't a "-"). You set the second number to 1. You are in the "reading second number" state.

您读取的是 0.第二个数字现在设置为 1x10+0 -> 10.您仍处于读取第二个数字"状态.

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

您读取的是 0.第二个数字现在设置为 10x10+0 -> 100.您仍处于读取第二个数字"状态.

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

您阅读了行尾.你执行你的结果:命令是s",第一个数字是正数,第一个数字是10,第二个数字是正数,第二个数字是100.

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

您切换回准备读取命令"状态.

You switch back to "ready to read command" state.

这篇关于Arduino串口数据解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆