• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Odczyt danych z jednego "ciągu liczb".
#1
Witam, potrzebuję odczytać liczby z "ciągu".
Przykładowy "ciąg" wygląda tak: 225,654 i potrzebuję odczytać 225 albo 654.
Nie wiem jak się do tego zabrać, nakierowałby ktoś mnie jakimś przykładem ?
 
Odpowiedź
#2
Rozumiem, że masz ten ciąg w zmiennej, sposób postępowania zależy czy to tablica char czy String. Dla tablicy char używasz strtok() by podzielić napis, dla string dzielisz sobie napis na substring. Jeśli z tego chcesz jeszcze uzyskać liczbę to używasz dla char funkcji atoi() dla licz max int lub analogicznych dla float/long. Dla string funkcje z klasy String (opis na stronie Arduino wszystkich https://www.arduino.cc/reference/en/lang...ingobject/ ).  No i opisana niedawno funkcja getVaule() przez Robson Kerman. Na tym forum są przykłady https://forum.arduinopolska.pl/watek-ser...=substring i kiedyś opisywałem strtok() przy okazji jakiegoś modemu GSM.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
Witam, zrobiłem tak:
Kod:
String readString;
int ind1;
int ind2;
String X2, Y2;


Kod:
if (Serial.available()) {
   while (Serial.available() > 0) {
       char c = Serial.read();  //gets one byte from serial buffer
       readString += c; //makes the string readString
   }
 }
 if (readString.length() > 1) {
   ind1 = readString.indexOf(",");
   X2 = readString.substring(0, ind1);
   ind2 = readString.indexOf(",", ind1+1);
   Y2 = readString.substring(ind1+1, ind2+1);
   Serial.print(X2);
   Serial.print(Y2);
}


Dostaje różne wiadomości zwrotne raz samo X2 z przecinkiem raz X2 i Y2 z przecinkami.
 
Odpowiedź
#4
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.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
@kaczakat wielkie dzięki, podziękowałbym ale nie działa mi przycisk.
 
Odpowiedź
#6
serialEvfent jest wywoływany przerwaniem od rx.

Kaczakat napisał(a):Twojemu programowi brakuje cierpliwości.
Dobrze powiedziane.


(26-04-2018, 14:36)damian5602 napisał(a): @kaczakat wielkie dzięki, podziękowałbym ale nie działa mi przycisk.

Sporo innych rzeczy nie działa.
Zarząd forum wytęża wszelkie siły i już niebawem przesiądziemy się na nowy autorski skrypt.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości