web-dev-qa-db-fra.com

Comment lire une valeur de chaîne avec un délimiteur sur Arduino?

Je dois gérer les servos depuis un ordinateur. 

Je dois donc envoyer des messages de gestion d’ordinateur à Arduino. J'ai besoin de gérer le nombre de servo et le coin. Je pense envoyer quelque chose comme ceci: "1; 130" (premier servo et corner 130, séparateur ";"). 

Existe-t-il de meilleures méthodes pour accomplir cela? 

Voici mon ce code:

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);
}

Ça ne marche pas. Quel est le problème?

11
yital9
  • Vous pouvez utiliser Serial.readString () et Serial.readStringUntil () pour analyser des chaînes De Serial sur arduino.
  • Vous pouvez également utiliser Serial.parseInt () pour lire les valeurs entières des données série.

Exemple de code

int x;
String str;

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

La valeur à envoyer en série serait "ma chaîne\n5" et le résultat serait str = "ma chaîne" et x = 5.

18
Ihab Hajj

La plupart des autres réponses sont soit très verbeuses, soit très générales. J'ai donc pensé donner un exemple de la façon dont cela peut être réalisé avec votre exemple spécifique utilisant les bibliothèques Arduino:

Vous pouvez utiliser la méthode Serial.readStringUntil pour lire jusqu'à votre délimiteur à partir du port Serial.

Et utilisez ensuite toInt pour convertir la chaîne en entier.

Donc, pour un exemple complet:

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

Bien sûr, on peut simplifier un peu:

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

        // Do something awesome!
    }
}
4
Joakim

C'est un super sous j'ai trouvé. C'était super utile et j'espère que ce sera pour vous aussi.

C'est la méthode qui appelle le sous-marin. 

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

C'est le sous!

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]) : "";
}
4
oharkins

Vous devez créer un tampon de lecture et calculer le début et la fin de vos 2 champs (servo # et corner). Ensuite, vous pouvez les lire et convertir les caractères en entiers à utiliser dans le reste de votre code. Quelque chose comme cela devrait fonctionner (non testé sur Arduino, mais 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);
            }
        }
2
Mangist

Il semble que vous ayez juste besoin de corriger

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

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

J'ai fait aussi quelque chose de similaire ..:

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

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