Forum: Mikrocontroller und Digitale Elektronik Serielle Kommunikation mit Arduino


von Peter L. (imax2010)


Lesenswert?

Hi,

also komme bei der Kommunikation von PC zu Arduino nicht mehr weiter 
(Mega2560). Wenns nur darum geht einzelne zahlen zu senden dann 
funktioniert das einwandfrei aber bei z.b. "p_brake=0" wirds zwar 
korrekt zurückgegeben aber ich kann damit nichts vergleichen (mit 
"strcmp(inString, "p_brake=1")") d.h. es passiert nicht. Hab dann 
herausgefunden, dass er nicht die gesamten strings oder so einließt und 
habe dazu u.a. das hier getestet:
1
#define MAXSTRING 5
2
char inString[MAXSTRING+1]; // Space for the string plus Nullbyte
3
byte index = 0;
4
5
6
7
void setup() {
8
  // initialize both serial ports:
9
  Serial.begin(9600);
10
  
11
  pinMode(47,OUTPUT);
12
  pinMode(46,OUTPUT);
13
}
14
15
void loop() {
16
 
17
 if (Serial.available() > 0 ) {
18
    inString[index] = Serial.read();
19
    inString[index+1] = '\0';
20
    index += 1;
21
  }
22
23
  if ( index == MAXSTRING ) {
24
    if ( !strcmp(inString, "start") ) {
25
          digitalWrite(47, HIGH);   // set the LED on
26
      index = 0;
27
    } else if ( !strcmp(inString, "stopp") ) {
28
         digitalWrite(47, LOW);   // set the LED off
29
      index = 0;
30
    }
31
  }
32
33
  
34
  
35
}

Leider ist das ja so, dass man 5 Zeichen haben muss um "fortzufahren".

Es ist so, dass von einer Software Daten ausgegeben werden. Den Namen 
der Variablen kann ich noch selbst festlegen z.b. p_brake  . Ändert sich 
dann der Zustand gibt die Software jeweils p_brake=0 oder p_brake=1 aus. 
Zudem kann diese auch z.b. n_n=123.345 ausgeben und enstprechend dieser 
ausgaben muss das arduino interagieren. Kann mir da mal einer auf die 
Sprünge helfen weil in C bin ich noch nicht wirklich bewandert.

Danke

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>Leider ist das ja so, dass man 5 Zeichen haben muss um "fortzufahren".

Ich hab 9 gezählt.

von Peter L. (imax2010)


Lesenswert?

A sorry hatte das falsche drin jetzt ist das was ich aus dem netz hab.

von Karl H. (kbuchegg)


Lesenswert?

Peter L. schrieb:
> A sorry hatte das falsche drin jetzt ist das was ich aus dem netz hab.

Jetzt weißt du auch, warum wir hier immer wieder sagen, dass man die 
DINGE auch LERNEN muss. Code aus dem Internet kopieren und zu glauben 
das reicht dann schon, ist einfach nicht genug. Um eine Herzoperation zu 
machen reicht es einfach nicht sich auf Youtube 2 Videos zum richtigen 
Aufkleben von Pflasteren anzusehen.

Stringoperationen sind eines der ersten zentralen Themen, die jeder 
Programmierer im Schlaf beherrschen muss.
Und nein, der Ansatz aus dem geposteten Programm ist nicht tauglich. Da 
fehlt es an einem ganz wesentlichen Punkt: es gibt kein vernünftiges 
Protokoll um erst mal zuverlässig einen String zu haben, den man dann 
mittels Stringoperationen zerlegen kann um rauszufinden, was die 
Gegenstelle eingentlich mitteilen will.

> Leider ist das ja so, dass man 5 Zeichen haben muss um "fortzufahren".

Das ist aber nur so, weil es dieser Programmierer so gemacht hat. Im 
allgemeinen ist das nicht so. Genau das nennt man dann ein Protokoll. 
Dein anderes Programm wird ja nicht nur den Text
1
p_brake=0
senden, sondern da kommt üblicherweise noch ein Zeichen danach. Zb. ein 
'\n', der anzeigt "Hier ist der Text jetzt zu Ende". Und genau dieses 
Zeichen ist es, das dem Empfänger mitteilt: Jetzt ist der Text 
vollständig - du kannst mit der Auswertung anfangen.

