Probleme mit Millis

Moin zusammen,

bin gerade an einem meiner ersten Arduino Projekte und hab ein Problem mit den millis.

Die Schaltung funktioniert soweit, die Relais schalten abwechselnd bleiben dann aber an und gehen nicht nach den vorgegeben 2000 millisekunden aus.

Ich hoffe der Sketch ist verständlich erklärt und logisch geschrieben.

Vielen Dank im Vorraus :slight_smile:

Simon

int Relais = 13;  
int Relais1 = 12; 

int button = 4;                            // Variable Taster
int buttonStatus = 1;                      // Hier wird die Information gespeichert, ob Taster gedrückt oder nicht.
int buttonStatusAlt = 1;                   // Hier ist die vorherige Information gespeichert
int zaehler = 0;                           // Zählt wie oft Taster gedrückt wurde



unsigned long lastMillis;
unsigned long lastMillis1;







void setup() {
  pinMode(Relais, OUTPUT);
  pinMode(Relais1, OUTPUT);
  
  pinMode(button, INPUT_PULLUP);
  
  lastMillis = millis();
  lastMillis1 = millis();

 
}

void loop() {
Serial.begin(9600);

  buttonStatus = digitalRead(button);      // Prüfe, ob Taster gedrückt oder nicht
  
  if (buttonStatusAlt != buttonStatus)     // Wenn der alte Status nicht dem neuen Status entspricht
  {
     if (buttonStatus == LOW)              // Und der Taster gedrückt wurde
     {
        if (zaehler == 2)                  // Und der Zähler gleich 2 ist
        {
           zaehler = 0;                    // Setze den Zähler zurück auf 0

        } 
        else
        {
     
           zaehler++;                     // Wenn der Zähler nicht 2 ist, erhöhe den Zähler um 1
                                          
        }
     }
  }

  buttonStatusAlt = buttonStatus;        // Setze den alten Status = den neuen Status


  if (zaehler == 1 && millis() - lastMillis <= 2000) {
    digitalWrite(Relais, HIGH);
  }
  else {
    digitalWrite(Relais, LOW);
    
  }


   if (zaehler == 2 && millis() - lastMillis1 <= 2000) {
    digitalWrite(Relais1, HIGH);
  }
  else {
    digitalWrite(Relais1, LOW);
    
  }

    }

Relais_Schaltung_Forum.ino (1.63 KB)

aktiviere die serielle Schnittstelle und schreib dir in deine If und else zweige Serial Print Ausgaben, damit du siehst, was dein Programm macht bzw warum Bedingungen erfüllt sind.

simons_arduinoprojects:
Ich hoffe der Sketch ist verständlich erklärt und logisch geschrieben.

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Hallo,

du musst dir die aktuellen millis nach einem erfolgreichen Schaltvorgang für den nächsten kommenden Vergleich merken. Hilft dir hier aber noch nicht weiter, es würde kurz unbemerkt schalten, da Relais zu träge und du bekommst das nicht mit.

Du darfst die Zeit nur bei Bedingung erfüllt, sprich Relais eingeschalten abfragen.
Bei Tastendruck oder Zählerstandsbedingung wird Relais eingeschalten und nur jetzt wird die Zeit beobachtet. Wenn abgelaufen wird Relais ausgeschalten und dann erneut auf Taste oder Zähler geschaut und neu entschieden.

Am Ende landest du beim endlichen Automaten, sprich Ablaufsteuerung.

Hallo,

irgendwann musst Du innerhalb der Loop lastMillis mal auf den Wert von millis() setzten.

Und bei if (zaehler == 2 && millis() - lastMillis1 <= 2000)

mach eine zusätzliche Klammer Sinn

f(zaehler == 2 && (millis() - lastMillis1 <= 2000))

nicht getestet

Heinz

Rentner:
Und bei if (zaehler == 2 && millis() - lastMillis1 <= 2000)
mach eine zusätzliche Klammer Sinn

Macht sie nicht. Schau mal in die Rangfolge der Operatoren.

Gruß Tommy

noiasca:
aktiviere die serielle Schnittstelle und schreib dir in deine If und else zweige Serial Print Ausgaben, damit du siehst, was dein Programm macht bzw warum Bedingungen erfüllt sind.

Danke für die schnelle Antwort.

könntest du mir das bitte mal am Beispiel zeigen wann ich da Serial.println einnfügen muss?

Bin wie gesagt noch ganz am Anfang des programmierens.. :slight_smile:

