Convertir serial.read () en une chaîne utilisable avec Arduino?

J’utilise deux Arduinos pour envoyer des chaînes de texte en clair à l’aide de newsoftserial et d’un émetteur-récepteur RF .

Chaque chaîne fait peut-être 20-30 caractères. Comment convertir Serial.read() en chaîne pour que je puisse faire if x == "testing statements" , etc.?

De l’ aide avec Serial.Read () obtenir la chaîne :

 char inData[20]; // Allocate some space for the ssortingng char inChar=-1; // Where to store the character read byte index = 0; // Index into array; where to store the character void setup() { Serial.begin(9600); Serial.write("Power On"); } char Comp(char* This) { while (Serial.available() > 0) // Don't read unless // there you know there is data { if(index < 19) // One less than the size of the array { inChar = Serial.read(); // Read a character inData[index] = inChar; // Store it index++; // Increment where to write next inData[index] = '\0'; // Null terminate the string } } if (strcmp(inData,This) == 0) { for (int i=0;i<19;i++) { inData[i]=0; } index=0; return(0); } else { return(1); } } void loop() { if (Comp("m1 on")==0) { Serial.write("Motor 1 -> Online\n"); } if (Comp("m1 off")==0) { Serial.write("Motor 1 -> Offline\n"); } } 

Chaîne illimitée lue

  Ssortingng content = ""; char character; while(Serial.available()) { character = Serial.read(); content.concat(character); } if (content != "") { Serial.println(content); } 

Vous pouvez utiliser Serial.readSsortingng() et Serial.readSsortingngUntil() pour parsingr les chaînes de série sur l’Arduino.

Vous pouvez également utiliser Serial.parseInt() pour lire des valeurs entières à partir de séries.

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

La valeur à envoyer sur la série serait my ssortingng\n5 et le résultat serait str = "my ssortingng" et x = 5

Je me posais la même question et après quelques recherches, j’ai trouvé quelque chose comme ça.

Cela fonctionne comme un charme pour moi. Je l’utilise pour contrôler à distance mon Arduino.

 // Buffer to store incoming commands from serial port Ssortingng inData; void setup() { Serial.begin(9600); Serial.println("Serial conection started, waiting for instructions..."); } void loop() { while (Serial.available() > 0) { char recieved = Serial.read(); inData += recieved; // Process message when new line character is recieved if (recieved == '\n') { Serial.print("Arduino Received: "); Serial.print(inData); // You can put some if and else here to process the message juste like that: if(inData == "+++\n"){ // DON'T forget to add "\n" at the end of the ssortingng. Serial.println("OK. Press h for help."); } inData = ""; // Clear recieved buffer } } } 

