Go Down

Topic: For Schleife geht nicht (Read 1 time) previous topic - next topic

Doc_Arduino

Hallo,

Zwischenfrage. Die Abspielfunktionen myDFPlayer.playMp3Folder(5) arbeiten blockierend?
Wenn ich dessen Code richtig verstehe?
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

das abspielen kann nur blockierend arbeiten, sonst würde das mit dem delay nicht funktionieren. Wenn man das delay nicht blockierend umbaut, würde es den ersten Sound nochmals abspielen, die Funktion würde immer aufgerufen solange der Button gedrückt ist. Der Button muss bei dem hier aber gedrückt werden, sonst läuft das alles nicht durch. Katze beißt sich in den Schwanz. Deswegen mein Favorit switch case, weil damit kannste dir klare Zustände bauen ohne dich in einem wilden if elseif Wollknäul zuverfitzen.

fehlende Variablen und Lib ergänzen ...
Code: [Select]

const byte pin_Taster = 2;
const byte pin_LED13 = 13;

void setup() {
  pinMode(pin_Taster, INPUT_PULLUP);
  pinMode(pin_LED13, OUTPUT);
}

void loop() {

  steuerung();

}


void steuerung ()
{
  enum state {NICHTS, SOUND, WAIT_FIRE, FIRE, AUS};
  static state zustand = NICHTS;
  static unsigned long zeitmerker = 0;

  switch (zustand) {
    case NICHTS:
                if (update_Taster() ) {         // Tasterabfrage
                  zustand = SOUND;
                }
                break;

    case SOUND:
                digitalWrite(pin_LED13, HIGH);
                myDFPlayer.playMp3Folder(5);
                zeitmerker = millis();          // Zeit merken für nächsten Vergleich
                zustand = WAIT_FIRE;
                break;

    case WAIT_FIRE:  
                if ( millis() - zeitmerker > 1500) {
                  zustand = FIRE;
                }
                break;          

    case FIRE:
                buttonDownTime = millis();
                torpedoTime = millis();
                torpedoPushes++;
                ignoreUp = true;
                myDFPlayer.playMp3Folder(1);
                zustand = AUS;
                break;

    case AUS:
                digitalWrite(pin_LED13, LOW);
                zustand = NICHTS;
                break;

    default:    zustand = AUS;
                break;
  }

}


bool update_Taster()
{
  static unsigned long last_ms = 0;
  static bool state = false;

  if (millis() - last_ms > 30) {
    last_ms = millis();
    state = !(digitalRead(pin_Taster));
  }
  return state;
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Trace841

Hallo,

das abspielen kann nur blockierend arbeiten, sonst würde das mit dem delay nicht funktionieren. Wenn man das delay nicht blockierend umbaut, würde es den ersten Sound nochmals abspielen, die Funktion würde immer aufgerufen solange der Button gedrückt ist. Der Button muss bei dem hier aber gedrückt werden, sonst läuft das alles nicht durch. Katze beißt sich in den Schwanz. Deswegen mein Favorit switch case, weil damit kannste dir klare Zustände bauen ohne dich in einem wilden if elseif Wollknäul zuverfitzen.

fehlende Variablen und Lib ergänzen ...
Code: [Select]

const byte pin_Taster = 2;
const byte pin_LED13 = 13;

void setup() {
  pinMode(pin_Taster, INPUT_PULLUP);
  pinMode(pin_LED13, OUTPUT);
}

void loop() {

  steuerung();

}


void steuerung ()
{
  enum state {NICHTS, SOUND, WAIT_FIRE, FIRE, AUS};
  static state zustand = NICHTS;
  static unsigned long zeitmerker = 0;

  switch (zustand) {
    case NICHTS:
                if (update_Taster() ) {         // Tasterabfrage
                  zustand = SOUND;
                }
                break;

    case SOUND:
                digitalWrite(pin_LED13, HIGH);
                myDFPlayer.playMp3Folder(5);
                zeitmerker = millis();          // Zeit merken für nächsten Vergleich
                zustand = WAIT_FIRE;
                break;

    case WAIT_FIRE:   
                if ( millis() - zeitmerker > 1500) {
                  zustand = FIRE;
                }
                break;         

    case FIRE:
                buttonDownTime = millis();
                torpedoTime = millis();
                torpedoPushes++;
                ignoreUp = true;
                myDFPlayer.playMp3Folder(1);
                zustand = AUS;
                break;

    case AUS:
                digitalWrite(pin_LED13, LOW);
                zustand = NICHTS;
                break;

    default:    zustand = AUS;
                break;
  }

}


bool update_Taster()
{
  static unsigned long last_ms = 0;
  static bool state = false;

  if (millis() - last_ms > 30) {
    last_ms = millis();
    state = !(digitalRead(pin_Taster));
  }
  return state;
}


Hallo,

danke für die Antwort.

Ich glaube nicht, dass die Abspielfunktion blockierend arbeitet. Wenn ich das Delay und den Sound für den Taster rausnehme, gibt es ja nur die Tasterabfrage für das gedrückt halten und den entsprechenden Variablen, die sich dabei ändern, woraus dann resultiert, dass der Lichteffekt läuft. Während der Lichteffekt läuft, wird die Sounddatei dafür abgespielt.

Nehme ich nur das Delay raus, wird der Sound (5) gar nicht erst abgespielt und das Programm läuft wie gewohnt weiter. Also Lichteffekt plus entsprechenden Sound.

Bei dem von dir vorgeschlagenen Code muss ich erstmal durchblicken und verstehen und dann noch gucken wo bei mir einbauen :D

ElEspanol

Ich glaube, dass der player nur den Abspielbefehl bekommt und ansonsten nichts mit dem Arduino zu tun hat. Also blockierungsfrei.

Nalp

Hi,

das Abspielen von zwei Tönen oder aber das dreifache "Feuern" ist im Prinzip die gleiche Problematik, deswegen hast du dort vermutlich auch wieder Probleme gehabt. Es geht schließlich jedes Mal darum, etwas zeitgesteuert zu starten.

Und noch eine kleine Ergänzung: delay() muss nicht falsch sein. Wenn es für deine Anforderungen ausreicht, dass während des Tons keine Eingabe und auch sonst nichts gemacht werden soll, dann kannst du das ruhig verwenden. Nur wenn du  achen parallel machen willst (z.B. während des Abspielens eine LED blinken etc.), oder "schöneren" Code haben willst, ist millis() nötig. Das kann man aber auch an kleineren Beispielen gut lernen ;)