Doc_Arduino:
Du darfst die Zeit nur bei Bedingung erfüllt, sprich Relais eingeschalten abfragen.
Bei Tastendruck oder Zählerstandsbedingung wird Relais eingeschalten und nur jetzt wird die Zeit beobachtet. Wenn abgelaufen wird Relais ausgeschalten und dann erneut auf Taste oder Zähler geschaut und neu entschieden.

heißt die millis dürfen erst das laufen anfangen wenn der Taster gedrückt wurde, richtig?

Wo ist da bei mir der Fehler? :frowning:

Hallo,

nein , millis() laufen doch immer ab Systenstart die willst Du nicht wirklich anhalten oder neu starten.
Es gibt wie immer mehrere Möglichkeiten ich würde es so machen .
altzeit setzten auf millis() wenn der Taster gedrückt wird bei der Flanke . Ebenfalls dann das Relais ein. Wenn die Differenz millis()-altzeit >= 2000 ist Relais abschalten.

Heinz

Rentner:
altzeit setzten auf millis() wenn der Taster gedrückt wird bei der Flanke . Ebenfalls dann das Relais ein. Wenn die Differenz millis()-altzeit >= 2000 ist Relais abschalten.

was muss ich dann im aktuellen Sketch ersetzen? Buttonstatus?

(deleted)

Peter-CAD-HST:
Hey Peter, das hab ich schon gemacht und funktioniert grundsätzlich auch, aber leider nur mit zwei verschiedenen Tastern, ich würde gerne das der Taster immer im wechsel Relais1 & Relais2 schaltet..

anbei der Sketch

int Relais = 13; 
int button = 2; 

int Relais1 = 12; 
int button1 = 3;


unsigned long lastMillis;
unsigned long lastMillis1;


