Twojemu programowi brakuje cierpliwości. Na pewno przeczytałeś tamte wątki? Powinieneś mieć też informację kiedy zakończyć budowanie stringa, zakończyć odbiór i przejść do obróbki. Jeśli odczytujesz char to powinieneś to robić aż przyleci znak końca linii, nowej linii. Jak korzystasz ze stringa to tak jak w tamtym wątku odczytaj całego stringa i jeśli to nie zawsze są liczby trzycyfrowe to szukaj tego przecinka:
Kod:
void loop() {
if (Serial.available() > 0) {
Str1 = Serial.readString();
String Str2 = getValue(Str1, ',' , 0)
Serial.println(Str2);
String Str3 = getValue(Str1, ',' , 1)
Serial.println(Str3);
}
Powyższy przykład jak już rozpocznie budowanie stringa to raczej będzie czekał aż przyleci koniec linii, może być to niepożądane.
Wg mnie lepiej korzystać z przykładu event, odczytuje w przerwaniu znak i składa z niego stringa aż do końca linii. Ale daje znać jak skończy odczyt linii i można to dalej obrabiać. Można tu korzystać i ze String (tak jest w przykładzie arduino) i z char:
Kod:
//#include <String.h>
#define buffsize 32
char input[buffsize];
uint16_t dane [4]; // jakie i ile zmiennych odbieramy z UART
byte index = 0;
boolean stringComplete = false; // gdy cale polecenie/napis odebrany
void parsujpolecenia()
{
//polecenie ma wygladac tak: cmd=zmienna1,zmienna2,zmienna3,zmienna4 z zalozenia sa to 4 liczby calkowite
// do 5 cyfr, dlatego buffsize32 ma zapas, dla innych trzeba zmodyfikowac bufor, tablice zmiennych, funkcje
// do konwersji napisu na liczby
//cmd=234,342,553,3432
uint8_t index=0;
char * polecenie=input;
Serial.print("Otrzymane polecenie: ");
Serial.println(polecenie);
char* command1 = strtok(polecenie, "=");
if (strcmp(command1 , "cmd")==0){ //sprawdzenie czy czesc przed znakiem = jest rowna cmd
while (command1 != 0)
{
Serial.println(command1);
command1 = strtok(NULL, ","); //dzielimy reszte napisu w miejscach gdzie jest ","
// Find the next command in input string
if(index<4) dane[index]=atoi(command1); //konwersja napisu na INT i zapisanie do kolejnej pozycji w tablicy
index++;
}
}
else Serial.println("Polecenie nieprawidlowe");
Serial.println("Aktualne parametry:");
Serial.print("Zmienna 1 = ");
Serial.println(dane[0]);
Serial.print("Zmienna 2 = ");
Serial.println(dane[1]);
Serial.print("Zmienna 3 = ");
Serial.println(dane[2]);
Serial.print("Zmienna 4 = ");
Serial.println(dane[3]);
stringComplete = false;
}
// Arduino initialization function.
void setup()
{
Serial.begin(115200);
}
void loop()
{
if (stringComplete) parsujpolecenia();
// Teraz mozna cos zrobic ze zmiennymi
}
void serialEvent() {
while (Serial.available()>0) {
char aChar = Serial.read();
if(aChar == '\n')
{
// wykryto znak konca linii \n, koniec odbioru
input[index] = 0;
index = 0;
stringComplete = true;
}
else
{
input[index] = aChar;
if(index<(buffsize-1)) index++; //jesli napis bedzie dluzszy niz bufor to nadmiar leci w kosz
input[index] = '\0'; // Na koncu napisu wstawiamy 0
}
}
}
A taki jest przykład w Arduino:
Kod:
/*
Serial Event example
When new serial data arrives, this sketch adds it to a String.
When a newline is received, the loop prints the string and clears it.
A good test for this is to try it with a GPS receiver that sends out
NMEA 0183 sentences.
NOTE: The serialEvent() feature is not available on the Leonardo, Micro, or
other ATmega32U4 based boards.
created 9 May 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/SerialEvent
*/
String inputString = ""; // a String to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
}
void loop() {
// print the string when a newline arrives:
if (stringComplete) {
Serial.println(inputString);
// clear the string:
inputString = "";
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
Nie wiem jak to jest robione, ale domyślam, się, że event jest wywoływany po odebraniu znaku w przerwaniu (bo nie ma nigdzie wywołania tej funkcji - robi to biblioteka Arduino).
Edit: if(index<(buffsize-1)) index++; zmieniłem na buffsize-1 bo wyjeżdżało za tablice, używałem do ręcznej komunikacji i zawsze było mniejsze niż buffsize, ale w prawdziwym życiu ponoć może być bum.