Convert serial.read () to useful string using Arduino?

I use two Arduinos to send text strings to each other using newsoftserial and an RF transceiver.

Each line is 20-30 characters long. How to convert Serial.read() to a string so that I can do if x == "testing statements" etc.?

+66
arduino
Apr 17 2018-11-11T00:
source share
15 answers

From Help with Serial.Read () Getting a String :

 char inData[20]; // Allocate some space for the string 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"); } } 
+58
Apr 17 '11 at 23:01
source share

Unlimited lines

  String content = ""; char character; while(Serial.available()) { character = Serial.read(); content.concat(character); } if (content != "") { Serial.println(content); } 
+105
Sep 15 '12 at 18:27
source share

You can use Serial.readString() and Serial.readStringUntil() to parse strings from Serial to Arduino.

You can also use Serial.parseInt() to read integer values ​​from the serial interface.

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

The value to send by serial number will be my string\n5 , and the result will be str = "my string" and x = 5

+50
Jan 07 '14 at 7:57
source share

I asked the same question myself, and after some research, I found something similar.

It works like a charm to me. I use it to remote control my Arduino.

 // Buffer to store incoming commands from serial port String 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 string. Serial.println("OK. Press h for help."); } inData = ""; // Clear recieved buffer } } } 
+11
Jun 11 '13 at 19:13
source share

That would be easier:

  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 <CR> (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/string/byte/strcmp if (result == 0) { Serial.println("data matches whatever"); } else { Serial.println("data does not match whatever"); } 
+4
Aug 16 '13 at 12:56 on
source share

The best and most intuitive way is to use the serialEvent () callback, which Arduino defines along with loop () and setup ().

I created a small library that handles the reception of messages, but did not manage to open it yet. This library gets \ n complete lines, which are a command and an arbitrary payload, separated by spaces. You can configure it to easily use your own protocol.

First of all, the library, SerialReciever.h:

 #ifndef __SERIAL_RECEIVER_H__ #define __SERIAL_RECEIVER_H__ class IncomingCommand { private: static boolean hasPayload; public: static String command; static String 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; String IncomingCommand::command = false; String IncomingCommand::payload = false; #endif // #ifndef __SERIAL_RECEIVER_H__ 

To use it, do the following in your project:

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

To use the received commands:

 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(); } 
+2
Sep 28 '13 at 11:44
source share

If you want to read messages from the serial port, and you need to deal with each individual message separately, I suggest splitting the messages into parts using a separator as follows:

 String getMessage() { String 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; } 

This way you will receive one message every time you use this function.

+2
Jan 15 '14 at 16:48
source share

Here is a more robust implementation that handles abnormal input and race conditions.

  • It detects unusually long input values ​​and safely discards them. For example, if the source had an error and generated input without the expected terminator; or was malicious.
  • It ensures that the string value always ends with zero (even if the buffer size is full).
  • Waits until the full value is committed. For example, transmission delays can cause Serial.available () to return zero until the rest of the value ends.
  • It does not skip values ​​when several values ​​arrive faster than they can be processed (taking into account the limitations of the serial input buffer).
  • It can handle values ​​that are a prefix of another value (for example, "abc" and "abcd" can be read).

It intentionally uses character arrays instead of the String type to be more efficient and avoid memory problems. It also avoids using the readStringUntil() function so as not to expire before input is entered.

The original question does not indicate how variable-length strings are defined, but I assume that they are terminated by a single newline character, which makes this a string reading problem.

 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 } 

Here is an example of how it is used to read commands from a serial monitor:

 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\")"); } } 
+2
Apr 30 '14 at 15:06
source share
 String content = ""; char character; if(Serial.available() >0){ //reset this variable! content = ""; //make string from chars while(Serial.available()>0) { character = Serial.read(); content.concat(character); } //send back Serial.print("#"); Serial.print(content); Serial.print("#"); Serial.flush(); } 
+2
Sep 26 '14 at 10:13
source share

If you use the concatenate method, be sure to trim the string if you are working with the if else method.

+1
Apr 13 '14 at 10:17
source share

Use the add line operator on serial.read (). It works better than string.concat ()

 char r; string mystring = ""; while(serial.available()) { r = serial.read(); mystring = mystring + r; } 

After you finish saving the stream to a string (in this case, as a mystring parameter), use the SubString functions to retrieve what you are looking for.

+1
Oct 07 '14 at 11:00
source share

Credit for this goes to magma. Great answer, but here it uses C ++ style strings instead of c style strings. Some users may find this easier.

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

It always works for me :)

 String _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 string } } } 
+1
Oct 31 '16 at 13:35
source share

I could get away from this:

 void setup() { Serial.begin(9600); } void loop() { String message = ""; while (Serial.available()) message.concat((char) Serial.read()); if (message != "") Serial.println(message); } 
0
04 Oct '15 at 12:23
source share

Lots of great answers, here are my 2 cents with exact functionality as asked in the question.

Plus it should be a little easier to read and debug.

Code verified up to 128 input characters.

Tested on Arduino uno r3 (Arduino IDE 1.6.8)

Functionality:

  • Turns the Arduino on or off (pin 13) by entering a command with a serial interface.

Teams

  • LED.ON
  • LED.OFF

Note. Remember to change the data rate based on the speed of your board.

 // 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; String 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 strings or increase the iteration in GetPossibleSerialData() function. delay(1); CheckAndExecuteSerialCommand(); } void CheckAndExecuteSerialCommand() { //Get Data from Serial String 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(); } } String GetPossibleSerialData() { String retVal; int iteration = 10; // 10 times the time it takes to do the main loop if (strSerialInput.length() > 0) { // Print the retreived string 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()); } } 
0
Aug 30 '16 at 4:34
source share



All Articles