使用Arduino将serial.read()转换为可用的string?
我使用两个Arduinos使用newsoftserial和一个RF收发器发送纯文本string。
每个string的长度可能是20-30个字符。 如何将Serial.read()
转换为一个string,所以我可以做, if x == "testing statements"
等?
从Serial.Read()获取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"); } }
无限的stringreaded
String content = ""; char character; while(Serial.available()) { character = Serial.read(); content.concat(character); } if (content != "") { Serial.println(content); }
您可以使用Serial.readString()
和Serial.readStringUntil()
从Arduino上的Serialparsingstring。
您也可以使用Serial.parseInt()
从串行读取整数值。
int x; String str; void loop() { if(Serial.available() > 0) { str = Serial.readStringUntil('\n'); x = Serial.parseInt(); } }
通过串行发送的值将是my string\n5
,结果将是str = "my string"
和x = 5
我自己也在问同样的问题,经过一番调查,我发现了类似的东西。
它对我来说就像一个魅力。 我用它来远程控制我的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 } } }
这将会更容易:
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"); }
最好,最直观的方法是使用serialEvent()callback函数Arduino与loop()和setup()一起定义。
我已经build立了一个小型图书馆,处理消息接收,但从来没有时间来开源。 这个库接收\ n结束的行代表一个命令和任意有效载荷,空格分隔。 你可以调整它来轻松使用自己的协议。
首先,一个库,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__
要使用它,在你的项目中这样做:
#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; } }
要使用收到的命令:
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(); }
如果你想从串口读取消息,你需要分别处理每一条消息,我build议使用这样的分隔符将消息分成几部分:
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; }
这样你每次使用这个函数都会收到一条消息。
这是一个更强大的实现,处理exceptioninput和竞争条件。
- 它检测到exception长的input值,并安全地丢弃它们。 例如,如果源发生错误,并且生成的input没有预期的终止符; 或者是恶意的。
- 它确保string值始终为空(甚至当缓冲区大小被完全填充时)。
- 它会一直等到捕获完整的值。 例如,传输延迟可能导致Serial.available()在值的其余部分到达之前返回零。
- 当多个值到达时,不会跳过值(可能受到串行input缓冲区的限制)。
- 可以处理作为另一个值的前缀的值(例如,“abc”和“abcd”都可以被读入)。
它故意使用字符数组而不是String
types,以提高效率并避免内存问题。 它也避免了使用readStringUntil()
函数,在input到达之前不超时。
原来的问题并没有说明如何定义可变长度的string,但是我会假设它们被一个换行符终止了 – 这就把它变成了一个行读取的问题。
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 }
以下是用于从串口监视器读取命令的示例:
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\")"); } }
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(); }
如果你使用连接方法,那么不要忘记修剪string,如果你正在使用if else方法。
在serial.read()上使用string附加操作符。 它比string.concat()更好地工作
char r; string mystring = ""; while(serial.available()) { r = serial.read(); mystring = mystring + r; }
在完成将string保存之后(在本例中为mystring)之后,使用SubString函数来提取您正在查找的内容。
对此的信贷去岩浆。 很好的答案,但这里使用的是c风格的string,而不是c风格的string。 有些用户可能会发现更容易。
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"); } }
这总是适合我:)
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 } } }
我可以摆脱这个:
void setup() { Serial.begin(9600); } void loop() { String message = ""; while (Serial.available()) message.concat((char) Serial.read()); if (message != "") Serial.println(message); }
许多伟大的答案,这里是我的2美分与问题中所要求的确切function。
另外,它应该是更容易阅读和debugging。
代码被testing到128个字符的input。
testingArduino uno r3(Arduino IDE 1.6.8)
function:
- 使用串行命令input打开或closures板载LED(引脚13)上的Arduino。
命令:
- 带领
- LED.OFF
注意:请记住根据您的主板速度更改波特率。
// 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()); } }