Serielle Eingabe

Guten Morgen liebe Gemeinde,
ich möchte ein kleines Programm schreiben das im Fall, dass ich ein einziges Zeichen im Serial Monitor eingebe, etwas anderes tut als wenn ich drei Zeichen eingebe. Leider klapt das bei mir nicht. Könntet ihr mir bitte helfen?
Hier mein Code:

char eingabe[4]; //Die eingegeben Zeichen
char RIC[4] = "000"; 

void setup()
{
  Serial.begin(9600);   
  Serial.println("Eingabe: ");
  Serial.println();
}

void loop() 
{ 
  if (Serial.available() >= 3)           // warten bis drei Zeichen eingegeben wurden
  {
    for(int i = 0; i < 3 ; i++)
    eingabe[i] = Serial.read();
 
    RIC[0] = eingabe[0];
    RIC[1] = eingabe[1];
    RIC[2] = eingabe[2];

    for ( int i = 0; i < 3 ; i++)             //Ausgabe Anfang
    {
      Serial.print("Eingabe[");
      Serial.print(i);
      Serial.print("]: ");
      Serial.print(eingabe[i]);
      Serial.print("  -  ");
    }
    Serial.print("Eingabe[3]: ");
    Serial.println(eingabe[3]);
    
    for ( int R = 1; R < 3 ; R++)
    {     
      Serial.print("RIC: ");            
      Serial.print(RIC[R]);
      Serial.print("      ");
    }
    Serial.println();
    Serial.println();                        //Ausgabe Ende
  }  
  
  else if (Serial.available() == 1 && Serial.available() <=2) //warten bis ein Zeichen eingegeben wurde
  {
    eingabe[0] = Serial.read();
    RIC[0] = eingabe[0];
    if(RIC[0] == 'n')
    {
      Serial.print("Anforderung: ");
      Serial.println(RIC[0]);
    }
    else if (RIC[0] != 'n')
    { 
      Serial.println("Anforderung ungültig");
    }
  }
}

Die Zeichen kommen immer nacheinander, und SerialMonitor sendet evtl auch noch Zeilenende Zeichen.

Ich würde diese Zeilenende-Zeichen abschalten, und wenn ein Zeichen gekommen ist, kurz warten. Wenn dann immer noch nicht mehr da ist, wars das.

if (Serial.available() )
{
  if (Serial.available() < 3 )
       delay (5); // Bei 9600 Zeit für ca. 5 Zeichen
  if (Serial.available() > 1)
  {
        //read long command
  }
  else 
  {
     switch (Serial.read())
     {
      // Single char processing
    }  
  }
}

Nachtrag:

Leider klapt das bei mir nicht

Das solltest du etwas genauer beschreiben, einen krassen Fehler ( “so kann das nie gehen” ) sehe ich in deinem Code auf Anhieb nicht.

Die Zeichen werdenhintereinander versendet dabei kann es passieren daß das erste Zeichen von 3 angekommen ist und der Sketch das als 1 Zeichen Message erkennt. Dann bei den anderen 2 Zeichen nicht weiß was anfangen. Du mußt dem Arduino Zeit geben alle Zeichen zu empfangen bevor kontrolliert wird. Grüße Uwe

sonyfuchs: ich möchte ein kleines Programm schreiben das im Fall, dass ich ein einziges Zeichen im Serial Monitor eingebe, etwas anderes tut als wenn ich drei Zeichen eingebe. Leider klapt das bei mir nicht. Könntet ihr mir bitte helfen?

Du unterliegst einem Irrtum, wenn Du annimmst, Du könntest über den Serial-Monitor von Arduino nur ein einziges Zeichen an Dein Programm senden.

Das Minimum, was Du über den Serial Monitor senden kannst, ist eine "leere Zeile", also wenn Du "gar nichts" eingibst und dann auf "senden" klickst. Gesendet würden dann zwei Steuerzeichen für CR - Carriage Return (ASCII-Code 13) LF - Linefeed (ASCII-Code 10)

Sobald Du in der Zeile EINEN Buchstaben eingibst und sendest, sendet der serielle Monitor schon drei Zeichen: Den eingegebenen Buchstaben und die beiden Steuerzeichen CR und LF (ASCII 13 und 10).

Wenn Du in der Zeile DREI Buchstaben eingibst, werden fünf Zeichen gesendet, die drei Buchstaben und am Ende der Zeile wieder CR und LF.