Ich will auch nochmal wiederholen, dass es lohnenswert sein könnte, einfache Beispiele selbst zu schreiben und versuchen, diese komplett zu verstehen. Dann fällt es auch in größeren Anwendungen irgendwann leichter, durchzublicken.. Beispiele gibt es zuhauf im Internet, z.B. hier.

Beste Grüße
Jan

Doc_Arduino

Hallo,

okay, auch wenn play nicht blockiert, wird das erstmal laufen, wenn Prinzip verstanden ist bauste dir ein case ein der den Zählerstand von torpedoPushes abfragt. Wenn noch nicht erreicht wechselt du den Zustand wieder auf SOUND, wenn erreicht, Ende AUS. Eigentlich ganz einfach.  ;)   switch case sollte verstanden werden bevor du dran rumfummelst. Entscheidend ist ob du im aktuellen case wartest und dort immer alles wiederholst bis zum Wechsel oder ob du einen case nur einmal durchläufst, zum Nächsten wechselst und dort wartest und dann weitere Aktionen ausführen lässt. usw.


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Trace841

Hallo,

okay, auch wenn play nicht blockiert, wird das erstmal laufen, wenn Prinzip verstanden ist bauste dir ein case ein der den Zählerstand von torpedoPushes abfragt. Wenn noch nicht erreicht wechselt du den Zustand wieder auf SOUND, wenn erreicht, Ende AUS. Eigentlich ganz einfach.  ;)   switch case sollte verstanden werden bevor du dran rumfummelst. Entscheidend ist ob du im aktuellen case wartest und dort immer alles wiederholst bis zum Wechsel oder ob du einen case nur einmal durchläufst, zum Nächsten wechselst und dort wartest und dann weitere Aktionen ausführen lässt. usw.


Ich habe das Gefühl, dass ich mir früher oder später den gesamten Code selbst schreiben werde. Da habe ich dann auch nicht das Problem etwas in einen bestehenden Code einbinden zu müssen, was so wie der Code jetzt geschrieben ist, vielleicht gar nicht "einfach so" geht.


Ich glaube, dass der player nur den Abspielbefehl bekommt und ansonsten nichts mit dem Arduino zu tun hat. Also blockierungsfrei.

So hatte ich die Einbindung des DFPlayers auch verstanden. Der bekommt ja über serial  nur den Befehl eine bestimmte Datei zu starten.


Und noch eine kleine Ergänzung: delay() muss nicht falsch sein. Wenn es für deine Anforderungen ausreicht, dass während des Tons keine Eingabe und auch sonst nichts gemacht werden soll, dann kannst du das ruhig verwenden. Nur wenn du  achen parallel machen willst (z.B. während des Abspielens eine LED blinken etc.), oder "schöneren" Code haben willst, ist millis() nötig. Das kann man aber auch an kleineren Beispielen gut lernen ;)


Ich glaube, mit dem Delay kann ich in diesem Fall leben. Schade ist nur, dass ich eine flackernde und zugleich fadende LED für das Antriebsleuchten habe. Dieses faden wird während dem Delay natürlich unterbrochen.

Naiv wie ich bin, dachte ich, dass es hier einen einfachen millis Ersatz für das Delay gibt :D

