Mehrere Aufgaben ohne Delay

Hallo zusammen, ich bin noch ziemlicher Neuling was Arduino angeht, leider finde ich für mein Problem weder hier im Forum noch über Suchmachinen die richte Lösung.

Ich möchte mittels Knopfdruck ein Relay öffnen, dass nach einer vorgegbenen Zeit oder mittels weiterem Knopfdruck wieder schließt.

Hier kommt Blink without delay da der Code ja weiter laufen muss ....

Soweit so gut, nur dass ich das ganze Spielchen mit 3 Knöpfen/Buttons und 3 Relays spielen möchte.

Mein Problem mit millis() ist, dass jedes Mal wenn ich auf einen Button drücke auch die Zeit neu hinterlegt wird.

Hat jemand eine Idee dazu ?

int knopf1 = 4;
int knopf2 = 5;
int knopf3 = 6;

long zeit = millis();

long pause = 200;
long pause2 = 10000;

int relstatusA = LOW;
int relstatusB = LOW;
int relstatusC = LOW;


void setup() {
 // put your setup code here, to run once:
Serial.begin(57600);
}

void loop() {
 // put your main code here, to run repeatedly:


if (digitalRead(knopf1) == HIGH){
 if((millis()-zeit) > pause){
     zeit = millis();
     relstatusA = !relstatusA;}}
     
if (relstatusA == HIGH){  
 if((millis()-zeit) > pause2){
     zeit = millis();
     relstatusA = !relstatusA;}}
       
     
     

if (digitalRead(knopf2) == HIGH){
 if((millis()-zeit) > pause){
     zeit = millis();
     relstatusB = !relstatusB;}}
     
if (relstatusB == HIGH){  
 if((millis()-zeit) > pause2){
     zeit = millis();
     relstatusB = !relstatusB;}}
       
     
     


if (digitalRead(knopf3) == HIGH){
 if((millis()-zeit) > pause){
     zeit = millis();
     relstatusC = !relstatusC;}}
     
if (relstatusC == HIGH){  
 if((millis()-zeit) > pause2){
     zeit = millis();
     relstatusC = !relstatusC;}}


     Serial.print(relstatusA);
     Serial.print(" ");
     Serial.print(relstatusB);
     Serial.print(" ");
     Serial.println(relstatusC);
}

Vielen Dank schon mal im Voraus

Backslash83:
Mein Problem mit millis() ist, dass jedes Mal wenn ich auf einen Button drücke auch die Zeit neu hinterlegt wird.

3 zeit variablen statt nur einer. Code-tags im Beitrag sollen auch magische Dinge bewirken. :wink:

lg, couka

Soweit so gut, nur dass ich das ganze Spielchen mit 3 Knöpfen/Buttons und 3 Relays spielen möchte.

Dann brauchst Du auch 3 Variablen für die Zeit.
Grüße Uwe

Auf meiner Webseite habe ich vor einiger Zeit etwas zu diesem Thema veröffentlicht. Der Artikel geht auf die Vermeidung von delay() ein und zeigt eine etwas unkonventionelle Methode zur Verwendung von millis(). Vielleicht hilft es dir weiter.

http://www.hobbyelektroniker.ch/programmieren1

Backslash83:
Soweit so gut, nur dass ich das ganze Spielchen mit 3 Knöpfen/Buttons und 3 Relays spielen möchte.

Hat jemand eine Idee dazu ?

Das ist eigentlich ein schönes Beispiel für Felder (oder Strukturen). Anstatt knopf1 zu nehmen, verwendest Du knopf[1]. Das macht man dann für alle Variablen, die bei allen Knöpfen bzw. Relais verwendet werden:

const byte anzahl = 3;  // Anzahl Knöpfe und Relais
const byte knopf[anzahl] = {2, 3, 4};
const byte relais[anzahl] = {5, 6, 7};
const unsigned long pause[anzahl] = {1000, 1000, 1000};
unsigned long zeit[anzahl] = {0, 0, 0}, aktMillis;
bool relstatus[anzahl] = {LOW, LOW, LOW};
bool knopfakt[anzahl], knopfalt[anzahl];
byte z;   // Zähler für Knöpfe und Relais

void setup() {
  Serial.begin(9600);
  for (z = 0; z < anzahl; z++) {
    pinMode(knopf[z], INPUT_PULLUP);
    pinMode(relais[z], OUTPUT);
  }
  z = 0;
}

void loop() {
  aktMillis = millis();
  knopfalt[z] = knopfakt[z];
  knopfakt[z] = digitalRead(knopf[z]);
  if (knopfakt[z] && !knopfalt[z]) {
    zeit[z] = aktMillis;
    relstatus[z] = HIGH;
  }
  if (aktMillis - zeit[z] >= pause[z]) {
    relstatus[z] = LOW;
  }

  digitalWrite(relais[z], relstatus[z]);

  // Serial.print("relstatus");
  // Serial.print(z);
  // Serial.print(": ");
  // Serial.print(relstatus[z]);
  // Serial.print(" ");
  z++;                        // nächster Knopf und nächstes Relais
  z = z % anzahl;             // Zähler auf Null, wenn maximale Anzahl erreicht.
  // if (!z) Serial.println();   // neue Zeile
  // delay(100);                 // nur um die Ausgabe zu bremsen
}

Dieser Sketch zeigt die Verwendung unabhängig funktionierender Zeitabläufe, erfüllt aber nicht die gewünschte Funktionalität! Nach jeder LOW-HIGH-Flanke des Tasters geht der Ausgang für eine Sekunde auf HIGH.

@René: Wie kann ich Dich überreden, Deine schöne Erklärung um die Nutzung von Feldern zu ergänzen? Also led[8] anstelle led8(). Dann bräuchte es nur eine Funktion. Ist auch nur leicht erweitertes “Erstellen von ‘Objekten’ mit der Copy / Paste - Methode”. :slight_smile:

Ich empfehle dieses Tutorial dazu, sollte dann Deine Fragen beantworten :wink:

Versuch’s mal mit mein Automaton library.
Ich hab dir ein sketch gemacht, drei knoepfe, drei relays, 2 s auto reset.
Functioniert alles unabhaengig.

#include <Automaton.h>

Atm_bit bit[3];
Atm_button button[3];
Atm_timer timer[3];
Appliance app;

int btnPin[] = { 2, 3, 18 };
int relayPin[] = { 4, 5, 6 };
int resetDelay = 2000;

void setup() {
  for ( int i = 0; i < 3; i++ ) {
    app.component( 
      timer[i].begin( resetDelay )
      .onTimer( bit[i], bit[i].EVT_OFF )
    );
    app.component( 
      bit[i].begin()
        .onChange( true, timer[i], timer[i].EVT_START )
        .led( relayPin[i] ) 
    );
    app.component(
      button[i].begin( btnPin[i] )
        .onPress( bit[i], bit[i].EVT_TOGGLE )
    );
  }
}

void loop() {
  app.run();
}