web-dev-qa-db-fra.com

Chaîne d'analyse Arduino (langage C) avec délimiteur (entrée via l'interface série)

Chaîne d'analyse Arduino (langage C) avec délimiteur (entrée via l'interface série)

Vous n'avez pas trouvé la réponse ici: /

Je veux envoyer à mon arduino via une interface série (Serial.read ()) une simple chaîne de trois nombres délimités par une virgule. Ces trois nombres pourraient être compris entre 0 et 255. 

Par exemple. 255,255,2550,0,01,20,10090,200,3

Ce que je dois faire, c'est analyser cette chaîne envoyée à arduino en trois entiers (disons r, g et b).

Alors quand j'envoie 100,50,30 Arduino le traduira en

int r = 100
int g = 50
int b = 30

J'ai essayé beaucoup de codes, mais aucun d'entre eux n'a fonctionné. Le problème principal est de traduire une chaîne (un tas de caractères) en entier. Je pensais qu'il y aurait probablement strtok_r comme délimiteur, mais c'est à peu près tout.

Merci pour vos suggestions :)

9
user1461310

Pour répondre à la question que vous avez réellement posée, les objets String sont très puissants et peuvent faire exactement ce que vous demandez. Si vous limitez vos règles d'analyse directement à partir de l'entrée, votre code devient moins flexible, moins réutilisable et légèrement compliqué.

Les chaînes ont une méthode appelée indexOf () qui vous permet de rechercher l'index dans le tableau de caractères de la chaîne d'un caractère particulier. Si le caractère est introuvable, la méthode doit renvoyer -1. Un deuxième paramètre peut être ajouté à l'appel de fonction pour indiquer un point de départ pour la recherche. Dans votre cas, puisque vos délimiteurs sont des virgules, vous devez appeler:

int commaIndex = myString.indexOf(',');
//  Search for the next comma just after the first
int secondCommaIndex = myString.indexOf(',', commaIndex + 1);

Vous pouvez ensuite utiliser cet index pour créer une sous-chaîne à l'aide de la méthode substring () de la classe String. Cela retourne une nouvelle chaîne commençant à un index de départ particulier et se terminant juste avant un deuxième index (ou la fin d'un fichier si aucun n'est fourni). Donc, vous tapez quelque chose qui ressemble à:

String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex + 1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex + 1); // To the end of the string

Enfin, les valeurs entières peuvent être récupérées à l'aide de la méthode non documentée de la classe String, toInt ():

int r = firstValue.toInt();
int g = secondValue.toInt();
int b = thirdValue.toInt();

Vous trouverez plus d’informations sur l’objet String et ses diverses méthodes dans la Documentation Arduino .

19
dsnettleton

Utilisez sscanf;

const char *str = "1,20,100"; // assume this string is result read from serial
int r, g, b;

if (sscanf(str, "%d,%d,%d", &r, &g, &b) == 3) {
    // do something with r, g, b
}

Utilisez mon code ici si vous souhaitez analyser un flux de chaîne ex: 255,255,255 0,0,0 1,20,100 90,200,3Fonction d’analyse de chaîne délimitée par des virgules

6
sdao

C'est bien! 

Le dernier commentaire sur "thirdvalue = 0" est vrai du code donné dans la réponse la plus votée par @dsnettleton. Cependant, au lieu d'utiliser "lastIndexOf (',');" , le code devrait juste ajouter un "+1" à "secondCommaIndex" comme @dsnettleton l'a fait correctement pour commaIndex + 1 (+1 manquant est probablement juste une faute de frappe du type). 

Voici le morceau de code mis à jour

int commaIndex = myString.indexOf(',');
int secondCommaIndex = myString.indexOf(',', commaIndex+1);
String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex+1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex+1); //To the end of the string  

Exemple)

Pour un myString = "1,2,3"

  • commaIndex = 1 (Recherche à partir de l'index 0, la position prise par le caractère 1, jusqu'à l'emplacement de la première virgule)
  • secondCommaIndex = 3 (Recherche à partir de l'index 2, la position prise par le caractère 2, jusqu'à l'emplacement de la prochaine virgule)
  • firstValue lit à partir de l'index 0-1 = "1"
  • secondValue lit à partir de l'index 2-3 = "2"
  • thirdvalue lit l'index 4-4 (le dernier point d'index de la chaîne) = "3"

Remarque: Ne confondez pas INDEX avec la LONGUEUR de la chaîne. La longueur de la chaîne est 5. Comme la chaîne indexOf compte à partir de 0, le dernier index est 4. 

La raison pour laquelle juste

String thirdValue = myString.substring(secondCommaIndex);

renvoie 0 lorsque vous utilisez .toInt () parce que thirdValue = ", 3" et non "3", ce qui corrige toInt (). 

ps. désolé d’écrire toutes les instructions, mais en tant que technicien, même j’aimerais parfois que quelqu'un écrase du code pour moi, surtout après avoir été consultant pendant les sept dernières années. Continuez le post génial! Aide les gens comme moi à sortir beaucoup!

1
mct

Je pense que le plus simple utilise parseInt() pour effectuer cette tâche:

void loop(){
    if (Serial.available() > 0){
        int r = Serial.parseInt();
        int g = Serial.parseInt();
        int b = Serial.parseInt();
    }
}

fait le tour.

1
R Zach

Je pense que vous voulez faire quelque chose comme ceci pour lire dans les données:

String serialDataIn;
String data[3];
int counter;


int inbyte;

void setup(){
  Serial.begin(9600);
  counter = 0;
  serialDataIn = String("");
}

void loop()
{
    if(serial.available){
        inbyte = Serial.read();
        if(inbyte >= '0' & inbyte <= '9')
            serialDataIn += inbyte;
        if (inbyte == ','){  // Handle delimiter
            data[counter] = String(serialDataIn);
            serialDataIn = String("");
            counter = counter + 1;
        }
        if(inbyte ==  '\r'){  // end of line
                handle end of line a do something with data
        }        
    }
}

Ensuite, utilisez atoi () pour convertir les données en entiers et les utiliser.

1
cstrutton