1

一旦在Arduino上读取了某个字节串,我正在尝试读取可变的字符流并在Arduino上处理它们。我有一个如下所示的示例草图,但我不知道如何比较“readString”来处理 Arduino 上的某些内容。我希望 Arduino 处理“命令”,例如 {blink}、{open_valve}、{close_valve} 等。

// Serial - read bytes into string variable for string
String readString;

// Arduino serial read - example
int incomingByte;

// flow_A LED
int led = 4;

void setup() {
    Serial.begin(2400);  // Open serial port and set Baud rate to 2400.
    Serial.write("Power on test");
}

void loop() {
    while (Serial.available()) {
      delay(10);
      if (Serial.available() > 0) {
          char c = Serial.read(); // Gets one byte from serial buffer
          readString += c; // Makes the string readString
      }
    }

    if (readString.length() > 0) {
        Serial.println( readString); // See what was received
    }

    if (readString == '{blink_Flow_A}') {
        digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level).
        delay(1000);             // Wait for one second.
        digitalWrite(led, LOW);  // Turn the LED off by making the voltage LOW.
        delay(1000);             // Wait for a second.
    }
4

2 回答 2

3

首先是一些定义:

  • SOP = 数据包开始(在您的情况下,是一个左大括号)
  • EOP = 数据包结束(在您的情况下,是右大括号)
  • PAYLOAD = SOP 和 EOP 之间的字符
  • 数据包 = SOP + 有效负载 + EOP

例子:

PACKET= {Abc}
SOP = {
EOP = }
PAYLOAD = Abc

您的代码应一次处理一个字符,并且应构造为状态机。代码启动时,解析器状态为“我正在等待 SOP 字符”。在这种状态下,您会丢弃收到的每个字符,除非它等于 SOP。

当您发现您收到一个 SOP 字符时,您将解析器状态更改为“我正在接收有效负载”。从现在开始,您将每个字符都存储到缓冲区中,直到您看到 EOP 字符或耗尽缓冲区(稍后会详细介绍)。如果您看到 EOP 字符,您可以通过附加一个 NULL 字符(即 0x00)“关闭”缓冲区,使其成为标准的以 NULL 结尾的 C 字符串,并且您可以使用标准函数(strcmp、strstr、 strchr 等)。此时,您将缓冲区传递给“process()”函数,该函数执行有效负载指定的操作 (1)

您必须指定数据包的最大长度,并相应地调整接收缓冲区的大小。您还必须在“有效负载接收”状态期间跟踪当前有效负载长度,因此您不会意外尝试将更多有效负载字节存储到临时缓冲区中,而不是它可以容纳的(否则会导致内存损坏)。如果您在没有看到 EOP 字符的情况下填充了接收缓冲区,那么该数据包要么格式错误(太长),要么传输错误将 EOP 字符更改为其他字符。在任何一种情况下,您都应该丢弃缓冲区内容并返回“等待 SOP”状态。根据协议设计,您可以向 PC 发送错误代码,以便在终端上键入的人或该端的软件知道它发送的最后一个命令无效或未正确接收。

最后,您剪下的闪烁代码应替换为非阻塞“无延迟闪烁”样式代码(查看 Arduino IDE 附带的示例)。

(1) 一个“进程”函数的例子:

void process(char* cmd) {
    if (strcmp(cmd, "open_valve") == 0) {
        open_valve();
    }
    else if (strcmp(cmd, "close_valve") == 0) {
        close_valve();
    }
    else {
        print_error("Unrecognized command.");
    }
}
于 2013-05-06T13:22:16.563 回答
0

您似乎正在比较此语句中的字符串:

if( readString == '{blink_Flow_A}' )

所以我不明白你的问题:

但我不知道如何比较“readString”来处理某些东西

您真的在问:如何从传入的字符流中提取命令?

如果是这种情况,则将每个命令视为“数据包”。数据包用括号括起来:{}。知道 {} 括号是数据包的开始和结束,很容易编写例程来获取数据包中的命令。

提取命令后,只需通过 if-then-else 语句来执行每个命令应该执行的操作。

如果我完全误解了您的问题,我深表歉意:)

编辑:

http://arduino.cc/en/Tutorial/StringComparisonOperators

if( readString == "{blink_Flow_A}" ) 应该是正确的语法。

既然你有声明

Serial.println(readString);

您应该看到收到的字符串。

于 2013-04-30T21:57:29.047 回答