Convert serial.read() into a useable string using Arduino?

后端 未结 15 1048
盖世英雄少女心
盖世英雄少女心 2020-11-29 15:27

I\'m using two Arduinos to sent plain text strings to each other using newsoftserial and an RF transceiver.

Each string is perhaps 20-30 characters in length. How do

15条回答
  •  有刺的猬
    2020-11-29 16:14

    Here is a more robust implementation that handles abnormal input and race conditions.

    • It detects unusually long input values and safely discards them. For example, if the source had an error and generated input without the expected terminator; or was malicious.
    • It ensures the string value is always null terminated (even when buffer size is completely filled).
    • It waits until the complete value is captured. For example, transmission delays could cause Serial.available() to return zero before the rest of the value finishes arriving.
    • Does not skip values when multiple values arrive quicker than they can be processed (subject to the limitations of the serial input buffer).
    • Can handle values that are a prefix of another value (e.g. "abc" and "abcd" can both be read in).

    It deliberately uses character arrays instead of the String type, to be more efficient and to avoid memory problems. It also avoids using the readStringUntil() function, to not timeout before the input arrives.

    The original question did not say how the variable length strings are defined, but I'll assume they are terminated by a single newline character - which turns this into a line reading problem.

    int read_line(char* buffer, int bufsize)
    {
      for (int index = 0; index < bufsize; index++) {
        // Wait until characters are available
        while (Serial.available() == 0) {
        }
    
        char ch = Serial.read(); // read next character
        Serial.print(ch); // echo it back: useful with the serial monitor (optional)
    
        if (ch == '\n') {
          buffer[index] = 0; // end of line reached: null terminate string
          return index; // success: return length of string (zero if string is empty)
        }
    
        buffer[index] = ch; // Append character to buffer
      }
    
      // Reached end of buffer, but have not seen the end-of-line yet.
      // Discard the rest of the line (safer than returning a partial line).
    
      char ch;
      do {
        // Wait until characters are available
        while (Serial.available() == 0) {
        }
        ch = Serial.read(); // read next character (and discard it)
        Serial.print(ch); // echo it back
      } while (ch != '\n');
    
      buffer[0] = 0; // set buffer to empty string even though it should not be used
      return -1; // error: return negative one to indicate the input was too long
    }
    

    Here is an example of it being used to read commands from the serial monitor:

    const int LED_PIN = 13;
    const int LINE_BUFFER_SIZE = 80; // max line length is one less than this
    
    void setup() {
      pinMode(LED_PIN, OUTPUT);
      Serial.begin(9600);
    }
    
    void loop() {
      Serial.print("> ");
    
      // Read command
    
      char line[LINE_BUFFER_SIZE];
      if (read_line(line, sizeof(line)) < 0) {
        Serial.println("Error: line too long");
        return; // skip command processing and try again on next iteration of loop
      }
    
      // Process command
    
      if (strcmp(line, "off") == 0) {
          digitalWrite(LED_PIN, LOW);
      } else if (strcmp(line, "on") == 0) {
          digitalWrite(LED_PIN, HIGH);
      } else if (strcmp(line, "") == 0) {
        // Empty line: no command
      } else {
        Serial.print("Error: unknown command: \"");
        Serial.print(line);
        Serial.println("\" (available commands: \"off\", \"on\")");
      }
    }
    

提交回复
热议问题