Pages: [1]   Go Down
Author Topic: Serial.read() Array mit string füllen und in int umwandeln  (Read 1599 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo.

Ich hätte da ein kleines Problem das vermutlich keines für einen „C“ kundigen ist.

Ein Programm sendet z.B. 1234,5,10 (wobei die Länge der Zahlen variabel ist.) seriell an den Arduino.
Nun soll 1234,5,10 mit Serial.read() so in ein Array (mit maximal 66 Elemente Array[66]) eingelesen werden das ich 3 Int Elemente in dem Array habe. Der Trenner soll das Komma sein.
Array[0] = 1234
Array[1] = 5
Array[2] = 10

Diese 3 Elemente werden dann einer Funktion übergeben
z.B. funktion(Array[0],  Array[1],  Array[2]);

Also:
String 1234,5,10 in Array einlesen wobei nach jedem Komma der Index um eine Stelle hochgezählt wird und somit 3 Elemente im Array[0..2] entstehen.

Die String Elemente in Int Werte umwandeln um diese der funktion(Array[0],  Array[1],  Array[2]); zu übergeben.

Ich habe keinen Schimmer wie ich das machen soll, bin noch totaler C Anfänger  smiley-red
bin für jeden Hinweis dankbar.
Gruß
vobie
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sollen die Werte in
Array[0] = 1234
Array[1] = 5
Array[2] = 10
schon Integer sein, oder noch Strings?
Am einfachsten und vermutlich am RAM-schonensten wäre es, die Werte schon beim Einlesen umzuwandeln

Code:
char buffer[10];
int data[3];
int bindex,dindex=0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  while(Serial.available() >0) {
    //aktuelles Zeichen einlesen
    buffer[bindex] = Serial.read();
    //Trenner oder Zeilenende gefunden
    if(buffer[bindex] == ',' || buffer[bindex] == '\n') {
      //Null-Terminierung
      buffer[bindex] = 0;
      //Umwandeln in eine Zahl
      data[dindex] = atoi(buffer);
     
      //Ausgabe der Daten (DEBUG)
      Serial.print("data at index ");
      Serial.print(dindex);
      Serial.print(" = ");
      Serial.println(data[dindex]);
     
      //Datenindex rotieren
      dindex = ++dindex % 3;
     
      //Buffer Index zurücksetzen
      bindex = 0;
    } else {
      bindex++;
    }
  } 
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das ging ja schnell. :-)

Wichtig ist das die Werte die der Funktion übergeben werden sollen vom Typ Int sind, wann die Umwandlung gemacht wird ist egal.
 
Der Code ist schon auf dem richtigen Weg, aber irgendwie klappt das mit dem 3 Element und dem zurücksetzen nach der ersten Eingabe nicht so richtig.

Hier mal die Ausgabe aus dem Serial Monitor:

1Eingabe: 4660,1,17
 Ausgabe: data at index 0 = 4660
              data at index 1 = 1

2Eingabe: 4660,1,0
 Ausgabe: data at index 2 = -21948
              data at index 0 = 1

gruß
vobie
 
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vermutlich weil das Zeilenende nicht korrekt erkannt wird.
Als Workaround müßte ein zusätzliches "," am Ende der 3 Zahlen erstmal helfen.
Der Code war aus der Hüfte geschossen, ohne das ich ihn testen konnte. Damit bin ich froh, das es überhaupt compiliert :-)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vielen Dank, mit dem Komma am Ende kann ich im Augenblick leben.
Auf jeden Fall habe ich erstmal eine Grundlage :-)
gruß
vobie
Logged

Munich/Germany
Offline Offline
God Member
*****
Karma: 11
Posts: 643
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Eventuell klappt es ja auch mit einem
Code:
    if(buffer[bindex] == ',' || buffer[bindex] == '\n' || !Serial.available()) {
anstelle von
Code:
    if(buffer[bindex] == ',' || buffer[bindex] == '\n') {

Wenn nichts mehr anliegt, ist ja auch das Ende erreicht und es braucht kein abschließendes Zeichen.
Logged

_______
Manfred

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

mit
Code:
if(buffer[bindex] == ',' || buffer[bindex] == '\n' || !Serial.available()) {
kommt bei Eingabe von 4660,1,17 leider
Code:
data at index 0 = 0
data at index 1 = 660
data at index 2 = 1
data at index 0 = 1
raus. :-(

gruß
vobie
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 56
Posts: 2983
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Wenn nichts mehr anliegt, ist ja auch das Ende erreicht und es braucht kein abschließendes Zeichen.
Wenn nichts mehr anliegt, war der Arduino nur zu schnell. Nach dem read() des letzten Zeichens vorhandenen Zeichens liefert available() 0 zurück.

Das while (available()) aussenrum ist schon richtig, ( könnte genausogut ein if (available()) sein, dann wird je loop max. 1 Zeichen gelesen )

Aber: hast du den Serial Monitor so eingestellt dass er nur NL überträgt ?

Was passiert mit anderen Zeichen ? z.B. CR , anderer Dreck ausser 0..9 Komma und NL

Das CR könnte die eine zusätzliche  0  in deinen Daten  sein ???
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

also wenn ich den Serial Monitor auf Neue Zeile(NL) einstelle funktioniert das mit
Code:
if(buffer[bindex] == ',' || buffer[bindex] == '\n'{
Wenn ich jetzt in der shell (Linux)
Code:
echo "4660,1,17\n" > /dev/ttyUSB0
absetze funktioniert das auch :-)
Nun aber habe ich ein neues Problem, meine testfunktion wird 3 mal ausgeführt,
immer wenn dem Array ein neues Element zugewiesen wird.
Eingabe:   4660,1,17
Ausgabe:  4660
              0
              0
              4660
              1
              0
              4660
              1
              17

Die Funktion darf aber nur einmal innerhalb einer Eingabe ausgeführt werden. Also Funktion erst ausführen wenn das Array die Werte 4660
1
17
komplett hat. Danach Array für die nächste Eingabe wieder auf 0 setzen.
Code:
char buffer[10];
int data[3];
int bindex,dindex=0;

void test(int wert0, int wert1, int wert2) {
Serial.println(wert0);
        Serial.println(wert1);
        Serial.println(wert2);
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  while(Serial.available() >0) {
    //aktuelles Zeichen einlesen
    buffer[bindex] = Serial.read();
    //Trenner oder Zeilenende gefunden
    if(buffer[bindex] == ',' || buffer[bindex] == '\n') {
      //Null-Terminierung
      buffer[bindex] = 0;
      //Umwandeln in eine Zahl
      data[dindex] = atoi(buffer);
     
      test(data[0], data[1], data[2]); // testfunktion
     
      //Datenindex rotieren
      dindex = ++dindex % 3;
     
      //Buffer Index zurücksetzen
      bindex = 0;
    } else {
      bindex++;
    }
  } 
}
Wo muss die Funktion "test" hin, damit sie nur einmal ausgeführt wird ?

gruss
vobie
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

statt so
Code:
test(data[0], data[1], data[2]); // testfunktion
      
      //Datenindex rotieren
      dindex = ++dindex % 3;
lieber so:
Code:
     
      //Datenindex rotieren
      dindex = ++dindex % 3;

      //wenn index wieder auf 0 gesetzt wird, dann wurden 3 werte eingelesen
      if(dindex==0) test(data[0], data[1], data[2]); // testfunktion

EDIT: da war eine Zeile aus den CODE-Tags gerutscht.
« Last Edit: November 20, 2012, 05:47:19 am by mkl0815 » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke !

Funktioniert fürs erste :-)
gruss
vobie
Logged

Pages: [1]   Go Up
Jump to: