Delay ersetzen und mehreren Tasten Funktionen zuweisen

Hi an alle,

ich versuche mich gedanklich gerade in den Arduino zu bohren.
Leider verzweifle ich hier bald, ich steige gerade einfach nicht durch und habe auch nach stundenlangem Googeln keinen anderen Weg gefunden als mich hier bei euch zu melden.

Folgende Herausforderung (für mich zumindest :slight_smile: ):

  • 6 Taster
  • 1 LED
  • 6 Abläufe

Auf jeden Taster soll ein Ablauf gebracht werden, welcher durch Tastendruck einer beliebig anderen Taste gewechselt werden soll. Als Beispiel:

Taste 1
LED an für 200ms
LED aus für 2000ms

LED an für 200ms
LED aus für 2000ms

LED an für 200ms
LED aus dauerhaft

Taste 2
LED an für 200ms
LED aus für 500ms
LED an für 200ms
LED aus für 2000ms

LED an für 200ms
LED aus für 500ms
LED an für 200ms
LED aus für 2000ms

LED an für 200ms
LED aus für 500ms
LED an für 200ms
LED aus dauerhaft

usw.

Wenn ich das mit delay() realisiere ist das zwar funktionstüchtig, jedoch kann ich den Ablauf nicht mit Tastendruck einer beliebig anderen Taste stoppen um dann das andere Programm durchlaufen zu lassen.
Natürlich habe ich versucht mich mit switch case und Blink without delay zu befassen, jedoch steige ich nicht durch.

Vielen Dank vorab :slight_smile:

Der Code dafür, welchen ich gerade verwende:

const int ledPin = 3;
#include "Button.h"
#include "Arduino.h"

#define BUTTON_PIN1 5
#define BUTTON_PIN2 6
#define BUTTON_PIN3 7
#define BUTTON_PIN4 8

#define PULLUP true        
#define INVERT true        
#define DEBOUNCE_MS 20

Button myBtn1(BUTTON_PIN1, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn2(BUTTON_PIN2, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn3(BUTTON_PIN3, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn4(BUTTON_PIN4, PULLUP, INVERT, DEBOUNCE_MS);

void setup()
{
 pinMode(ledPin, OUTPUT);
}


void loop()
{
   myBtn1.read();
   myBtn2.read();
   myBtn3.read();
   myBtn4.read();
   
   if (myBtn1.wasReleased()) {  
   pulse1();  
 }                    
   if (myBtn2.wasReleased()) {      
   pulse2();  
   }                 
   if (myBtn3.wasReleased()) {      
   pulse3(); 
   }                        
   if (myBtn4.wasReleased()) {    
   pulse4();  
}
}



void pulse1()
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);  

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
}

void pulse2()
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
}

void pulse3()
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
}

void pulse4()
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

 delay(2000);

digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
}

void pulse5()
{
digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
}

void pulse6()
{
digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW); 
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW); 
 
 delay(2000);

digitalWrite(ledPin, HIGH);
delay(600);
digitalWrite(ledPin, LOW);
delay (400);
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW); 
}

Wir sehen deinen Sketch (Code-Tags verwenden) nicht.
Wie sollen wir helfen ?

Code habe ich oben eingefügt :slight_smile:

magic-monkey:
Code habe ich oben eingefügt :slight_smile:

Ok, der Sketch wimmelt nur so von delay.
Die müssen def. raus.

Sieh dir mal den "Timer" Interval.h an, die könnte helfen.

magic-monkey:
Leider verzweifle ich hier bald,...
Folgende Herausforderung (für mich zumindest :slight_smile: ):
...

Das mit dem Verzweifeln ist blöd. Zumindest hast Du hier schon einmal ein super Forum gefunden.

Was Du schreibst, lässt auch mich sofort an einen „endlichen Automaten“ denken. Evtl. hilft auch, was ich hier gesabbelt habe. Wg. einem Domain-Umzug wird die Seite gerade fehlerhaft angezeigt. Das dürfte aber bald wieder gut aussehen. Beachte ggf. die Folgeseite.

Gruß

Gregor

Vielen lieben Dank für die Rückmeldungen und der Unterstützung. Ich habe wirklich versucht mich da Schritt für Schritt rein zu denken. Tatsächlich hatte ich sogar gedacht die Lösung zu haben, jetzt entstand jedoch das Problem, dass bei jedem Tastendruck eines anderen Tasters, das jeweilige Programm zusätzlich gestartet wurde.

Also habe ich Taste 1 gedrückt, läuft Programm 1.
Drückte ich dann Taste 2, ist Programm 2 gleichzeitig mit Programm 1 gelaufen....
Es wurde also nicht das laufende Programm abgebrochen, es wurde einfach alles gestartet was betätigt wurde :smiley:

Also, folgendes soll erreicht werden

Taste 1 drücken
Led leuchtet für 200ms
Pause 2000ms
das Ganze 3 mal

Taste 2 drücken
Led leuchtet für 200ms
Pause 500ms
Led leuchtet für 200ms
Pause 2000ms
das Ganze 3 mal

usw.

