Arduino的串行数据分析 [英] Arduino serial data parsing

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

问题描述

我正在写一个应用程序与Android手机通过蓝牙来控制我的机器人,一切都顺利的话,数据的呼应和验证,但我有一些麻烦的协议,特别是我希望我的机器人的轮子转动当我发送一个命令,如 S,10,100 S,-30,-10 ...(中值百分比)。

我的问题是,当我想在我的Arduino解析我的车轮速度命令我必须从高达​​4 的单独的字节来解析的 INT ,例如 S,-100,-100 让我的机器人全速后退去,但我怎么解析这让我可以叫 setSpeed​​(左,右); 离开右键等于-100?

我知道我可以分别分析每一个字节,并把它们放在一起得到一个整数,但它不是很优雅,很可能有一个更好的解决方案,这一切已经,不幸的是我还没有发现它。

修改

下面是我的Arduino功能解析我的命令:

 无效parseCommand(字符*命令,为int * returnValues​​)
{
  //解析状态机
  字节设为i = 2,J = 0,标志= 0;
  INT温度= 0;
  而(*(命令+ I)!='\\ 0')
  {
    开关(*(命令+ I))
    {
      案件 ',':
        returnValues​​ [J ++] =签署-temp:温度;
        签= 0;
        温度= 0;
        打破;
      案件 '-':
        签= 1;
        打破;
      默认:
        TEMP =临时* 10 + *(命令+ I) - 48;
    }
    我++;
  }
  //设置最后一个返回值
  returnValues​​ [J] =签署-temp:温度;
}

您解析像 S,100,-100 (必须 \\ 0 终止时调用它这样):

 字符serialData [16];
无效循环()
{
  如果(Serial.available()大于0)
  {
    Serial.readBytesUntil('\\ 0',serialData,15);
    开关(serialData [0])
    {
      案件的:
        INT速度[2];
        parseCommand(serialData,速度);
        setSpeed​​(速度[0],速度[1]);
        打破;
    }
    //始终回响
    Serial.write(serialData);
    //消息的一端maked以\\ 0
    Serial.print('\\ 0');    //明确serialData阵列
    memset的(serialData,0,sizeof的(serialData));
  }
}


解决方案

刚看完每个字符都变成一个状态机。这是简单而有效的。

要在一些数字由数字阅读,这样做:从零开始。对于每一个数字,十乘数并添加位的值。因此,例如,阅读97将工作是这样的:


  1. 您在没有事先位数字阅读,从0开始。


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


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


  4. 您在一个非数字阅读,你输出97。


下面是一个更完整的例子 S,10,100


  1. 您开始在准备读取命令状态。


  2. 您阅读S,S是命令。切换到准备读第一个逗号状态。


  3. 您读取第一个逗号,则切换到准备找出第一个参数的符号的状态。


  4. 您阅读数字。因为这不是一个 - ,第一个参数是正数。您可以设置第一个数字到数字的值,1。你现在在阅读第一号的状态。


  5. 您看一个数字,0您设置的第一个数字为1 * 10 + 0 - > 10,你仍然在阅读第一号的状态


  6. 您读一个逗号。你现在在准备找出第二个参数的标志的状态。


  7. 您阅读1.第二个数字是正的(因为这是不是一个 - )。您可以设置第二个数字为1。你是在读第二个数字的状态。


  8. 您阅读0。第二个数字是现在设置为1×10 + 0 - > 10,你仍然在读第二个数字状态


  9. 您阅读0。第二个数字是现在设置为10×10 + 0 - > 100.你仍然在读第二个数字状态


  10. 您看行的结束。执行结果:该命令是S,第一个数字是正的,第一个数字是10,第二个数字是正数,第二个数字是100


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


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).

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.

EDIT

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

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.

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. You read in a digit with no prior digit, you start with 0.

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

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

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

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

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

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

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

  4. 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.

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

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

  7. 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.

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

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

  10. 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.

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

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

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