Forum: Compiler & IDEs String neu suchen, Arduino


von Jonas R. (jonasrover)


Lesenswert?

Hallo ich habe folgendes Problem:
Ich habe das Problem das immer wenn ich einen String sende der nicht 
verglichen wird, das sich das Programm aufhängt.
Es würde mich freuen wenn Ihr mir helfen könntet da ich noch nicht so 
ganz der super Programmierer binn.
1
char inData[20]; // Allocate some space for the string
2
char inChar=-1; // Where to store the character read
3
byte index = 0; // Index into array; where to store the character
4
int leda=12;
5
int ledb=11;
6
7
8
9
void setup(){
10
pinMode(leda,OUTPUT);
11
pinMode(ledb,OUTPUT);
12
  Serial.begin(9600);
13
}
14
15
16
17
18
19
char Comp(char* This){
20
21
  while(Serial.available() > 0) // Don't read unless
22
    // there you know there is data
23
  {
24
    if(index < 19) // One less than the size of the array
25
    {
26
      inChar = Serial.read(); // Read a character
27
      inData[index] = inChar; // Store it
28
      index++; // Increment where to write next
29
      inData[index] = '\0'; // Null terminate the string
30
      
31
    }
32
  }
33
34
  if(strcmp(inData,This)  == 0){
35
    for(int i=0;i<19;i++){
36
      inData[i]=0;
37
    }
38
39
    index=0;
40
    return(0);
41
42
  }
43
  else{
44
    return(1);
45
46
47
  }
48
}
49
50
51
void loop()
52
{
53
54
55
56
  if(Comp("*grün an#")==0){
57
    digitalWrite(leda,HIGH);
58
59
  }
60
  if(Comp("*grün aus#")==0){
61
    
62
    digitalWrite(leda,LOW);
63
  }
64
    if(Comp("*rot aus#")==0){
65
    
66
    digitalWrite(ledb,LOW);
67
  }
68
  if(Comp("*rot an#")==0){
69
    digitalWrite(ledb,HIGH);
70
    
71
  }
72
  
73
      if(Comp("*Licht aus#")==0){
74
    digitalWrite(leda,LOW);
75
    digitalWrite(ledb,LOW);
76
  }
77
  if(Comp("*Licht an#")==0){
78
    digitalWrite(ledb,HIGH);
79
    digitalWrite(leda,HIGH);
80
  }
81
  
82
    if(Comp("*licht an#")==0){
83
    digitalWrite(ledb,HIGH);
84
    digitalWrite(leda,HIGH);
85
  }
86
  
87
        if(Comp("*licht aus#")==0){
88
    digitalWrite(leda,LOW);
89
    digitalWrite(ledb,LOW);
90
  }
91
92
93
}

: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

Hallo Jonas,

Jonas Röver schrieb:
> if(Comp("*grün an#")==0)
Es ist grundsätzlich, immer und überall, auch in einem String (gerade 
wenn es ums vergleichen geht) eine sehr schlechte idee, zeichen zu 
benutzen, die nicht dem englischen Alphabet angehören (bzw. nicht 
standard 7-bit ASCII zeichen)!
Guter Tipp zum Programmieren: Besorg dir eine Tastatur mit 
englischem/u.s. layout! Dann kommst du beim Programmieren gar nicht in 
die Situation "ausversehen" zeichen zu benutzen, die irgendwie, 
irgendwann, irgendwo mal probleme machen können. Alle zeichen die in 
dieser Tabelle stehen: http://de.wikipedia.org/wiki/ASCII#ASCII-Tabelle 
, also mit 0 bis 127 Codiert sind, können ohne Probleme genutzt werden. 
Alles was danach kommt... naja, kann dich im schlimmsten fall schon mal 
wochen oder monate an zeit kosten, um einen fehler zu finden.

Jonas Röver schrieb:
> das sich das Programm aufhängt
Ich glaube nicht, das sich das Programm aufhängt. Ich denke folgendes 
passiert:
Du hast 2 Strings, die du vergleichst. Der vergleich schlägt fehl, und 
deine Funktion Comp liefert eine 1 zurück... und was machst du mit der 
eins? richtig: nichts. also passiert auch nichts, und du siehst auch 
nichts, weil du die 1 nicht auswertest.
Es könnte auch noch sein, dass das Programm vielleicht doch in der
> while(Serial.available() > 0)
-Schleife hängen bleibt, warum auch immer.

Wie sendest du den String vom PC zum Arduino? Terminal-Programm? 
Welches?
Hast du die Kommunikation überhaupt schon mal getestet? Sende erstmal 
ein Zeichen vom PC zum Arduino, und sende das Zeichen einfach direkt 
wieder zurück, dann weißt du immerhin schonmal das die Kommunikation 
PC<-->Arduino funktioniert.

#############################################################

Nachtrag: (Ich lass den Text da oben jetzt stehen, einfach um meine 
Gedankengänge zu zeigen, auch wenn es schon wieder hinfällig ist)

Du hast einen Denkfehler...
In deiner Funktion Comp wartest du darauf, einen String zu empfangen...
Das bedeutet für dein Programm folgendes:
Bei jedem aufruf von Comp, wartet dein Programm auf Input von der 
Seriellenschnittstelle!
Das heißt, immer wenn du Comp aufrufst, musst du auch was an den 
Arduino senden, weil er da sonst natürlich hängen bleibt.

Ich geb dir eine kleine Denkhilfe (Pseudo-Code), wie man es machen 
könnte :
1
void loop()
2
{
3
  // Daten von der Seriellenschnittstelle abholen
4
  while(daten an seriellerschnitstelle)
5
  {
6
    dataIn[i] = serial.read()
7
    i++
8
  }
9
10
  // Strings direkt vergleichen also ohne deine Comp-Funktion
11
  if(strcmp(...) == 0)
12
  {
13
    // mach was
14
  }
15
  else
16
  {
17
    // vergleich ist fehlgeschlagen, Irgendwie sichtbar machen z.b. eine
18
    // LED aufleuchten lassen
19
  }
20
  // dataIn zurück setzen
21
}