Kann doch eigentlich nicht so schwer sein :frowning:

Kann doch eigentlich nicht so schwer sein :frowning:

Da hast du recht!

Sieht wie eine Ablaufsteuerung aus.
Und das, gar nicht mal so komplex.

magic-monkey:
... Also, folgendes soll erreicht werden

Taste 1 drücken
Led leuchtet für 200ms
Pause 2000ms
das Ganze 3 mal

Taste 2 drücken
Led leuchtet für 200ms
Pause 500ms
Led leuchtet für 200ms
Pause 2000ms
das Ganze 3 mal

usw.

Kann doch eigentlich nicht so schwer sein :frowning:

Ja, eigentlich ist es ziemlich einfach. Der Knoten im Hirn löst sich meistens dann auf, wenn man die Zustände definiert, die auftreten können/sollen und dann nicht in „Pausen“ denkt, sondern Zeitpunkte festlegt, zu denen etwas passieren soll.

Sehr hilfreich ist es außerdem, seinen Code durch passende und einheitliche Einrückungen/Klammerungen zu „formatieren“, damit man die Struktur eines Codes erfassen kann, ohne den Code selbst vollständig lesen zu müssen.

Gruß

Gregor

PS: Bei Deiner Beschreibung kannst Du z. B. alles bis auf die „Taste x drücken“ einrücken, weil der Tastendruck wohl nicht zu dem „das Ganze 3 mal“ gehört. Oder du fasst den Teil, der wiederholt werden soll in Klammern. Siehe z. B. Pseudocode – Wikipedia.

magic-monkey:
Es wurde also nicht das laufende Programm abgebrochen, es wurde einfach alles gestartet was betätigt wurde :smiley:

Also, folgendes soll erreicht werden
...
usw.

Kann doch eigentlich nicht so schwer sein :frowning:

Evtl. merkst du selber, dass deine Beschreibung sehr unvollständig ist.

@Magic-Monkey: Kommst Du inzwischen zurecht?

Was ich über Pausen-Denke und Zeitpunkte geschrieben habe, ist evtl. zu unkonkret. Vielleicht ist es so besser:

Statt

tu_was;
warte 10 Sekunden;
tu_noch_was;

formuliert man besser

tu_was; // und notiere, wann das getan wurde
wenn seither 10 Sekunden verstrichen sind
  { tu_noch_was; }

Außerdem kann es helfen, sich mit den Grundgedanken der objektorientierten Programmierung zu befassen.

In der Realität hat man es mit Dingen zu tun, die Eigenschaften haben und mit denen man Sachen anstellen kann. Du hast mit zwei „Blinkdingern“ zu tun. Jedes Blinkding besteht aus einer Taste und einer LED. Wenn Du eine Klasse (die Abstraktion eines Blinkdings) definierst, legst Du fest, was für Eigenschaften (Attribute) die Objekte haben und wie damit gearbeitet werden bzw. was damit angestellt werden kann (Methoden).
Als Eigenschaft eines Blinkdings kann man festlegen, dass der dazugehörende Taster an einem bestimmten Pin hängt. Das wäre eine Variable der Blinkding-Klasse. Eine andere Variable wäre z. B. der Zeitpunkt, zu dem die LED eingeschaltet wurde. Als Methode würdest Du festlegen, wie der Zustand der LED umgeschaltet wird (an->aus bzw. umgekehrt). In loop() werden die Blinkdinger dann nacheinander aufgefordert, ihren „loop-Job“ zu erledigen – dabei wird unter Anderem geguckt, ob seit dem Umschalten der LED eine bestimmte Zeit verstrichen ist. Wenn ja, wird wieder umgeschaltet, wenn nicht, wird gar nichts gemacht.

Auf diese Weise kannst Du beliebig viele Blinkdinger benutzen und mit allen „gleichzeitig“ arbeiten. In Wirklichkeit werden die Blinkdinger nacheinander zu Aktionen aufgefordert, aber weil das sehr schnell passiert, sieht es so aus, als würden die Blinkdinger unabhängig voneinander und zur selben Zeit funktionieren.

HTH

Gregor

PS: Mir ist gerade aufgefallen, dass ich die von Dir formulierte Aufgabe falsch im Gedächtnis hatte. Gib Bescheid, wenn Du Probleme hast, mein Geschreibsel auf Deine Bastelei anzuwenden.

@Gregor: glaubst du wirklich, dass ein kurzer Anriss von objektorienter Programmierung einen Einsteiger mit 3 Posts und delays im Sketch wirklich weiter bringt?

ElEspanol:
@Gregor: glaubst du wirklich, dass ein kurzer Anriss von objektorienter Programmierung einen Einsteiger mit 3 Posts und delays im Sketch wirklich weiter bringt?

Ja. Wenn derjenige weiterhin mit Arduino spielt, hat er zumindest schon einmal davon gehört. Und da ich Zehn-Finger-Tipper bin, ist das Sabbeln kein Problem für mich.

Gruß

Gregor

Ja. Wenn derjenige weiterhin mit Arduino spielt, hat er zumindest schon einmal davon gehört.

