How to read a string value with a delimiter on Arduino?

后端 未结 7 907
小鲜肉
小鲜肉 2020-12-10 03:34

I have to manage servos from a computer.

So I have to send manage messages from computer to Arduino. I need manage the number of servo and the corner. I\'m thinking

相关标签:
7条回答
  • 2020-12-10 04:02

    This code reads string until it sees '>' character

    void loop() {
      // put your main code here, to run repeatedly:
      String msg = getMessage();
    }
    
    String getMessage() {
      String msg = "";
    
      while (Serial.available()>0) {
        msg =  Serial.readStringUntil('>');
      }
      return msg;
    }
    
    0 讨论(0)
  • 2020-12-10 04:07
    • You can use Serial.readString() and Serial.readStringUntil() to parse strings from Serial on arduino
    • You can also use Serial.parseInt() to read integer values from serial

    Code Example

    int x;
    String str;
    
    void loop() 
    {
        if(Serial.available() > 0)
        {
            str = Serial.readStringUntil('\n');
            x = Serial.parseInt();
        }
    }
    

    The value to send over serial would be "my string\n5" and the result would be str = "my string" and x = 5

    Note: Serial.available() inherits from the Stream utility class. https://www.arduino.cc/reference/en/language/functions/communication/serial/available/

    0 讨论(0)
  • 2020-12-10 04:08

    You need to build a read buffer, and calculate where your 2 fields (servo #, and corner) start and end. Then you can read them in, and convert the characters into Integers to use in the rest of your code. Something like this should work (not tested on Arduino, but standard C):

    void loop()
            {
                int pos = 0; // position in read buffer
                int servoNumber = 0; // your first field of message
                int corner = 0; // second field of message
                int cornerStartPos = 0; // starting offset of corner in string
                char buffer[32];
    
                // send data only when you receive data:
                while (Serial.available() > 0)
                {
                    // read the incoming byte:
                    char inByte = Serial.read();
    
                    // add to our read buffer
                    buffer[pos++] = inByte;
    
                    // check for delimiter
                    if (itoa(inByte) == ';')
                    {
                        cornerStartPos = pos;
                        buffer[pos-1] = 0;
                        servoNumber = atoi(buffer);
    
                        printf("Servo num: %d", servoNumber);
                    }
                }
                else 
                {
                    buffer[pos++] = 0; // delimit
                    corner = atoi((char*)(buffer+cornerStartPos));
    
                    printf("Corner: %d", corner);
                }
            }
    
    0 讨论(0)
  • 2020-12-10 04:09

    Most of the other answers are either very verbose or very general, so I thought I'd give an example of how it can be done with your specific example using the Arduino libraries:

    You can use the method Serial.readStringUntil to read until your delimiter from the Serial port.

    And then use toInt to convert the string to an integer.

    So for a full example:

    void loop() 
    {
        if (Serial.available() > 0)
        {
            // First read the string until the ';' in your example
            // "1;130" this would read the "1" as a String
            String servo_str = Serial.readStringUntil(';');
    
            // But since we want it as an integer we parse it.
            int servo = servo_str.toInt();
    
            // We now have "130\n" left in the Serial buffer, so we read that.
            // The end of line character '\n' or '\r\n' is sent over the serial
            // terminal to signify the end of line, so we can read the
            // remaining buffer until we find that.
            String corner_str = Serial.readStringUntil('\n');
    
            // And again parse that as an int.
            int corner = corner_str.toInt();
    
            // Do something awesome!
        }
    }
    

    Of course we can simplify this a bit:

    void loop() 
    {
        if (Serial.available() > 0)
        {
            int servo = Serial.readStringUntil(';').toInt();
            int corner = Serial.readStringUntil('\n').toInt();
    
            // Do something awesome!
        }
    }
    
    0 讨论(0)
  • 2020-12-10 04:12

    It's universal parser

    struct servo
    {
        int iServoID;
        int iAngle;
    };
    
    std::vector<std::string> split(const std::string& str, const std::string& delim)
    {
        std::vector<std::string> tokens;
        size_t prev = 0, pos = 0;
        do
        {
            pos = str.find(delim, prev);
            if (pos == std::string::npos) pos = str.length();
            std::string token = str.substr(prev, pos-prev);
            if (!token.empty()) tokens.push_back(token);
            prev = pos + delim.length();
        }
        while (pos < str.length() && prev < str.length());
        return tokens;
    }
    
    std::vector<servo> getServoValues(const std::string& message)
    {
        std::vector<servo> servoList;
        servo servoValue;
        std::vector<std::string> servoString;
        std::vector<std::string> values = split(message, ",");
        for (const auto& v : values)
        {
            servoString.clear();
            servoString = split(v, ";");
            servoValue.iServoID = atoi(servoString[0].c_str()); //servoString[0].toInt();
            servoValue.iAngle = atoi(servoString[1].c_str());// servoString[1].toInt();
            servoList.emplace_back(servoValue);
        }
        return servoList;
    }
    

    to call:

    std::string str = "1;233,2;123";
    std::vector<servo> servos = getServoValues(str);
    for (const auto & a : servos)
        std::cout<<a.iServoID << " " << a.iAngle << std::endl;
    

    Result

    1 233
    2 123
    
    0 讨论(0)
  • 2020-12-10 04:17

    This is a Great sub I found. This was super helpful and I hope it will be to you as well.

    This is the method that calls the sub.

    String xval = getValue(myString, ':', 0);
    

    This is The sub!

    String getValue(String data, char separator, int index)
    {
      int found = 0;
      int strIndex[] = {
        0, -1  };
      int maxIndex = data.length()-1;
      for(int i=0; i<=maxIndex && found<=index; i++){
        if(data.charAt(i)==separator || i==maxIndex){
          found++;
          strIndex[0] = strIndex[1]+1;
          strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
      }
      return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
    }
    
    0 讨论(0)
提交回复
热议问题