Forum: Mikrocontroller und Digitale Elektronik Serielle Daten bei Arduino auslesen


von Jul H. (jules03)


Lesenswert?

Hallo,

wie man am Betreff bereits erkennt, kennt es darum die serielle Daten 
vom Arduino auszulesen. In meinem Projekt sende ich zum Arduino über den 
seriellen Monitor immer ein char z.B. 'g'.
Je nachdem was angekommen ist will ich eine RGB LED leuchten lassen.

Dies gelingt mir auch in der loop(), jedoch möchte ich auch die 
Helligkeit variieren und lese die gesendeten Daten einfach in der 
jeweiligen Unterfunktion (green_led()) nochmal aus und hier liegt das 
PROBLEM.
2 bis 3 mal funktiniert meine Funktion, dann passiert murks.
Ich kann dann nicht mehr zwischen den Funktionen in der loop() wechseln 
oder muss das char 2 mal senden, damit es registriert wird.

Da ich noch ein Neuling in der Sache bin, hoffe ich ihr könnt mir 
helfen..


/////////////CODE////////////

int green = 12;
int red = 11;
int blue = 9;
int color;
int brightness;
int bright = 0;


void setup() {
  Serial.begin(9600);
  pinMode(green, OUTPUT);
  pinMode(red, OUTPUT);
  pinMode(blue, OUTPUT);
  bright = 205;
}

void loop() {
  if(Serial.available() > 0) {
    color = Serial.read();
    char rec = color;
    Serial.println(color);
    Serial.println(rec);
  }

  if(color == 'a') {
      turn_off();
  }

  else if(color == 'g') {
      green_led();
  }

}

/////////////// Funktionen ///////////////

int turn_off() {
  analogWrite(green, 0);
  analogWrite(red, 0);
  analogWrite(blue, 0);
}

int green_led() {
  analogWrite(green, bright);
  analogWrite(red, 0);
  analogWrite(blue, 0);

  if(Serial.available() > 0) {
    brightness = Serial.read();
    char rec = brightness;
    Serial.println(brightness);
    Serial.println(rec);
  }

  if(brightness == 'u') {
    bright = bright + 50;
    if(bright >= 255)
      bright = 255;
  }
  else if(brightness == 'd') {
    bright = bright - 50;
    if(bright <= 5)
      bright = 5;
  }
}

von Einer K. (Gast)


Lesenswert?

Hmm...

So einen Parser habe ich noch nicht gesehen.

Und wenn du das Problem hast, dass es nur manchmal funktioniert, dann 
solltest du ihn nochmal überarbeiten.

In welchem Format sendest du die Daten?
Leider kann ich das aus dem Code nicht erkennen.



Darf ich dir den "Arduino CmdMessenger" ans Herz legen?

von Jul H. (jules03)


Lesenswert?

Also ich sende immer ein char, oder meinst das die Bitbreite?
Ich glaube das wären bei dem Arduino 8Bit.

Was ist denn der Arduino CmdMessenger ?

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Jul H. schrieb:
> 2 bis 3 mal funktiniert meine Funktion, dann passiert murks.
Kannst du das mal naeher beschreiben?
Was genau passiert? Und was genau erwartest du, was passieren 
sollte?

von tnec2ym (Gast)


Lesenswert?

Jul H. schrieb:
> Was ist denn der Arduino CmdMessenger ?

Erster und zweiter Treffer bei Google, wenn du nach "Arduino 
CmdMessenger" suchst

von Jul H. (jules03)


Lesenswert?

Ich erwarte, wenn ich ein 'g' sende, dass analowWrite(green, bright) 
ausgeführt wird (also dass die grüne LED leuchtet) und wenn ich ein 'a' 
sende, soll die LED ausgehen. Das funktioniert auch alles mit dem 
Serial.read(), jedoch möchte ich die LED, wenn sie grün ist auch 
verschieden hell leuchten lassen -> mit 'd' weniger und mit 'u' mehr.

Ich vermute das Problem liegt bei den beiden Serial.read() Funktionen, 
vielleicht wird eine Funktion schon ausgeführt, wenn die nachricht noch 
nicht komplett angekommen ist und dann kommt es zu diesen bugs -> man 
muss 2 mal 'g' senden damit es ausgeführt wird oder die funktion wird 
garnicht ausgeführt.

von fast (Gast)


Lesenswert?

du hast zwei Serial.read in deinem Programmablauf.

Angenommen du liest beim 2. read das ‘a‘ ein, dann
ist das bei dir nicht vorgesehen.

Abhilfe: •ein• read und schau dir state machines an

von Bastian W. (jackfrost)


Lesenswert?

Hi,

du löscht nach dem abarbeiten den Inhalt deiner Variablen die du für die 
if Abfragen nutzt nicht. Zudem ist es so das der neue Wert für 
"brightness"
nur eingelesen wird wenn die Zeit zwischen dem "g" und dem neuen 
Buchstaben kürzer ist als die Zeit die das Programm braucht bis es
1
if(Serial.available() > 0) {
2
    brightness = Serial.read();
3
    char rec = brightness;
4
    Serial.println(brightness);
5
    Serial.println(rec);
6
  }