D.h. dein erstes Ziel ist es nicht, irgendwelche Vergleiche anzustellen, 
sondern einfach nur mal den Text komplett und sicher aus dem 
Eingabestrom herauszufischen. Dazu brauchst du dieses Terminierzeichen, 
wie auch immer das in deinem Protokoll definiert ist.
Aber derartige Textübertragungen, die sich auf einer vorab bekannten 
Anzahl von Zeichen stützen, sind Mist. Ein simples Kabel abstecken, 
Kabel wieder anstecken bringt das alles durcheinander. Das ist nicht 
tauglich. Das ist eben: "Ich kann ein Pflaster aufkleben - Schwester: 
Knochensäge und Spreizer." So wird das nichts. Das ist Programmieren, 
wie sich die kleine Erna vorstellt, dass Programmieren funktioniert.

: Bearbeitet durch User
von Konrad S. (maybee)


Lesenswert?

Kaj schrieb im Beitrag #3683799:
> Peter L. schrieb:
>> if ( !strcmp(inString, "start") )
> Weißt du was da steht? Natürlich weißt du es nicht...
> Da steht:
>
1
> if( strcmp(inString, "start") != 0 )
2
>
> Das heißt soviel wie: wenn der empfangene String nicht dem String
> "start" entspricht, mach was.

Darüber sollten wir nochmal nachdenken, meinst du nicht, Kai?

von Peter L. (imax2010)


Lesenswert?

Hab ne funktionierende Lösung hingekriegt dank eines netten Helfers 
(nein nicht hier aus dem Forum). Dieser hat mir einiges Erklärt im 
Gegensatz zu hier wo's einfach heißt "Kauf dir ein Buch..."

Darauf möcht ich auch nicht näher eingehen.
Hab jetzt eine andere Frage:

Wenn ich:

...."wert.substring(9,80);"...

mache dann erhalte ich als wert bei z.b.

tstfunc=1:

garnichts also nur leer. Habe ich aber einen längeren Wert z.b.

tstfunc=123456:

dann kommt als wert auch 12345 raus. Da es ja immer die 9. Stelle sein 
wird wo die Zahlenfolge beginnt versteh ich nicht, dass wenn nur 1 steht 
der wert "leer" ist und ab 2 Zahlen dann alles passt. Mit Substring sage 
ich doch nur, dass ich die "Werte" ab Zeichen 9- xx in die andere 
variable "speichern" möchte oder?

von Mike (Gast)


Lesenswert?

Hast du die Beschreibung der Funkion Substring gelesen?
http://arduino.cc/en/Tutorial/StringSubstring

Als Bemerkung steht da: "Caution: make sure your index values are within 
the String's length or you'll get unpredictable results."

Und das ist bei dir dann wohl eingetreten

von Walter (Gast)


Lesenswert?

Peter L. schrieb:
> Hab ne funktionierende Lösung hingekriegt dank eines netten Helfers
> (nein nicht hier aus dem Forum). Dieser hat mir einiges Erklärt im
> Gegensatz zu hier wo's einfach heißt "Kauf dir ein Buch..."
>
> Darauf möcht ich auch nicht näher eingehen.

aber ich, in diesem Thread hat dir keiner gesagt "kauf dir ein Buch" 
(was ein guter Tipp ist) sondern es gab mehrere Tipps zu deinem 
Programm.
Wenn Dich hier die Leute nerven, warum fragst du dann nicht deinen 
netten Helfer?

In deinem ersten Codestück gibt es übrigens einen Überlauf wenn weder 
Start noch Stopp als String kommen

von Peter L. (imax2010)


Lesenswert?

Ja mit 9 tritt das ein stimmt (Da hab ich die doch glatt überflogen...).

.substring(8);

Hatte das aber zufällig davor mit der 8 getestet weil ich mich vertan 
habe,  da ist dann wenn hinter dem = ne 1 steht auch beim Wert als 
ergebnis die '1'. Habe ich jetzt aber '12345' hinter dem '=' so hab ich 
jetzt aber das '=' mit im Ergebnis. Irgendwie hab ich n denkfehler oder 
sowas...