ElEspanol

Ich glaube, mit dem Delay kann ich in diesem Fall leben. Schade ist nur, dass ich eine flackernde und zugleich fadende LED für das Antriebsleuchten habe. Dieses faden wird während dem Delay natürlich unterbrochen.
Schlechte Idee. Und die Begründung lieferst du ja gleich mit.

Trace841

Schlechte Idee. Und die Begründung lieferst du ja gleich mit.
Ja, das ist mir klar. Denn genau darum ging es in dem Thread ja bisher. Delay zu vermeiden. Aber um das zu vermeiden, habe ich ja einige Vorschläge bekommen. Diese machen aber ein neu-, bzw. umschreiben des Codes notwendig. Dazu bin ich noch nicht in der Lage.

Welche Idee (außer neu-/umschreiben) hast du denn um genau den Effekt zu erzielen, den ich jetzt mit Delay habe, nur eben ohne Delay, so dass meine Antriebs-LED nicht unterbrochen wird?

ElEspanol

Poste mal deinen aktuellen Code, Schaltplan und das iso der sd-Karte. Vielleicht packt mich ja mal der Ehrgeiz und ich baue es nach und schaue es mir genauer an.
Und wenigstens eine Beschreibung, für was das ganze ist und ggf. der Link, wo es herkommt.

combie

#55
Jun 18, 2019, 07:07 pm Last Edit: Jun 18, 2019, 07:17 pm by combie
Quote
Welche Idee (außer neu-/umschreiben) hast du denn um genau den Effekt zu erzielen, den ich jetzt mit Delay habe, nur eben ohne Delay, so dass meine Antriebs-LED nicht unterbrochen wird?
Du könntest dein Dimmdingen in yield() verlagern, dann kannst du dein delay() beibehalten.


-----------
Quote
Dazu bin ich noch nicht in der Lage.
Dann versetze dich in die Lage!

Das Konzept "Zeitabhandlung mit millis()" und "Nebenläufigkeit" ist nur auf den ersten Blick kompliziert.
Das kann jeder verstehen und anwenden.
Es dauert allerdings manchmal etwas, bis der Groschen fällt.
Wichtig: Er muss bei dir fallen.

Das heißt, du solltest solange mit dem Konzept spielen, bis es richtig sitzt.
Und dann erst daran gehen, es bei dir einzubauen.

Tipp:
Der Kopf ist rund, damit das Denken die Richtung ändern kann.


---------

Ablaufsteuerung
Meine Standardantwort zu Ablaufsteuerungen:
Quote
Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay, 
--
Blink Without Delay
Der Wachmann
--
Multitasking Macros
Intervall Macro
Ein schwarzes Schaf, zur rechten Zeit, erspart den Streit, bringt Einigkeit.

ElEspanol

Na ja, yield ist nun wirklich keine Lösung, um das Lernen der wichtigsten Basics zu umgehen.

combie

Ja, mag sein...

Es ist allerdings eher die innere Ausrichtung unseres Trace841 welche modifiziert werden sollte.
Leider sind meine Ärmchen zu kurz.
Das muss er/sie/es selber machen.

Und wenn das verstehen von Nebenläufigkeit mit yield() dahin führt, soll es mir recht sein.
Wenn nicht, auch gut, dann nicht.


Ein schwarzes Schaf, zur rechten Zeit, erspart den Streit, bringt Einigkeit.

Doc_Arduino

Hallo,

naja, dass Thema hatten wir glaube ich schon einmal.   ;)  Wenn die Nutzung von yield() dazu führt das man das eigentliche Problem umgeht, dann führt das nicht zur Lösung des eigentlichen Problems. Mit der Anwendung millis kann man viele Nebenläufigkeiten bauen ohne diese kaschieren zu müssen. Damit wird yield() für den Anwender nicht mehr benötigt und bleibt den "Arduino Sketch Innereien" vorenthalten. Ansonsten kommt es wie es kommen muss, der Anwender kloppt sein delay auch in yield() rein und wundert sich das gar nichts mehr geht.

Ich vertrete die Linie man sollte dem unbedarften Neuling solche Dinge wie yield() erst gar nicht an die Hand geben. Das Problem wird nur verschleppt, es kann nur Mist bei rauskommen. millis muss als die Grundlage überhaupt verstanden werden, davor darf und soll sich niemand drücken. Das habe ich in Stein gemeißelt.  :)
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

#59
Jun 18, 2019, 10:49 pm Last Edit: Jun 18, 2019, 11:12 pm by combie
Quote
Ich vertrete die Linie man sollte dem unbedarften Neuling solche Dinge wie yield() erst gar nicht an die Hand geben.
Was habe ich mit deinen Dogmen zu schaffen?


Ein schwarzes Schaf, zur rechten Zeit, erspart den Streit, bringt Einigkeit.

Go Up