Dein Fehler ist die komplett verquere Logik, mit der Du Zeichen einlesen möchtest: Zeichen treffen in unendlich schnarchnasig langsamer Geschwindigkeit EINZELN im seriellen Eingangspuffer ein und nicht alle gleichzeitig.

D.h. die Zeichen werden nacheinander gesendet. Dann kannst Du im Arduino noch 100 loop-Durchläufe lang null Zeichen im Eingangspuffer haben. Dann kommt das erste Zeichen im Eingangspuffer an, 100 Loop-Durchläufe später das zweiten Zeichen Noch 100 Loop-Durchläufe das dritte Zeichen etc.

Ob das letzte Zeichen einer Zeile angekommen ist, müßtest Du nicht danach prüfen, wieviele Zeichen angekommen sind, sondern ob das Zeilenendezeichen ASCII-13 oder ASCII-10 eingetroffen ist. Dann ist die von seriellen Monitor gesendete Zeile vollständig.

@jurs, Du unterliegst einem Irrtum, wenn Du annimmst, Du könntest über den Serial-Monitor von Arduino nicht nur ein einziges Zeichen an Dein Programm senden.

Bei mir hat der SerialMonitor die Option ( CR / LF / CRLF / nichts ) als Zeilenende zu senden, falls ich das richtig verstanden habe.

Alle Buchstaben der Eingabezeile gehen beim Betätigen der Enter - Taste auf die Reise, evtl. inclusive der definierten Zeilenende-Zeichen. Das ist zwar schneller als ich tippen kann, jeder sketch sollte jedoch damit rechnen, dass ( 0 / 1 / mehr ) Zeichen pro loop-Durchlauf ankommen.

Ausserdem kann - theoretisch immer mal - ein Zeichen verloren gehen, und irgendwie sollte sich eine serielle Kommunikation wieder synchronisieren. Dieser Einwand ist sehr berechtigt. Und ein Zeilenende-Zeichen bietet sich dafür auch immer an.

michael_x:
Bei mir hat der SerialMonitor die Option ( CR / LF / CRLF / nichts ) als Zeilenende zu senden, falls ich das richtig verstanden habe.

Ahhh, Du meinst die Datei preferences.txt, manuell Editieren, Option “serial.line_ending=3” und dass man dort was anderes eintragen könnte?

Stimmt, da bin ich bei meiner Antwort wirklich davon ausgegangen, dass er das nicht geändert hat, sondern den seriellen Monitor von Arduino in der gelieferten Grundkonfiguration verwendet.

Edit/Nachtrag: Beispielcode zum Einlesen von der seriellen Schnittstelle mit dem “Seriellen Monitor” in Standardkonfiguration

void setup()
{  
    Serial.begin(9600);    //Serielle Ausgabe initialisieren
} 


char eingabe[4]; //Die eingegeben Zeichen

boolean readCommand(){
  static byte count=0;
  char c;
  if (Serial.available()==0) return false; // nix zu lesen da
  if (count==0) memset(eingabe,0,sizeof(eingabe)); // eingabe-Puffer löschen
  c=Serial.read();
  if (c==13) 
  {
    count=0;
    return true; // CR Steuerzeichen erkannt, eingabe ist komplett
  }  
  else if (c>=32 && count<sizeof(eingabe)-1)
  {
    eingabe[count]=c;
    count++;
  }  
  else ; // alle anderen Steuerzeichen ignorieren
  return false; 
}


void loop()
{
  if (readCommand())
  {
    Serial.print("Eingegeben: ");
    Serial.print(eingabe);
    Serial.print("  (");
    Serial.print(strlen(eingabe));
    Serial.println(" Zeichen)");
  }
}

jurs:
Ahhh, Du meinst die Datei preferences.txt, manuell Editieren, Option “serial.line_ending=3” und dass man dort was anderes eintragen könnte?

Oh, geht das auch so kompliziert ? :wink:
Ich dachte an das da:

SerialMonitor.jpg

michael_x: Ich dachte an das da:

Da muß ich wohl inzwischen betriebsblind sein, weil ich da nie dran herumschraube.

Also der von mir gepostete Beispielcode gilt jedenfalls für die Einstellung: "Sowohl NL als auch CR" oder die Einstellung "Zeilenumbruch (CR)"