Kurze Unterbrechung eines "Zustands" ohne großen Rechenaufwand

Hallo,

ich habe hier zwei LEDs, die nur dann nicht leuchten sollen, wenn zwei bestimmte Knöpfe [u]gleichzeitig[/u] gedrückt sind.

Hierfür habe ich bisher diesen Code verwendet:

void syncronAbfrage01()
{
  if (Knopf_1_State == 1 && Knopf_5_State == 1 )
  {
    digitalWrite(LED_1,LOW);
    digitalWrite(LED_5,LOW);
  }
  else
  {
    digitalWrite(LED_1, (LEDbit&1)==1?HIGH:LOW);
    digitalWrite(LED_5, (LEDbit&16)==16?HIGH:LOW);
  }

So bekommen sie aber (zum jetzigen Zeitpunkt) ca. 8000 Mal pro Sekunde den in LEDbit hinterlegten Zustand übermittelt.

Da es nicht notwendig ist ihnen so oft zu "sagen" wie sie zu leuten haben, frage ich mal hiermit in die Runde, ob man das "eleganter" lösen kann. Falls ja, interessiert mich natürlich auch wie. XD

Gruß Chris

Hai,

wie wäre es so:

  1. Knopf 1 abfragen - Zustand speichern
  2. Knopf 2 abfragen - Zustand speichern
  3. Wenn sich Zustand Knopf 1 oder Knopf 2 geändert hat: Ermitteln wie die LEDs zu leuchten haben und Pins entsprechend schalten andernfalls wieder zum ersten Schritt

Gruß, Ralf

Würde mal so sagen: Entweder man fragt die Taster im Interrupt ab, der ja - prellen jetzt mal weggedacht - nur bei einer Status-Änderung der Taster kommt (auf Change prüfen), oder du machst es weiter in einer Loop und gibst einer zusatzlichen Status-Variable dann halt immer den entsprechenden Wert. Das musst du dann zwar nach wie vor so machen, könntest aber erst danach den selben Wert noch mal prüfen und entsprechend (einem bereits vorhandenem oder eben neuen Zustand) reagieren und die LED's schalten. Das spart dann einiges an Zeit in der Loop. Per ISR wäre sinniger - spart am (aller-) meisten, weil die Hardware für dich denkt.

boolean BothLedsAreON = false;

void syncronAbfrage01()
{
  if (Knopf_1_State == 1 && Knopf_5_State == 1 )
  { if BothLedsAreON 
    { // do nothing
    }
    else
    { // switch both LED's ON, save state of LEDs separatly ?
      BothLedsAreON = true;
    }
  }
  else
  { // switch both LED's OFF, save state of LEDs separatly ?
    BothLedsAreON = false;
  }
}

Dem Dino ist das übrigends ziemlich wurscht, wie oft er in welcher Zeit die LOOP wiederholen kann. Das macht er ungebrochen bis zum Skt. Nimmerleinstag - und er wartet auch Geduldig, bis irgendwelche Interrupts beendet wurden, delay's (endlich) zu Ende gelaufen sind. Auch stört es den Dino nicht, wenn irgendwo ne Endlosschleife mit WHILE oder DO - WHILE mangels Abbruchkriterium niemals zurückkehren - dann hat er halt frei. :grin:

Bei einem Code, welcher in der Loop vielleicht nur ein paar Taster auf Statui abfragt, einigen Sensoren Daten entlockt, mit LEDs ein bischen Licht macht oder auch sonstwie Töne von sicht gibt, ist das alles nicht tragisch - dafür ist der Hobel sicher schnell genug.

Wird's aber dann doch im Laufe des/eines Projektes immer diffizieler und komplexer, sollte man schon mal auch die Laufzeit einer Loop achten. Insbesondere, wenn so by the way hier und da komplexe mathematische Berechnungen stattfinden oder Daten angenommen, berechnet und auch gleich wieder berschickt werden ..... was alles (reichlich) Zeit kosten kann. Da geht in einer Loop schnell auch mal ein mittelmäßig lang gedrückter Taster einfach so unter.

Umgekehrt kann man sein Programm auch dahingehend ausbremsen, wenn alles mögliche via Interrupt realisiert wurde. Der arme Dino kann leider (wie Männer ?!) nur eine Sache gleichzeitig. Und wer sich dann nicht an die Regel hält ISR's so klein wie möglich zu proggen (oder eben auch nicht kann, weil nicht anders geht), darf sich über gleichartige "Ausfälle" auch nicht wundern.

Falls es jemand vergessen haben sollte: Ein Arduino - prinzipiell egal welcher - ist kein Power-PC ! Der ist eher wie mein ehemaliger Nachbar: Programmiert darauf 1x am Tag den Hof und die Einfahrt zu fegen und wehe, einer kommt mit nem Bier daher .....

Danke für den langen Text.

Ich möchte das Problem ohne Interrupts lösen. Leider verstehe nicht was Du mit BothLedsAreON = false; meinst, obwohl ich mir der Bedutung von Pseudocode bewusst bin.

Ich bitte um Erleuchtung. :roll_eyes:

Gruß Chris

Die Erleuchtung steht ganz oben mit

boolean BothLedsAreON = false;

sprich als eine global definibierte Variable vom Typ boolean (wahr oder falsch) mit initialisierung = falsch. Also beide LEDs aus. Das kannst du am Quelltext-Anfang so machen oder dort nur die var definieren mit.

boolean BothLedsAreON;

Diese muss aber späterstens im SetUp einen definierten Wert bekommen, sprich:

BothLedsAreON = false;

Du siehst, was ich meine ? Nochmal alle 3 Zeilen: boolean BothLedsAreON; BothLedsAreON = false; (das klappt nicht immer so mit Leerzeichenversatz....) boolean BothLedsAreON = false;

I hope all BRAIN-LEDS are now constantly ON !

Danke. Ich muss den Code glaube ich sich erst "setzen lassen". XD

Bekomme es grad nicht in die Birne.

Dank Dir soweit!

Gruß Chris

Chris72622: Danke. Ich muss den Code glaube ich sich erst "setzen lassen". XD

Aber hast Du Dir mal angesehen und durchgegrübelt, was ich etwas weiter oben geschrieben habe? Könnte das ein Weg für Dich sein?

Gruß, Ralf

Hallo,

danke Euch Beiden. TERWIs “Variante” konnte ich jetzt umsetzen, bin jedoch auf ein weiteres Problem gestoßen.

Wenn die beiden Tasten gedrückt gehalten werden gehen, gehen die LEDs aus.

Trotzdem ist es aber z.B. über andere, parallel abzuarbeitenden Funktionen noch immer möglich, während der Zeit, in der die beiden Tasten gedrückt gehalten werden, die LEDs wieder einzuschalten.

Dies ohne Verwendung von delay möglichst elegant zu unterbinden ist nun mein Problem.

Darüber, dass diese Anforderung von meiner im Eröffnungsposting geforderten Frage abweicht bin ich mit im klaren. :expressionless:

Gruß Chris

Wieso gehen die LEDs aus, wenn beide Taster (BothLedsAreON == TRUE) gedrückt sindd ? Hast du das einschalten in die falsche Bedingung gesetzt ?

Wenn BothLedsAreON vor dem Setup definiert wurde (und das sollte / muss so), dann ist diese Variable global und von allen anderen Funktionen auch "benutzbar". D.h., du sollte in deinen anderen Routinen, die irgendwas an den LEDs schalten & walten ebenfalls diese Var. prüfen. Ist sie WAHR -> if (BothLedsAreON) { return } liegt also immer noch der Status beider gedrückter Schalter vor und die Funktionen sollten dann eben nichts machen.

Ein delay() bewirkt für diese Zustandsprüfung absolut gar nichts - es hält eben nur den Dino für die angegebene Zeit und der macht derweilen eben absolut gar nichts -> schläft.

Delay ist eigentlich nur dann zu verwenden, wenn man definiert eine Zeit warten will / muss, etwa wenn sich z.B. ein Sensor oder sonst was an Hardware initialisiert und man bewusst warten muss / sollte, bis es weitergehen kann. Oder in der Test-/Entwicklungsphase, wenn man sich am Monitor mit SerialPrint etwas ausgeben lassen will und möchte es dann nebenbei auch noch lesen / mitverfolgen können - dann macht 1 ( ! ) definiertes delay in der LOOP Sinn. Sonst eingentlich nicht.

Wartet man auf wichtige Ereignisse und sind diese zudem zeitkritisch oder (extrem) kurz, klappt so was mit Abfrage in der Loop eher nicht - da muss dann schon ein Inerrupt herhalten. Vorausgesetzt das "Ereignis" kann an einem Pin des Dion's "ziehen". Z.B. Taster oder bei externer Hardware so was wie ein IRQ-Ausgang. GPS- oder manche Kommunikations-Module haben so was z.B. um zu signalisieren, das aktuelle Daten vorliegen und auf Abfrage warten.

TERWI: Wieso gehen die LEDs aus, wenn beide Taster (BothLedsAreON == TRUE) gedrückt sind? Hast du das einschalten in die falsche Bedingung gesetzt ?

Passt doch. Lies nochmal seinen ersten Post, so wollte ers ja haben.

Ja, das stimmt.

Hab es jetzt einfach so gemacht, dass die Funktionen die dazwischenfunken einfach an die Bedingung geknüpft sind ob beide Knöpfe gedrückt sind oder nicht. Auf der einen Seite simpel auf der anderen eine weitere "wilde" "if-Verzweigung" in meinem immer surrealer anmutenden Programmcode. :fearful:

Gruß Chris