Sehe ich auch so!

Mit meinem Kram kann auch nicht jeder "sofort" was anfangen.
Soll ich deswegen die Klappe halten?

Also ich bin schon einmal sehr dankbar für jegliche Hilfe, welche ich hier bekommen habe :slight_smile:
Ich habe jetzt auch alles erreicht, was ich schaffen wollte durch euch jedoch fehlt noch eine Kleinigkeit zur Vollendung.

Ziel:
Sobald ein Taster gedrückt wird, soll die aktuell laufende Aktion unterbrochen werden um den neuen Ablauf zu starten.

Beispiel:
Taste 1 wurde gedrückt - Ablauf 1 läuft.
Taste 2 wird gedrückt während Ablauf 1 läuft - Ablauf 1 wird gestoppt und Ablauf 2 beginnt.

Den folgenden Code verwende ich aktuell:

#include "Timer.h"            
#include "Button.h"

#define BUTTON_PIN1 2
#define BUTTON_PIN2 3
#define BUTTON_PIN3 4
#define BUTTON_PIN4 5
#define BUTTON_PIN5 6
#define BUTTON_PIN6 7
#define PULLUP true 
#define INVERT true
#define DEBOUNCE_MS 20

Button myBtn1(BUTTON_PIN1, PULLUP, INVERT, DEBOUNCE_MS);    
Button myBtn2(BUTTON_PIN2, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn3(BUTTON_PIN3, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn4(BUTTON_PIN4, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn5(BUTTON_PIN5, PULLUP, INVERT, DEBOUNCE_MS);
Button myBtn6(BUTTON_PIN6, PULLUP, INVERT, DEBOUNCE_MS);

const int led = 13;
Timer t; 

void setup(void)
{
    pinMode(led, OUTPUT);
}

void loop(void)
{
    t.update();
    myBtn1.read();
    myBtn2.read();
    myBtn3.read();
    myBtn4.read();
    myBtn5.read();
    myBtn6.read();
    
    if (myBtn1.wasReleased()) {
      pulse1();
      t.every(2500, pulse1, 2);
    }     
    if (myBtn2.wasReleased()) {
      pulse2();
      t.every(2750, pulse2, 2);
    }
    if (myBtn3.wasReleased()) {
      pulse3();
      t.every(3000, pulse3, 2);
    }
    if (myBtn4.wasReleased()) {
      pulse4();
      t.every(3250, pulse4, 2);
    }     
    if (myBtn5.wasReleased()) {
      pulse5();
      t.every(3500, pulse5, 2);
    }
    if (myBtn6.wasReleased()) {
      pulse6();
      t.every(3750, pulse6, 2);
    }    
}


void pulse1()
{
t.pulse(led, 200, LOW);
}

void pulse2()
{
t.oscillate(led, 200, LOW, 2);
}

void pulse3()
{
t.oscillate(led, 200, LOW, 3);
}

void pulse4()
{
t.oscillate(led, 200, LOW, 4);
}

void pulse5()
{
t.pulse(led, 600, LOW);
}

void pulse6()
{
t.pulse(led, 600, LOW);
t.after(1200, pulse1);
}

Über weitere Hilfestellung bin ich sehr dankbar :confused:
Ich drehe mich seit Tage im Kreis und komme selbst mit Switch Case nicht weiter...

Hi

Mache eine State-Machine daraus.
Nichts wurde gedrückt: Status=0
Im Status 0 bringt Dich Taste 1 zu Status 1, Taste 2 zu Status 2
In Status 1 läuft die LED 1 'Ihr Programm' ab, wenn Sie fertig ist, wird Status wieder auf 0 gesetzt
Gleiches für Status 2.
Wenn im Status 2 die Taste 1 gedrückt wird, wird die LED 2 abgeschaltet und Status auf 1 gesetzt
Wenn im Status 1 die Taste 2 gedrückt wird, wird die LED 1 abgeschaltet und Status auf 2 gesetzt.

Das Ganze ohne blockierende for/while/delay
In den Staus (ja, die Mehrzahl von Status ist: Status ... hoffte zwar auf Staten, wie bei Globus, ist aber nicht so) 1 oder 2 müssen sich die LEDs 'merken', wie weit das eigene Programm fortgeschritten ist, quasi eine Art 'Unter-Status', Der ebenfalls nach Abarbeiten einer der Aufgaben erhöht wird und irgendwann das Programm der LED durch hat - die letzte Aktion ist hier also, den Status wieder auf 0 zu setzen.

Schreibe Dir haarklein auf, was der Code wann wo machen soll.
Gerne auch auf kariertem DIN-A4 Block (so was liegt hier immer in greifbarer Nähe rum ... ob für I²C in Assembler oder meine Kommunikation zweier (mehrerer) µC, dafür gibt es Papier).

Lasse auch gerne ein/zwei Zeilen Platz zwischen Deinen Einzelschritten - Den wirst Du hier und da immer wieder brauchen, weil Dir weitere nötige Kleinigkeiten einfallen, Die eben genau dort ausgeführt werden müssen.

MfG