Arduino를 사용하여 serial.read ()를 사용 가능한 문자열로 변환 하시겠습니까?
두 개의 Arduino를 사용하여 newsoftserial 및 RF 트랜시버를 사용하여 일반 텍스트 문자열을 서로 전송했습니다.
각 문자열의 길이는 20-30 자입니다. 등을 Serial.read()
할 수 있도록 문자열 로 어떻게 변환 if x == "testing statements"
합니까?
에서 Serial.Read () 점점 문자열 도움말 :
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");
}
}
무제한 문자열 읽기
String content = "";
char character;
while(Serial.available()) {
character = Serial.read();
content.concat(character);
}
if (content != "") {
Serial.println(content);
}
아두 이노의 직렬에서 Serial.readString()
와 Serial.readStringUntil()
를 사용 하여 문자열을 구문 분석 할 수 있습니다 .
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");
}
가장 쉽고 직관적 인 방법은 Arduino가 loop () 및 setup ()과 함께 정의하는 serialEvent () 콜백을 사용하는 것입니다.
나는 메시지 수신을 처리하는 작은 라이브러리를 오래전에 만들었지 만 그것을 오픈 소스 할 시간이 없었습니다. 이 라이브러리는 공백으로 구분 된 명령 및 임의의 페이로드를 나타내는 \ 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();
}
직렬 포트에서 메시지를 읽고 싶고 모든 메시지를 개별적으로 처리해야하는 경우 다음과 같은 구분 기호를 사용하여 메시지를 부분으로 분리하는 것이 좋습니다.
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;
}
이렇게하면 함수를 사용할 때마다 하나의 메시지를 받게됩니다.
다음은 비정상적인 입력 및 경쟁 조건을 처리하는보다 강력한 구현입니다.
- 비정상적으로 긴 입력 값을 감지하여 안전하게 버립니다. 예를 들어, 소스에 오류가 있고 예상 종료 자없이 입력이 생성 된 경우; 또는 악의적이었습니다.
- 이는 문자열 값이 항상 널로 종료되도록합니다 (버퍼 크기가 완전히 채워진 경우에도).
- 완전한 값이 캡처 될 때까지 기다립니다. 예를 들어 전송 지연으로 인해 나머지 값이 도착하기 전에 Serial.available ()이 0을 반환 할 수 있습니다.
- 여러 값이 처리 될 수있는 것보다 더 빨리 도착할 때 값을 건너 뛰지 않습니다 (직렬 입력 버퍼의 제한에 따름).
- 다른 값의 접두사 인 값을 처리 할 수 있습니다 (예 : "abc"및 "abcd"모두 읽을 수 있음).
String
보다 효율적이고 메모리 문제를 피하기 위해 의도적으로 유형 대신 문자 배열을 사용합니다 . 또한 readStringUntil()
입력이 도착하기 전에 시간이 초과되지 않도록 함수 사용을 피 합니다.
원래 질문은 가변 길이 문자열이 어떻게 정의되는지 말하지 않았지만 단일 개행 문자로 끝나는 것으로 가정합니다. 이는 줄 읽기 문제로 바뀝니다.
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();
}
연결 방법을 사용하는 경우 if else 방법으로 작업하는 경우 문자열을 자르는 것을 잊지 마십시오.
serial.read ()에서 문자열 추가 연산자를 사용하십시오. string.concat ()보다 잘 작동합니다.
char r;
string mystring = "";
while(serial.available())
{
r = serial.read();
mystring = mystring + r;
}
스트림을 문자열 (이 경우 mystring)에 저장 한 후 SubString 함수를 사용하여 찾고있는 것을 추출합니다.
이것에 대한 크레딧은 마그마에게 돌아갑니다. 좋은 대답이지만 여기에서는 c 스타일 문자열 대신 C ++ 스타일 문자열을 사용하고 있습니다. 일부 사용자는 더 쉬울 수 있습니다.
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");
}
}
나는 이것으로 벗어날 수 있습니다.
void setup() {
Serial.begin(9600);
}
void loop() {
String message = "";
while (Serial.available())
message.concat((char) Serial.read());
if (message != "")
Serial.println(message);
}
많은 훌륭한 답변, 여기에 질문에서 요청한 정확한 기능을 가진 2 센트가 있습니다.
또한 읽기 및 디버그가 조금 더 쉬워야합니다.
코드는 최대 128 자 입력으로 테스트됩니다.
Arduino uno r3 (Arduino IDE 1.6.8)에서 테스트 됨
기능 :
- 직렬 명령 입력을 사용하여 Arduino 온보드 LED (핀 13)를 켜거나 끕니다.
명령 :
- LED.ON
- 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());
}
}
이것은 항상 나를 위해 작동합니다 :)
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
}
}
}
참고 URL : https://stackoverflow.com/questions/5697047/convert-serial-read-into-a-useable-string-using-arduino
'IT박스' 카테고리의 다른 글
(xxxx xxxx xxxx xxxx)와 같은 신용 카드 입력을위한 UITextField 서식 지정 (0) | 2020.11.06 |
---|---|
django runserver를 다시 시작할 때 포트를 '삭제'하는 방법 (0) | 2020.11.06 |
Android에서 기본 경고 대화 상자의 너비와 높이를 제어하는 방법은 무엇입니까? (0) | 2020.11.06 |
Windows 명령 프롬프트를 사용하여 빈 폴더를 삭제하는 방법은 무엇입니까? (0) | 2020.11.06 |
레일의 정의되지 않은 메소드`devise_for ' (0) | 2020.11.06 |