von Jürgen S. (jurs)


Lesenswert?

Peter L. schrieb:
> Hab ne funktionierende Lösung hingekriegt dank eines netten Helfers
> (nein nicht hier aus dem Forum). Dieser hat mir einiges Erklärt im
> Gegensatz zu hier wo's einfach heißt "Kauf dir ein Buch..."
>
> Darauf möcht ich auch nicht näher eingehen.
> Hab jetzt eine andere Frage:
>
> Wenn ich:
>
> ...."wert.substring(9,80);"...
>
> mache ...

Oh! Mein! Gott!

Du hast im Prinzip am Anfang des Threads recht vernünftig mit der 
Verwendung von nullterminierten C-Strings angefangen (nur leider ohne 
jegliche Ahnung vom Programmieren) und bist jetzt bei lahmen 
String-Objekten gelandet.

OK, mann kann auch mit RAM-fressenden, lahmen und zur Standard-Library 
inkompatiblen String-Objekten etwas programmieren. Ist allerdings 
überhaupt nicht mein Fall, obwohl ich Arduinos programmiere. Denn das 
Programmieren mit String-Objekten artet zu einem Alptraum aus, sobald Du 
irgendwas machen möchtest, was von der handvoll 
Arduino-Komfortfunktionen für String-Objekte nicht unterstützt wird.

Aber das verstehe ich trotzdem nicht:
> "Hab ne funktionierende Lösung hingekriegt"
und
> "wenn nur 1 steht der wert "leer" ist und ab 2 Zahlen dann alles passt"

Passt an der Lösung nun doch nicht alles?

Wenn nein, dann mache ich Dir mal folgendes Angebot:
Du schreibst mal beispielhaft und möglichst genau auf, was Du als 
Kommandos wie senden möchtest, und ich mache Dir einen funktionierenden, 
beispielhaften Sketch zur Auswertung mit dem Arduino.

von Markus H. (haniham) Benutzerseite


Lesenswert?

Hi,
Nur damit ich auch mal was sage: Ich bin vor einiger Zeit auf das hier 
gestoßen: http://playground.arduino.cc/Code/CmdMessenger und konnte die 
Library bereits erfolgreich nutzen. Vielleicht kannst du ja auch was 
damit anfangen.
Gruß

von Peter L. (imax2010)


Lesenswert?

Also: ganz oben der Code vom Thread war nur aus dem Netz kopiert, 
entsprach aber nicht dem was ich brauchte. Hab aber jetzt ne Funktion 
gefunden wo mit Puffer,... gearbeitet wird (und auch verstanden) und die 
funktioniert soweit top. Die Sache ist jetzt folgende: Es kommen Befehle 
im Format p_brake=0:
an. p_brake ist nur beispiel, dieser "text" kann frei definiert werden. 
Wenn nur logiken mit 0 und 1 (also hinter dem = ) kommen ist das ja kein 
Thema weil da vergleiche ich einfach den Input mit dem was drinstehen 
sollte. Kommt jetzt aber ein Wert ..=123.456 dann ist das ja nicht 
wirklich umsetzbar. Dazu wollte ich einfach den Substringcode benutzen 
um mir immer den hinteren teil auszugeben und zu verarbeiten (vor dem = 
sind immer 7 stellen, ansonsten ginge das ja nicht)

Bsp:

p_brake=0:  -> Irgendein Output springt auf 0 oder 1 oder sonst was.
tstfunc=127.432: -> z.B. Wert der auf 7-Seg. Angezeigt werden soll.


@Markus:
Werd ich mir mal anschauen. Danke.

: Bearbeitet durch User
von Jürgen S. (jurs)


Lesenswert?

Peter L. schrieb:
> Bsp:
>
> p_brake=0:  -> Irgendein Output springt auf 0 oder 1 oder sonst was.
> tstfunc=127.432: -> z.B. Wert der auf 7-Seg. Angezeigt werden soll.

