아래와 같은 형식으로 아두이노 시리얼 연결을 통해 서보 위치 리스트를 보냅니다.
1:90&2:80&3:180
다음과 같이 구문 분석한다.
servoId : Position & serboId : Position & serboId : Position'
이 값을 어떻게 분할하여 정수로 변환할 수 있습니까?
다른 답변과는 달리, I'는 다음과 같은 이유로 스트링을 멀리하고 싶다.
아두이노와 같은 임베디드 환경에서 I'는 오히려 **표준 C 함수를 사용한다.
그러면 다음과 같은 코드 샘플이 생성됩니다.
// Calculate based on max input size expected for one command
#define INPUT_SIZE 30
...
// Get next command from Serial (add 1 for final 0)
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
// Add the final 0 to end the C string
input[size] = 0;
// Read each command pair
char* command = strtok(input, "&");
while (command != 0)
{
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
{
// Actually split the string in 2: replace ':' with 0
*separator = 0;
int servoId = atoi(command);
++separator;
int position = atoi(separator);
// Do something with servoId and position
}
// Find the next command in input string
command = strtok(0, "&");
}
장점은 동적 메모리 할당이 수행되지 않고 명령을 읽고 실행하는 함수 내부의 로컬 변수로 '입력'을 선언할 수도 있습니다. 함수가 반환되면 스택에서 '입력'이 차지하는 크기가 복구됩니다.
이 기능을 사용할 수 있는 별도의 문자열 조각으로 무엇을 기반으로 분리하는 문자입니다.
String xval = getValue(myString, ':', 0);
String yval = getValue(myString, ':', 1);
Serial.println("Y:" + yval);
Serial.print("X:" + xval);
변환할 문자열을 int
int xvalue = stringToNumber(xval);
int yvalue = stringToNumber(yval);
이 덩어리 코드를 문자열을 그은 그것을 분리하는 기반으로 특정 문자 및 반품 항목 사이의 분리하는 캐릭터
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
다음과 같은 작업을 수행할 수 있지만 몇 가지 사항을 고려하십시오.
'''readStringUnited()''를 사용하면 문자 또는 시간 초과가 수신될 때까지 대기합니다. 따라서 현재 문자열에서는 마지막 위치가 조금 더 오래 지속되므로 기다려야 합니다. 이 타임아웃을 피하기 위해 후행 ''&''을 추가할 수 있습니다. 모니터에서 이 동작을 쉽게 확인할 수 있으며, 추가 ''&''이 있는 문자열과 없는 문자열을 전송해 보면 시간 초과 지연이 나타납니다.
서보 인덱스는 필요하지 않으며, 위치 문자열을 보내고 문자열의 값 위치를 기준으로 서보 인덱스를 얻을 수 있습니다. 예를 들어 다음과 같습니다: ''90&80&180&''). 서보 인덱스를 사용할 경우 메시지에 문제가 없는지 확인하기 위해 ('int'로 변환한 다음 루프 인덱스 i와 일치) 확인할 수 있습니다.
'''readStringUntil''의 반환 문자열이 비어 있지 않은지 확인해야 합니다. 함수 시간이 초과되면 충분한 데이터를 받지 못한 것이므로 ''int'' 값을 추출하려고 하면 이상한 결과가 나타납니다.
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=1; i<=3; i++) {
String servo = Serial.readStringUntil(':');
if(servo != ""){
//here you could check the servo number
String pos = Serial.readStringUntil('&');
int int_pos=pos.toInt();
Serial.println("Pos");
Serial.println(int_pos);
}
}
}
'Stream.readStringUnited(terminator)'을 사용하여 각 부품에 대해 다른 터미네이터를 전달할 수 있습니다.
그런 다음 각 부분에서 'String.toInt'을(를) 호출합니다.
가장 간단한 솔루션을 사용하는 것sscanf().
int id1, id2, id3;
int pos1, pos2, pos3;
char* buf = "1:90&2:80&3:180";
int n = sscanf(buf, "%d:%d&%d:%d&%d:%d", &id1, &pos1, &id2, &pos2, &id3, &pos3);
Serial.print(F("n="));
Serial.println(n);
Serial.print(F("id1="));
Serial.print(id1);
Serial.print(F(", pos1="));
Serial.println(pos1);
Serial.print(F("id2="));
Serial.print(id2);
Serial.print(F(", pos2="));
Serial.println(pos2);
Serial.print(F("id3="));
Serial.print(id3);
Serial.print(F(", pos3="));
Serial.println(pos3);
이 제공되는 출력은 다음과 같습니다.
n=6
id1=1, pos1=90
id2=2, pos2=80
id3=3, pos3=180
Cheers!
은 예를 참조하십시오에서: https://github.com/BenTommyE/Arduino_getStringPartByNr
// splitting a string and return the part nr index split by separator
String getStringPartByNr(String data, char separator, int index) {
int stringData = 0; //variable to count data part nr
String dataPart = ""; //variable to hole the return text
for(int i = 0; i<data.length()-1; i++) { //Walk through the text one letter at a time
if(data[i]==separator) {
//Count the number of times separator character appears in the text
stringData++;
} else if(stringData==index) {
//get the text when separator is the rignt one
dataPart.concat(data[i]);
} else if(stringData>index) {
//return text and stop if the next separator appears - to save CPU-time
return dataPart;
break;
}
}
//return text if this is the last part
return dataPart;
}
String getValue(String data, char separator, int index)
{
int maxIndex = data.length() - 1;
int j = 0;
String chunkVal = "";
for (int i = 0; i <= maxIndex && j <= index; i++)
{
chunkVal.concat(data[i]);
if (data[i] == separator)
{
j++;
if (j > index)
{
chunkVal.trim();
return chunkVal;
}
chunkVal = "";
}
else if ((i == maxIndex) && (j < index)) {
chunkVal = "";
return chunkVal;
}
}
}
jfpoilpret은 Arduino의 직렬 명령을 구문 분석하기 위한 훌륭한 answer을 제공했습니다. 그러나 Antiny85에는 양방향 시리얼이 없습니다 - SoftwareSerial을 사용해야 합니다. Attiny85에 대해 동일한 코드를 포팅하는 방법입니다.
#include <SoftwareSerial.h>
// Calculate based on max input size expected for one command
#define INPUT_SIZE 30
// Initialize SoftwareSerial
SoftwareSerial mySerial(3, 4); // RX=PB3, TX=PB4
// Parameter for receiving Serial command (add 1 for final 0)
char input[INPUT_SIZE + 1];
void setup() {
mySerial.begin(9600);
}
void loop() {
// We need this counter to simulate Serial.readBytes which SoftwareSerial lacks
int key = 0;
// Start receiving command from Serial
while (mySerial.available()) {
delay(3); // Delay to allow buffer to fill, code gets unstable on Attiny85 without this for some reason
// Don't read more characters than defined
if (key < INPUT_SIZE && mySerial.available()) {
input[key] = mySerial.read();
key += 1;
}
}
if (key > 0) {
// Add the final 0 to end the C string
input[key] = 0;
// Read each command pair
char* command = strtok(input, "&");
while (command != 0)
{
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
{
// Actually split the string in 2: replace ':' with 0
*separator = 0;
int servoId = atoi(command);
++separator;
int position = atoi(separator);
}
// Find the next command in input string
command = strtok(0, "&");
}
}
}
핀 번호에 대한 첨부85 설계도 [2
컴파일 스케치 위치:
Sketch uses 2244 bytes (27%) of program storage space. Maximum is 8192 bytes.
Global variables use 161 bytes (31%) of dynamic memory, leaving 351 bytes for local variables. Maximum is 512 bytes.
따라서 나머지 코드를 위한 충분한 공간과 메모리가 있습니다.
char str[] = "1:90&2:80&3:180"; // test sample serial input from servo
int servoId;
int position;
char* p = str;
while (sscanf(p, "%d:%d", &servoId, &position) == 2)
{
// process servoId, position here
//
while (*p && *p++ != '&'); // to next id/pos pair
}
It's 지 않는 당신의 질문에 대답하지만 그것이 유용할 수 있습니다. 는 경우에 귀하의 문자열에는 특정 접두어,다음 사용할 수 있습니다 단순히startsWith
과문
. E.g.
void loop ()
if(Serial.available()){
command = Serial.readStringUntil('\n');
Serial.println("Received command: " + command);
if(command.startsWith("height")) {
Serial.println(command.substring(7));
}
}
}
다음 보낼높이 10
무엇을 추출합니다10
.
여기에는아두이노하는 방법은 분할 문자열로 질문에 응답"를 분리하는 방법은 문자열에서 substring?"선언으로 중복되는 현재의 질문입니다.
목적의 솔루션을 분석하의 시리즈GPS위치 로그인SD card일이다. 대신하는 데 문자열에서 받은시리얼
,문자열에서 읽은 파일입니다.
함수가StringSplit()
구문 분석하는 문자열sLine="1.12345,4.56789hello"
3 문자열sParams[0]="1.12345"
,sParams[1]="4.56789"
&sParams[2]="hello"
입니다.
문자열 sInput
:입력 라인을 구문 분석,
2.char cDelim
:구분 기호 문자는 매개변수문자열 sParams[]
:출력의 배열을 매개 변수
4.int iMaxParams
:의 최대 수를 매개 변수int
:의 숫자로 구문 분석 매개 변수기능에 따라문자열::indexOf()
와문자열::substring()
:
int StringSplit(String sInput, char cDelim, String sParams[], int iMaxParams)
{
int iParamCount = 0;
int iPosDelim, iPosStart = 0;
do {
// Searching the delimiter using indexOf()
iPosDelim = sInput.indexOf(cDelim,iPosStart);
if (iPosDelim > (iPosStart+1)) {
// Adding a new parameter using substring()
sParams[iParamCount] = sInput.substring(iPosStart,iPosDelim-1);
iParamCount++;
// Checking the number of parameters
if (iParamCount >= iMaxParams) {
return (iParamCount);
}
iPosStart = iPosDelim + 1;
}
} while (iPosDelim >= 0);
if (iParamCount < iMaxParams) {
// Adding the last parameter as the end of the line
sParams[iParamCount] = sInput.substring(iPosStart);
iParamCount++;
}
return (iParamCount);
}
그리고 사용법은 정말 간단합니다:
String sParams[3];
int iCount, i;
String sLine;
// reading the line from file
sLine = readLine();
// parse only if exists
if (sLine.length() > 0) {
// parse the line
iCount = StringSplit(sLine,',',sParams,3);
// print the extracted paramters
for(i=0;i<iCount;i++) {
Serial.print(sParams[i]);
}
Serial.println("");
}