erreicht. Wenn nicht dann wird das ausgeführt was noch in brightness 
drinnen steht. Das Programm wartet ja nicht bis was da ist , sondern nur 
wenn was gekommen ist wird der Wert eingelesen und verarbeitet.

Du brauchst also eine state machine die nach dem "g" die nachfolgende 
Eingabe verarbeitet egal wann sie kommt.

Gruß JackFrost

von fop (Gast)


Lesenswert?

Vermutlich ist die Funktion green() schon durch bis das U oder das D 
ankommen.
Außerdem solltest Du sicherstellen, dass ein Buchstabe nur genau einmal 
ausgewertet wird.
Und überhaupt, wenn Du schon lauter verschiedene Buchstaben benutzt, 
werte an einer Stelle alle Möglichkeiten aus. Ansonsten läuft das 
irgendwann aus dem Ruder und Du empfängst eine Farbe, wenn Du bei der 
Helligkeit bist und umgekehrt.

von Joachim B. (jar)


Lesenswert?

am einfachsten ist doch ein vollständiges Komando senden

green200<ENTER> (mit CR/LF)

wenn der Ardu CR sieht Text übernehmen Text prüfen ob green drin ist und 
ob danach noch 1-3 Ziffern kommen, dann das Komando ausführen

solange der Ardu CR nicht sieht Zeichen sammeln bis CR oder Buffer voll, 
dann Buffer leeren und verwerfen!

Beitrag "Re: Hilfe bei Klingeltrafo & ESP32"

so am Ardu und ESP
1
void serialEvent(void) 
2
{ while (Serial.available()) 
3
  { char incomingByte = (char)Serial.read();
4
    if(incomingByte == 13)  // Wenn das Enter ankommt
5
    { serial_in_buff[chr_cnt] = '\0';
6
      strcpy(serial_in_command, serial_in_buff);
7
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff)); // 30.554 Bytes
8
      chr_cnt = 0;
9
      stringComplete = true;
10
    }
11
    else // Falls kein Enter kommt muss der Text gespeichert werden in dem inText Array
12
    { if(isprint(incomingByte))
13
      { if(chr_cnt<(MAXBUFFER-2))
14
          serial_in_buff[chr_cnt++] = incomingByte;
15
        else
16
        { Serial.println(F("serBUF ov-> DEL"));
17
          memset(&serial_in_buff[0], 0, sizeof(serial_in_buff)); // 30.554 Bytes
18
          memset(&serial_in_command[0], 0, sizeof(serial_in_command)); // 30.554 Bytes
19
//          *serial_in_command=0;
20
          chr_cnt=0;
21
        } // if(chr_cnt<(MAXBUFFER-2))
22
      } // if(isprint(incomingByte))
23
    } // if !(incomingByte == 13)
24
  } // while (Serial.available()) 
25
} // void serialEvent()

: Bearbeitet durch User
von fop (Gast)


Lesenswert?

Joachim B. schrieb:
> am einfachsten ist doch ein vollständiges Komando senden

Für ihn evtl. nicht. Dann braucht er nämlich so was wie eine 
Statemachine zur Auswertung.
Wenn ein R ein R ist, egal wann und nach was es kommt, vereinfacht dass 
die Auswertung. Und selbst damit tut er sich ja noch schwer.

von Einer K. (Gast)


Lesenswert?

fop schrieb:
> Wenn ein R ein R ist, egal wann und nach was es kommt, vereinfacht dass
> die Auswertung.

Einen solchen primitiven Parser habe ich gerade vorgefunden.

Den kann ich hier ja mal zeigen:
(evtl. hilfts ja)
1
enum Option
2
{
3
  WrOff    = 12,
4
  WrOn     = 13,
5
  ShuntOff = 14,
6
  ShuntOn  = 15
7
};
8
9
void serialEvent() 
10
{
11
    switch(Serial.read())
12
    {
13
       case ShuntOn :  SHUNT_Set(true);
14
                       break; 
15
                       
16
       case ShuntOff:  SHUNT_Set(false);
17
                       break; 
18
                       
19
       case WrOn    :  Wait(); 
20
                       WR_Set(true);
21
                       break; 
22
                       
23
       case WrOff   :  Wait(); 
24
                       WR_Set(false);
25
                       break; 
26
    }
27
}
OK, der ist so primitiv, dass das Wort Parser schon fast eine 
Übertreibung ist.
Aber bei dieser Anwendung könnte es reichen.

von Jul H. (jules03)


Lesenswert?

Danke für die vielen guten Antworten!!!

Ich habe mich über FSM informiert und meinen Code überdacht :)
Jetzt klappt alles nach Plan !!!

von Volker K. (tobel)


Lesenswert?

Jul H. schrieb:
> Danke für die vielen guten Antworten!!!
>
> Ich habe mich über FSM informiert und meinen Code überdacht :)
> Jetzt klappt alles nach Plan !!!

Schön das du dein Problem gelöst hast.

Leider hilft deine Schlußantwort niemandem weiter, der beim durchsuchen 
des Forums ein ähnliches Problem hat.

Schön währe es, wenn du abschließend deine Problemlösung hier aufzeigen 
würdest, so könnte der Trööt auch anderen helfen.

Gruss Volker

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.