Codevorschlag für eine einfache Auswertung und zeitgleiches Blinken der 
Pin-13 LED:
1
#define BLINKLED 13
2
3
void commandExecution()
4
{
5
#define BUFSIZE 21  
6
  char buffer[BUFSIZE]; // Maximale Stringlänge plus 1
7
  if (!Serial.available()) return; // kein Zeichen verfügbar, nichts machen
8
  delay(100); // abwarten, bis kompletter Befehl empfangen wurde
9
  memset(buffer,0,sizeof(buffer)); // String-Puffer ausnullen
10
  int charcount=0; // Anzahl der empfangenen Zeichen
11
  while (Serial.available()) // Seriellen eingangspuffer auslesen
12
  {
13
    char c=Serial.read();
14
    if (c>=32 && charcount<BUFSIZE-1)
15
    {
16
      buffer[charcount]=c;
17
      charcount++;
18
    }
19
  }
20
  // Jetzt ist der Befehl eingelesen und kann ausgewertet werden
21
  if (strstr(buffer,"p_brake="))
22
  {
23
    Serial.print("Empfangen p_brake: " );
24
    int i=atoi(&buffer[8]);  // Wert in eine Integer-Variable wandeln
25
    Serial.println(i);
26
  }
27
  else if (strstr(buffer,"tstfunc="))
28
  {
29
    Serial.print("Empfangen tstfunc: " );
30
    float f=atof(&buffer[8]);  // Wert in eine Gleitkomma-Variable wandeln
31
    Serial.println(f,3);
32
  }
33
  else
34
  {
35
    Serial.print("Unbekannter Befehl: ");
36
    Serial.println(buffer);
37
  }
38
}
39
40
void setup() {
41
  Serial.begin(9600);
42
  pinMode(BLINKLED,OUTPUT);
43
}
44
45
void loop() {
46
  commandExecution();
47
  digitalWrite(BLINKLED,(millis()/1000)%2); // Pin-13 LED blinken lassen
48
}

von Peter L. (imax2010)


Lesenswert?

Danke dir Jürgen wirklich tolle und Ressourcenarme Lösung die wirklich 
sehr gut läuft. Das mit dem Auswerten ist jetzt wenn man's verstanden 
hat relativ einfach. In C bin ich noch absolut grün, komm aber langsam 
mit der syntaxstrucktur zurecht.  Hatte vorher nur n bisschen Bascom 
rumprogrammiert und sonst nur visualbasic am pc, ist halt eben ein 
anderer syntax.
Danke!

von Jürgen S. (jurs)


Lesenswert?

Peter L. schrieb:
> Das mit dem Auswerten ist jetzt wenn man's verstanden
> hat relativ einfach.

Ich sehe übrigens gerade, dass die Empfangsroutine noch nicht ganz 
narrensicher ist, änder mal die beiden Vergleichszeilen so ab, dass 
verglichen wird, ob der gesuchte String auch wirklich am Anfang der 
Zeile gefunden wird:
1
 if (strstr(buffer,"p_brake=")==buffer)
2
 und
3
 else if (strstr(buffer,"tstfunc=")==buffer)

Sonst wird z.B. ein ungültiger Befehl wie
xytstfunc=127.432:
falsch ausgewertet und nicht als ungültig erkannt.


> In C bin ich noch absolut grün, komm aber langsam
> mit der syntaxstrucktur zurecht.

Es geht nicht nur um die Syntax, sondern auch um die Library.

Wenn Du unter Arduino programmierst, mußt Du Dir darüber im klaren 
werden, dass Du nicht nur die "Arduino-Komfortbefehle" ("digitalWrite" 
oder "Serial.read" etc.) zur Verfügung hast. Von diesen Komfortbefehlen 
sind viele sogar so komplett vermurkst, dass man sie besser niemals 
verwendet. Zum Beispiel alles, was mit String-Objekten zu tun hat.

Was Du außer den Arduino-Komfortfunktionen als Library zur Verfügung 
hast, ist die AVR libc, Librarybeschreibung siehe:
http://www.nongnu.org/avr-libc/user-manual/modules.html

Und neben der C-Syntax ist es insbesondere diese Library, aus der Du ein 
paar grundlegende Funktionen kennenlernen müßtest, um Deinen Controller 
sinnvoll programmieren zu können.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.