Ce serait beaucoup plus facile:

  char data [21]; int number_of_bytes_received; if(Serial.available() > 0) { number_of_bytes_received = Serial.readBytesUntil (13,data,20); // read bytes (max. 20) from buffer, untill  (13). store bytes in data. count the bytes recieved. data[number_of_bytes_received] = 0; // add a 0 terminator to the char array } bool result = strcmp (data, "whatever"); // strcmp returns 0; if inputs match. // http://en.cppreference.com/w/c/ssortingng/byte/strcmp if (result == 0) { Serial.println("data matches whatever"); } else { Serial.println("data does not match whatever"); } 

La manière la plus efficace et la plus intuitive consiste à utiliser le rappel serialEvent () que définit Arduino avec loop () et setup ().

J’ai construit une petite bibliothèque il y a quelque temps qui gère la réception des messages, mais n’a jamais eu le temps de l’ouvrir. Cette bibliothèque reçoit des lignes terminées représentant une charge et une charge arbitraire, séparées par des espaces. Vous pouvez le modifier pour utiliser votre propre protocole facilement.

Tout d’abord, une bibliothèque, SerialReciever.h:

 #ifndef __SERIAL_RECEIVER_H__ #define __SERIAL_RECEIVER_H__ class IncomingCommand { private: static boolean hasPayload; public: static Ssortingng command; static Ssortingng payload; static boolean isReady; static void reset() { isReady = false; hasPayload = false; command = ""; payload = ""; } static boolean append(char c) { if (c == '\n') { isReady = true; return true; } if (c == ' ' && !hasPayload) { hasPayload = true; return false; } if (hasPayload) payload += c; else command += c; return false; } }; boolean IncomingCommand::isReady = false; boolean IncomingCommand::hasPayload = false; Ssortingng IncomingCommand::command = false; Ssortingng IncomingCommand::payload = false; #endif // #ifndef __SERIAL_RECEIVER_H__ 

Pour l’utiliser, dans votre projet, procédez comme suit:

 #include  void setup() { Serial.begin(115200); IncomingCommand::reset(); } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); if (IncomingCommand::append(inChar)) return; } } 

Pour utiliser les commandes reçues:

 void loop() { if (!IncomingCommand::isReady) { delay(10); return; } executeCommand(IncomingCommand::command, IncomingCommand::payload); // I use registry pattern to handle commands, but you are free to do whatever suits your project better. IncomingCommand::reset(); } 

Si vous voulez lire des messages depuis le port série et que vous devez traiter chaque message séparément, je vous suggère de séparer les messages en plusieurs parties en utilisant un séparateur comme celui-ci:

 Ssortingng getMessage() { Ssortingng msg=""; //the message starts empty byte ch; // the character that you use to construct the Message byte d='#';// the separating symbol if(Serial.available())// checks if there is a new message; { while(Serial.available() && Serial.peek()!=d)// while the message did not finish { ch=Serial.read();// get the character msg+=(char)ch;//add the character to the message delay(1);//wait for the next character } ch=Serial.read();// pop the '#' from the buffer if(ch==d) // id finished return msg; else return "NA"; } else return "NA"; // return "NA" if no message; } 

De cette façon, vous recevrez un message unique chaque fois que vous utiliserez la fonction.

Voici une implémentation plus robuste qui gère les conditions d’entrée et de course anormales.

  • Il détecte les valeurs d’entrée inhabituellement longues et les rejette en toute sécurité. Par exemple, si la source avait une erreur et généré une entrée sans le terminateur attendu; ou était malveillant.
  • Il s’assure que la valeur de chaîne est toujours terminée par null (même lorsque la taille du tampon est complètement remplie).
  • Il attend que la valeur complète soit capturée. Par exemple, les retards de transmission peuvent entraîner le retour de zéro de Serial.available () avant que le rest de la valeur ne soit arrivé.
  • Ne saute pas de valeurs lorsque plusieurs valeurs arrivent plus rapidement qu’elles peuvent être traitées (sous réserve des limitations du tampon d’entrée série).
  • Peut gérer des valeurs qui sont un préfixe d’une autre valeur (par exemple, “abc” et “abcd” peuvent tous deux être lus).

Il utilise délibérément des tableaux de caractères au lieu du type Ssortingng , pour être plus efficace et éviter les problèmes de mémoire. Cela évite également d’utiliser la fonction readSsortingngUntil() pour ne pas expirer avant l’arrivée de l’entrée.

La question initiale ne dit pas comment les chaînes de longueur variable sont définies, mais je suppose qu’elles se terminent par un seul caractère de nouvelle ligne, ce qui en fait un problème de lecture de ligne.

 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 } 

Voici un exemple d'utilisation pour lire des commandes à partir du moniteur série:

 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\")"); } } 
 Ssortingng content = ""; char character; if(Serial.available() >0){ //reset this variable! content = ""; //make ssortingng from chars while(Serial.available()>0) { character = Serial.read(); content.concat(character); } //send back Serial.print("#"); Serial.print(content); Serial.print("#"); Serial.flush(); } 

Si vous utilisez la méthode concaténée, n’oubliez pas de couper la chaîne si vous utilisez la méthode if else.

Utilisez l’opérateur append de chaîne sur le fichier serial.read (). Cela fonctionne mieux que ssortingng.concat ()

 char r; ssortingng myssortingng = ""; while(serial.available()) { r = serial.read(); myssortingng = myssortingng + r; } 

Après avoir sauvegardé le stream dans une chaîne (myssortingng, dans ce cas), utilisez les fonctions SubSsortingng pour extraire ce que vous recherchez.

Crédit pour cela va au magma. Bonne réponse, mais ici, il utilise des chaînes de style c ++ au lieu de chaînes de style c. Certains utilisateurs peuvent trouver cela plus facile.

 Ssortingng ssortingng = ""; char ch; // Where to store the character read void setup() { Serial.begin(9600); Serial.write("Power On"); } boolean Comp(Ssortingng par) { while (Serial.available() > 0) // Don't read unless // there you know there is data { ch = Serial.read(); // Read a character ssortingng += ch; // Add it } if (par == ssortingng) { ssortingng = ""; return(true); } else { //dont reset ssortingng return(false); } } void loop() { if (Comp("m1 on")) { Serial.write("Motor 1 -> Online\n"); } if (Comp("m1 off")) { Serial.write("Motor 1 -> Offline\n"); } } 

Ça fonctionne toujours pour moi 🙂

 Ssortingng _SerialRead = ""; void setup() { Serial.begin(9600); } void loop() { while (Serial.available() > 0) //Only run when there is data available { _SerialRead += char(Serial.read()); //Here every received char will be //added to _SerialRead if (_SerialRead.indexOf("S") > 0) //Checks for the letter S { _SerialRead = ""; //Do something then clear the ssortingng } } } 

Je pourrais m’en tirer avec ça:

 void setup() { Serial.begin(9600); } void loop() { Ssortingng message = ""; while (Serial.available()) message.concat((char) Serial.read()); if (message != "") Serial.println(message); } 

Beaucoup de bonnes réponses, voici mes 2 centimes avec une fonctionnalité exacte comme demandé dans la question.

De plus, il devrait être un peu plus facile à lire et à déboguer.

Le code est testé jusqu’à 128 caractères d’entrée.

Testé sur Arduino uno r3 (Arduino IDE 1.6.8)

Fonctionnalité:

  • Active ou désactive la led embarquée Arduino (pin 13) à l’aide d’une entrée de commande série.

Commandes:

  • CONDUIT SUR
  • LED.OFF

Remarque: n’oubliez pas de modifier la vitesse de transmission en fonction de la vitesse de votre carte.

 // Turns Arduino onboard led (pin 13) on or off using serial command input. // Pin 13, a LED connected on most Arduino boards. int const LED = 13; // Serial Input Variables int intLoopCounter = 0; Ssortingng strSerialInput = ""; // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(LED, OUTPUT); // initialize serial port Serial.begin(250000); // CHANGE BAUD RATE based on the board speed. // initialized Serial.println("Initialized."); } // the loop routine runs over and over again forever: void loop() { // Slow down a bit. // Note: This may have to be increased for longer ssortingngs or increase the iteration in GetPossibleSerialData() function. delay(1); CheckAndExecuteSerialCommand(); } void CheckAndExecuteSerialCommand() { //Get Data from Serial Ssortingng serialData = GetPossibleSerialData(); bool commandAccepted = false; if (serialData.startsWith("LED.ON")) { commandAccepted = true; digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level) } else if (serialData.startsWith("LED.OFF")) { commandAccepted = true; digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW } else if (serialData != "") { Serial.println(); Serial.println("*** Command Failed ***"); Serial.println("\t" + serialData); Serial.println(); Serial.println(); Serial.println("*** Invalid Command ***"); Serial.println(); Serial.println("Try:"); Serial.println("\tLED.ON"); Serial.println("\tLED.OFF"); Serial.println(); } if (commandAccepted) { Serial.println(); Serial.println("*** Command Executed ***"); Serial.println("\t" + serialData); Serial.println(); } } Ssortingng GetPossibleSerialData() { Ssortingng retVal; int iteration = 10; // 10 times the time it takes to do the main loop if (strSerialInput.length() > 0) { // Print the retreived ssortingng after looping 10(iteration) ex times if (intLoopCounter > strSerialInput.length() + iteration) { retVal = strSerialInput; strSerialInput = ""; intLoopCounter = 0; } intLoopCounter++; } return retVal; } void serialEvent() { while (Serial.available()) { strSerialInput.concat((char) Serial.read()); } }