Natürlich kann man das alles schöner, besser und schneller machen, aber 
es soll ja auch nur ein anstoß sein.

Nochmal zusammengefasst:
- (empfohlen) keine "Sonderzeichen/Umlaute" wie ä,ü,ß,€,µ, usw.
  Zeichen wie "%&*# etc, sind aber zulässig (siehe ASCII-Tabelle)
  ggf. muss auf ESC-Sequenzen geachtet werden, bin grade nicht sicher.

- Daten nur einmal abholen, dann alle vergleiche machen, und erst dann
  wieder Daten abholen

Das ist, das, was mir so auf die schnelle auffällt. Viel glück

Grüße

von Kaj (Gast)


Lesenswert?

Kaj schrieb:
> Du hast einen Denkfehler...
> In deiner Funktion Comp wartest du darauf, einen String zu empfangen...
> Das bedeutet für dein Programm folgendes:
> Bei jedem aufruf von Comp, wartet dein Programm auf Input von der
> Seriellenschnittstelle!
> Das heißt, immer wenn du Comp aufrufst, musst du auch was an den
> Arduino senden, weil er da sonst natürlich hängen bleibt.

Das ist natürlich völliger blödsinn von mir :-(
Die schleife wartet ja gar nicht auf daten, mein fehler. Aber wenn keine 
Daten empfangen werden, vergleichst du einen String, den du in die 
Funktion Comp reingibst, mit einem Array das voll mit 0 ist, der 
vergleich schlägt fehl und wir sind bei:
Kaj schrieb:
> Du hast 2 Strings, die du vergleichst. Der vergleich schlägt fehl, und
> deine Funktion Comp liefert eine 1 zurück... und was machst du mit der
> eins? richtig: nichts. also passiert auch nichts, und du siehst auch
> nichts, weil du die 1 nicht auswertest.

Grüße

(*noch immer kein Anspruch auf richtigkeit meiner auskunft :-/ )

von Karl H. (kbuchegg)


Lesenswert?

Der ganze Ansatz ist unsinnig.
Und das beginnt bereits damit, das der Empfänger nicht entscheiden kann, 
wann denn der Sender nichts mehr senden wird.
Genau dazu gibt es die Return Taste. Damit man in einem Text zb 
markieren kann: So jetzt ist der Text fertig.
Diejenigen, die noch mit einer Commandline und nicht mit klickibunti 
gelernt haben, kennen das noch. An einer Command-Line gibt man die 
Zeichen ein. Man kann ändern, mit dem Cursor hin und her fahren, Zeichen 
einfügen, zeichen löschen, was auch immer. Erst wenn man auf Return 
drückt, signalisiert man der Command Line: Soooo, fertig, meine 
Text-Eingabe steht, jetzt kannst du anfangen sie auszuwerten.

Und genauso auch hier:
Der Sender muss dem Empfänger irgendwie mitteilen: Fettich, jetzt kommt 
nichts mehr, das was du bisher gekriegt hast, das ist mein Text.

Und da sich die return Taste dafür bewährt hat, würde ich vorschlagen du 
benutzt das auch. Drückst du auf Return, dann wird das Zeichen '\n' 
übertragen. Das ist für den Arduino das Signal "Das wars, jetzt ist der 
String fertig, ich kann anfangen ihn auszuwerften"

Die Strategie ist
1
void loop()
2
{
3
  wenn ein zeichen an der seriellen Schnittstelle angekommen ist
4
  {
5
    hole das Zeichen
6
7
    ist es kein '\n'?
8
      hänge es an die bisher erhaltene Zeichenkette hinten drann
9
10
    andernfalls
11
    {
12
      // der Sender hat den Text fertig übertragen
13
      hänge noch ein '\0' Zeichen hinten drann, um aus der
14
      Zeichenkette einen String zu machen
15
16
      werte ihn aus, indem mit den vereinbarten Schlüsselwörtern
17
      verglichen wird und die Aktion durchgeführt wird
18
    }
19
  }
20
}

2 wesentliche Dinge:
Wir warten nicht darauf, das der String komplett übertragen wurde!
Wenn ein Zeichen eingetroffen ist, dann holen wir es und hängen es an 
den bisherigen Text hinten drann. Mehr nicht! Sobald das Zeichen hinten 
an den text angehängt wurde, macht das Programmm mit seiner restlichen 
Arbeit weiter.
Erst wenn ein '\n' eintrifft wissen wir: jetzt ist der vollständige Text 
da. Erst jetzt kann die Auswertung beginnen.

von Karl H. (kbuchegg)


Lesenswert?

Das ...
1
  if(Comp("*Licht an#")==0){
2
...
3
  if(Comp("*licht an#")==0){
4
...
macht man auch anders. Denn der nächste schreibt 'an' mit einem 'A', der 
übernächste schreibt überhaupt alles in Grossbuchstaben, und und und. Da 
wird man nicht fertig, wenn man alle Kombinationen in jeweils eigenen 
Abfragen auswertet.
Was man statt dessen macht ist, dass man den empfangenen String komplett 
in Grossbuchstaben umwandelt, ehe dann die Vergleicherei (natürlich mit 
den Kommandos in Grossbuchstaben) los geht. Dann spielt die genaue 
Gross-/Kleinschreibung des Benutzers keine Rolle mehr, selbst ein 
getipptes "*LiChT aN#" wird dann korrekt vom Programm als "*LICHT AN#" 
erkannt.

: Bearbeitet durch User
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.