Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arduino串行数据解析_Arduino - Fatal编程技术网

Arduino串行数据解析

Arduino串行数据解析,arduino,Arduino,我正在编写一个应用程序,用我的Android手机通过蓝牙控制我的机器人,一切都很顺利,数据得到了回音和验证,但我在协议上遇到了一些问题,特别是当我发送一个命令,如s,10100或s,-30,-10时,我希望我的机器人的轮子转动。。。(值以百分比表示) 我的问题是,当我想在Arduino上解析我的轮速命令时,我必须解析多达4个独立的字节到int,例如s,-100,-100使我的机器人全速后退,但我如何解析它,以便调用setSpeed(左,右)左侧和右侧等于-100 我知道我可以分别分析每个字节,然

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

我的问题是,当我想在Arduino上解析我的轮速命令时,我必须解析多达4个独立的
字节
int
,例如
s,-100,-100
使我的机器人全速后退,但我如何解析它,以便调用
setSpeed(左,右)左侧<代码>和右侧<代码>等于-100

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

编辑 下面是用于解析命令的Arduino函数:

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
终止)的内容时,您可以这样称呼它:


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

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

  • 如果读入的数字没有前面的数字,则从0开始

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

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

  • 如果读取非数字,则输出97

  • 下面是一个更完整的示例
    s,10100

  • 从“准备读取命令状态”开始

  • 你读“s”,s是命令。切换到“准备读取第一个逗号”状态

  • 读取第一个逗号,切换到“准备计算第一个参数的符号”状态

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

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

  • 你读的是逗号。您现在处于“准备找出第二个参数的符号”状态

  • 你读1。第二个数字是正数(因为它不是“-”号)。您将第二个数字设置为1。您处于“读取第二个数字”状态

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

  • 你读了0。第二个数字现在设置为10x10+0->100。您仍处于“读取第二个数字”状态

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

  • 切换回“准备读取命令”状态

  • 我喜欢你的答案,但我想我会扮演魔鬼代言人的角色

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

    在下面的示例中,从串行数据读取数据,直到它看到二进制分隔符
    0X7F
    。读取的字节存储在
    inData
    char数组中。请查看以下文档:

    charindata[16];
    面包;
    bRead=Serial.readBytesUntil(0x7F,inData,4);
    
    然后可以将该字节转换为整数或进行其他操作。请记住,最大值为+/-126,因为这是一个有符号字符(127是分隔符,不会被视为值)

    您可以通过以下方式访问这些值:

    Serial.print(“字节读取:”);
    序列号:println(面包);
    Serial.println(“第一字节”);
    Serial.println((int)inData[0]);
    Serial.println(
    地图((int)inData[0],0126,01024)
    );
    Serial.println(“第二字节”);
    Serial.println((int)inData[1]);
    
    我用下面的bash命令测试了这一点(在确保串行速度设置正确后):

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

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

    你刚刚打败了我,再次:(一个逐字符的状态机就像你能得到的一样灵活、可维护和可扩展。随着新命令的添加,涉及大量库函数的解决方案很快就会变得混乱。似乎有很多麻烦,我认为这是一个相对常见的问题,所以可能现有的函数可以做到这一点……状态机就是这样。当你在控制机器人的其他方面取得进展时,知道非法命令肯定会被检测到、拒绝,并发出一条精确的错误消息,指出出错的地方以及在命令行中发生的位置,这是一堆比从一大堆带字符串的库函数中的某个地方发出的segfault更好的错误到处都是索引,非常漂亮,非常优雅。你可以看看SparkFun的系列。源代码是可用的,它们做的事情非常相似。那些避免二进制操作的人是魔鬼的拥护者,我的朋友friend@Siidheesh有些人是出于固执而鼓吹,有些人是出于无知。不幸的是,在这种情况下,我属于后者
    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));
      }
    }