Как прочитать строковое значение с разделителем на Arduino?

Мне нужно управлять сервомашинами с компьютера.

Поэтому мне нужно отправить управляющие сообщения с компьютера на Arduino. Мне нужно управлять количеством сервопривода и угла. Я думаю о том, чтобы отправить что-то вроде этого: "1; 130" (первый серво и угол 130, делиметр ";" ).

Есть ли лучшие методы для этого?

Вот мой код:

String foo = "";
void setup(){
   Serial.begin(9600);
}

void loop(){
   readSignalFromComp();
}

void readSignalFromComp() {
  if (Serial.available() > 0)
      foo = '';
  while (Serial.available() > 0){
     foo += Serial.read(); 
  }
  if (!foo.equals(""))
    Serial.print(foo);
}

Это не работает. В чем проблема?

Ответ 1

  • Вы можете использовать Serial.readString() и Serial.readStringUntil() для анализа строк из Serial на Arduino
  • Вы также можете использовать Serial.parseInt() для чтения целочисленных значений из последовательного

Пример кода

int x;
String str;

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

Значение для отправки через последовательный будет "моя строка \n5", а результат будет str = "моя строка" и х = 5

Примечание. Serial.available() наследуется от служебного класса Stream. https://www.arduino.cc/reference/en/language/functions/communication/serial/available/

Ответ 2

Это отличный суб, который я нашел. Это было очень полезно, и я надеюсь, что это будет и для вас.

Это метод, который вызывает sub.

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

Это 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]) : "";
}

Ответ 3

Большинство других ответов либо очень подробные, либо очень общие, поэтому я подумал, что приведу пример того, как это можно сделать с вашим конкретным примером, используя библиотеки Arduino:

Вы можете использовать метод Serial.readStringUntil для чтения до вашего разделителя с порта Serial.

И затем используйте toInt, чтобы преобразовать строку в целое число.

Итак, для полного примера:

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

Конечно, мы можем немного упростить это:

void loop() 
{
    if (Serial.available() > 0)
    {
        int servo = Serial.readStringUntil(';').toInt();
        int corner = Serial.readStringUntil('\n').toInt();

        // Do something awesome!
    }
}

Ответ 4

Вам нужно построить буфер чтения и вычислить, где начинаются и заканчиваются ваши 2 поля (серво и #). Затем вы можете прочитать их и преобразовать символы в целые числа, чтобы использовать их в остальной части вашего кода. Что-то вроде этого должно работать (не проверено на Arduino, но стандартно 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);
            }
        }

Ответ 5

Похоже, вам просто нужно исправить

  foo = '';  >>to>>  foo = "";

  foo += Serial.read();  >>to>>  foo += char(Serial.read());

Я тоже сделал кое-что похоже.:

void loop(){
  while (myExp == "") {
    myExp = myReadSerialStr();
    delay(100);
  }
}    

String myReadSerialStr() {
  String str = "";
  while (Serial.available () > 0) {
    str += char(Serial.read ());
  }
  return str;
}