void setup() {
  pinMode(Relais, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  lastMillis = millis();

  pinMode(Relais1, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
  lastMillis1 = millis();
}

void loop() {

  if (!digitalRead(button)) {  
    lastMillis = millis();
  }

  if (millis() - lastMillis <= 2000) {
    digitalWrite(Relais, HIGH);
  }
  else {
    digitalWrite(Relais, LOW);
  }


   if (!digitalRead(button1)) { 
    lastMillis1 = millis();
  }

  if (millis() - lastMillis1 <= 2000) {
    digitalWrite(Relais1, HIGH);
  }
  else {
    digitalWrite(Relais1, LOW);
  }



  
}

Hallo,

schau Dir das mal an

Relais werden wechselnd eingeschaltete , aus immer nach 2 sekunden

Heinz

const byte btn = 2;
const byte led = 13;
const byte led1 = 12;
bool btnstate, lastbtnstate;

int count = 0;
unsigned long lastMillis, lastMillis1;

void setup() {
  // put your setup code here, to run once:
  pinMode(btn, INPUT_PULLUP);
  pinMode (led, OUTPUT);
  pinMode (led1, OUTPUT);
  Serial.begin(9600);

}

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

  btnstate = !digitalRead(btn); //Eingang lesen
  delay(10); // entprellen mal mit delay

 // erste LED ein
  if (btnstate & !lastbtnstate & count == 0) {
    lastMillis = millis(); // starten
    digitalWrite(led, HIGH);

  }

// zweite LED ein 
  if (btnstate & !lastbtnstate & count == 1) {
    lastMillis1 = millis(); // starten
    digitalWrite(led1, HIGH);


  }
// Zähler bearbeiten
  if (btnstate & !lastbtnstate) {
    count++;
    if (count == 2) count = 0;
    lastbtnstate = HIGH;
    Serial.println (count);
  }

  // Zeit abfragen
  if (millis() - lastMillis >= 2000 ) digitalWrite(led, LOW);
  if (millis() - lastMillis1 >= 2000 ) digitalWrite(led1, LOW);

  // flankenmerker rücksetzen
  if (!btnstate) lastbtnstate = LOW;

}

Rentner:
Hallo,

Relais werden wechselnd eingeschaltete , aus immer nach 2 sekunden

danke das funktioniert!

Jetzt würde ich gerne die gleiche Funktion noch 3 mal laufen lassen, wie kann ich das in einem Sketch zusammenfassen?

Es soll dann so Funktionieren:

Pin 2 - schaltet Relais Pin 12 + 13
Pin 3 - schaltet Relais Pin 10 + 11
Pin 4 - schaltet Relais Pin 8 + 9
Pin 5 - schaltet Relais Pin 6 + 7

vielen dank für deine schnelle Hilfe! :slight_smile:

Hallo,

da gibts jetzt wieder mehrere Möglichkeiten.

q&d mit past&coy

mit Arrays
mit Strukturen
mit Objekten
mit einer Timer lib

Heinz

Rentner:
Hallo,

mit past&coy

hab ich probiert, und immer die jeweilige Variable um +1 erweitert, dann funktioniert aber trotzdem nur das erste..

(deleted)

Hallo,

wenn das Mit copy&past nicht funktioniert hast Du etwas falsch gemacht. Was kann ich Dir nicht sagen , wie auch.

Ich hab jetzt mal von meinen Vorschlägen die sicher für Dich am einfachsten verständliche Variante genommen. Im Wesentlichen beruht das auf dem obigen Sketch von mir.

Zunächst stelle Dir mal vor das Du das Ein und Ausschalten der LED´s in eine Funktion auslagerst, der Du bestimmte Parameter übergibst. Dann kannst Du diese mehrfach aufrufen, also den Code mehrfach nutzen. Dazu musst Du wissen was Funktionen sind und wie man Parameter übergibt.
Dann stelle Dir vor das es sich um 4 Einheiten handelt die man über einen Nummer i ansprechen will. Also mehrere Arrays mit je 4 Elementen. 4 xTaster , 4 x LED_A und 4 x LED_B. Dazu musst Du wissen was Arrays sind und wie man die anspricht.

Nun habe ich die lib Bunce2 verwendet damit geht das Flanke erkennen und entprellen sehr einfach.

Den ursprunglichen counter habe ich ersetzt durch eine bool Variable die letztlich für A oder B zuständig ist und jeweils bei einem Tastendruck getoggelt wird.

Die eigendliche Funktion kann man dann in einer Shleife aufrufen und übergibt Ihr die Numer i , die Flanke desTasters, und die Variable toggle.

Die Funktion steuert dann die LED´s an. Sie wird ständig aufgerufen , sonst könnte sie ja die LED´s nicht wieder ausschalten.

Natürlich gibt es ,wie immer, noch andere Möglichkeiten , aber darauf hatte ich ja bereits hingewiesen. Ich hoffe Du kannst den Sketch verstehen.

Heinz

#include <Bounce2.h>
#define NUM_BUTTONS 4

// Pins in Array ablegen 
const byte btnpin[] = {2, 3, 4, 5}; 
const byte ledApin[] = {6, 8, 10, 12};
const byte ledBpin[] = {7, 9, 11, 13};

bool toggle[NUM_BUTTONS];
bool btnflag; // Flanke Taster gedrückt

// mehrere Instanzen von Bounce in einem Array anlegen
// siehe Beispiel aus der Lib 
Bounce * button = new Bounce[NUM_BUTTONS];

void setup() {
  // put your setup code here, to run once:

  for (int i = 0; i < NUM_BUTTONS; i++) {
   // pins einstellen
    button[i].attach(btnpin[i], INPUT_PULLUP);
    button[i].interval(20);
    pinMode(ledApin[i], OUTPUT);
    pinMode(ledBpin[i], OUTPUT);
  }
  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  for (int i = 0; i < NUM_BUTTONS; i++) {
    button[i].update();

    btnflag = button[i].fell();
    if (btnflag) {
      toggle[i] = !toggle[i]; // Wert toggeln
      //Serial.print(toggle[i]);Serial.println(i);
    }
    timer(i, btnflag, toggle[i]);
  }
  
}

void timer(int gruppe, bool flag, bool tog) {
  // Speicher für die Zeiten hier static damit sie nicht
  // verloren gehen.
  uint32_t static altzeitA[NUM_BUTTONS];
  uint32_t static altzeitB[NUM_BUTTONS];

  if (flag) { // starten 
    Serial.print("starten Gruppe "); Serial.print(gruppe); 
    if (tog) { // LED A
      altzeitA[gruppe]=millis();
      digitalWrite(ledApin[gruppe], HIGH);
      Serial.println(" LED A");
    }
    else { // LED B 
      altzeitB[gruppe]=millis();
      digitalWrite(ledBpin[gruppe], HIGH);
      Serial.println(" LED B");
    }
  }
  // Zeit abgelaufen LED A
  if (millis() - altzeitA[gruppe] >= 2000){
    digitalWrite(ledApin[gruppe],LOW);
}

// Zeit abgelaufen LED B 
  if (millis() - altzeitB[gruppe] >= 2000){
    digitalWrite(ledBpin[gruppe],LOW);
}
}

Rentner:
Ich hab jetzt mal von meinen Vorschlägen die sicher für Dich am einfachsten verständliche Variante genommen.

sorry hab ganz vergessen zu antworten, funktioniert perfekt, vielen Dank!