millis() anstelle von delay()

Programmierung der Arduino UNO, Arduino MEGA, Arduino Nano, ........
Antworten
Benutzeravatar
Admin
Administrator
Beiträge: 1194
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

millis() anstelle von delay()

Beitrag von Admin »

Ich habe hier mal ein Programm gemacht, das nur zeigt wie die Zeitkontrolle mit "millis()" funktioniert.

Code: Alles auswählen


// Baudrate fuer Serial Schnittstelle
const int baudSerial = 9600;
// ------Zeitmerker Deklaration ----
unsigned long aktuellezeit = 0;
// ------millis Deklaration 01 -----
unsigned long pausestartzeit01 = 0; // Jede Sekunde eine Aktion
const unsigned long pausezeit01 = 1000;
// ------millis Deklaration 02 -----
unsigned long pausestartzeit02 = 0; // Alle zwei Sekunden eine Aktion
const unsigned long pausezeit02 = 2000;
// ------millis Deklaration 03 -----
unsigned long pausestartzeit03 = 0; // Alle drei Sekunden eine Aktion
const unsigned long pausezeit03 = 3000;
//-----------------------------------------------------------------------------------
void setup()
{
  // Serial Schnittstelle starten
  Serial.begin(baudSerial);
}
//----------------------------------------------------------------------------------
void loop() {
  aktuellezeit = millis(); // Aktuelle Zeit für alle Millis Aktionen übergeben

//------------------Erste Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit01 >= pausezeit01) // Eine Sekunde abgelaufen??
  { 
    //Hier die aktuelle Aktion einsetzen, die jede Sekunde ablaufen soll.
    
    pausestartzeit01 = aktuellezeit; // Neue Pausestartzeit übergeben
  }

//------------------Zweite Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit02 >= pausezeit02) // Zwei Sekunden abgelaufen??
  { 
    //Hier die aktuelle Aktion einsetzen, die alle zwei Sekunden ablaufen soll
  
    pausestartzeit02 = aktuellezeit; // Neue Pausestartzeit übergeben
  }

//------------------Dritte Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit03 >= pausezeit03) // Drei Sekunden abgelaufen??
  { 
    //Hier die aktuelle Aktion einsetzen, die alle zwei Sekunden ablaufen soll
 
    pausestartzeit03 = aktuellezeit; // Neue Pausestartzeit übergeben
  }

}
Man kann diesen Grundstock benutzen, um drei Aktionen, bei denen jede für sich, in einem anderen Zeittackt immer wieder laufen sollen, ständig kontrolliert zu wiederholen. Natürlich kann man die Aktionen auch endlos erweitern. Und die Zeiten verändern / anpassen. Hier im Programm ist die einzige Aktion die in diesen Zeittackten stattfinden nur die Serial.println() Ausgabe, dass man sieht wie es abläuft. Der Sekundentakt kommt jede Sekunde, der 2 Sekundentakt alle zwei Sekunden, der 3 Sekundentakt alle drei Sekunden. Da, wo ich immer reingeschrieben habe "//Hier die aktuelle Aktion oder mehr Aktionen einsetzen" schreibt man das rein, was in diesem Zeittakt ablaufen soll. Natürlich darf da auch kein delay() rein, sonst ist alles für´n Arsch. Da kann man Relais einschalten oder ausschalten. LED´s ein oder aus. Daten zu Display´s schicken. Sensoren abfragen. Und vieles mehr. Was man eben in den Zeitabständen machen will.

Die Serial.println() kann man natürlich verschwinden lassen, ausser man will kontrollieren ob alles korrekt abläuft. Die Zeit für die jeweilige Zelle läuft immer wieder neu los, wenn man die "pausestartzeit" an die "aktuellezeit" angleicht. Man kann also z.B. die Zeile "pausestartzeit02 = aktuellezeit;" auch aus der Zelle herausnehmen und wo anders im Loop diese Startzeit aktivieren. Egal wo diese Zeile ausgeführt wird, ab da läuft die Zeit für diese Zelle neu ab, und wird nach Ablauf der zugehörigen "pausezeit" wieder EINMAL ausgeführt.
Benutzeravatar
Admin
Administrator
Beiträge: 1194
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: millis() anstelle von delay()

Beitrag von Admin »

Ich habe hier mal nur das geschrieben, was man zum Benutzen des "millis();" - Befehles braucht. Der Unterschied zwischen millis() und delay() ist, das das Programm beim delay(); für die eingetragene Zeit stehen bleibt. Nachteil, in dieser Zeit kann ich nichts ausführen, also z.B. auch keine Tastenzustände abfragen. Also ich versuche inzwischen, delay(); völlig aus meinem Kopf zu streichen. Es gibt fast keine Aktion, wo das delay(); Sinn macht.

Bei den Aktionen mit millis(); bleibt das Programm nicht stehen, sondern es werden die Teile, die nicht ausgeführt werden sollen, "übersprungen" und nur wenn die zugehörige Zeit abgelaufen ist, wird das was {in den Spitzen klammern} steht, einmal ausgeführt. Dann wird "Pausezeit neu übergeben" und somit geht die Pause von vorne los. Diese "Pause neu übergeben" sorgt also dafür, dass der Teil in den Spitzen Klammern wieder für nicht mehr ausgeführt wird, bis die Pause wieder abgelaufen ist. Man kann da zwischen diese spitzen Klammern nicht nur einen Befehl eintragen, sondern man kann auch das gesammte Programm da reinschreiben, dann wird eben das ganze Programm alle 1, 2, oder 3 Sekunden einmal ausgeführt. Also das ganze Programm aus dem Loop da reinschreiben, oder die Teile des Programmes, die eben mit den Zeitabständen laufen sollen.

Code: Alles auswählen

unsigned long aktuellezeit = 0;
// ------millis Deklaration 01 -----
unsigned long pausestartzeit01 = 0; // Jede Sekunde eine Aktion
const unsigned long pausezeit01 = 1000;
// ------millis Deklaration 02 -----
unsigned long pausestartzeit02 = 0; // Alle zwei Sekunden eine Aktion
const unsigned long pausezeit02 = 2000;
// ------millis Deklaration 03 -----
unsigned long pausestartzeit03 = 0; // Alle drei Sekunden eine Aktion
const unsigned long pausezeit03 = 3000;
//-----------------------------------------------------------------------------------
void setup()
{
// Hier braucht man für die Milli-Aktionen nichts.
}
//----------------------------------------------------------------------------------
void loop() {
  aktuellezeit = millis(); // Aktuelle Zeit für alle Millis Aktionen übergeben

  //------------------Erste Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit01 >= pausezeit01) // Eine Sekunde abgelaufen??
  {
    //Hier die aktuelle Aktion einsetzen, die jede Sekunde ablaufen soll.

    pausestartzeit01 = aktuellezeit; // Neue Pausestartzeit übergeben
  }

  //------------------Zweite Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit02 >= pausezeit02) // Zwei Sekunden abgelaufen??
  {
    //Hier die aktuelle Aktion einsetzen, die alle zwei Sekunden ablaufen soll

    pausestartzeit02 = aktuellezeit; // Neue Pausestartzeit übergeben
  }

  //------------------Dritte Aktion-------------------------------------------------
  if (aktuellezeit - pausestartzeit03 >= pausezeit03) // Drei Sekunden abgelaufen??
  {
    //Hier die aktuelle Aktion einsetzen, die alle zwei Sekunden ablaufen soll

    pausestartzeit03 = aktuellezeit; // Neue Pausestartzeit übergeben
  }
  
// Hier kann man Tastenabfragen oder sonstiges reinschreiben, was nicht nur in bestimmten Zeitabständen gemacht werden soll, 
// sondern in jedem Loop Durchgang. Das wäre dann alle paar Millisekunden wieder. 

}
Benutzeravatar
Admin
Administrator
Beiträge: 1194
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: millis() anstelle von delay()

Beitrag von Admin »

Ich habe mal nochmal was ganz einfaches, möglichst übersichtlich zusammengestellt. Da gibt es keine SerialPrint() Spielereien. Einfach nur drei Ausgänge, an die man drei LED´s hängen kann, wo die Erste im Tackt von 1 Sekunde blinkt, die Zweite im Tackt von 2 Sekunden, die Dritte im Tackt von 3 Sekunden.

Code: Alles auswählen

// Deklarationen
//-----------------------AusgangPIN6-------------------------------------
const byte Ausgang01 = 6;          // Pin 6 ist für LED01
byte Ausgangsstatus01 = 0;
unsigned long Sekundenablauf01 = 0; // Ausgang Schaltzeit auf 1000ms 3 Sekunden einrichten
const unsigned long Pausezeit01 = 1000;
//-----------------------AusgangPIN7-------------------------------------
const byte Ausgang02 = 7;          // Pin 7 ist für LED02
byte Ausgangsstatus02 = 0;
unsigned long Sekundenablauf02 = 0; // Ausgang Schaltzeit auf 2000ms 1 Sekunde einrichten
const unsigned long Pausezeit02 = 2000;
//-----------------------AusgangPIN8-------------------------------------
const byte Ausgang03 = 8;          // Pin 8 ist für LED03
byte Ausgangsstatus03 = 0;
unsigned long Sekundenablauf03 = 0; // Ausgang Schaltzeit auf 3000ms 1 Sekunde einrichten
const unsigned long Pausezeit03 = 3000;
//===================Deklarationen Ende=========================================================================
void setup() {
  //-----------Ausgänge einrichten--------------------------------------
  pinMode(Ausgang01, OUTPUT);                 // Pin 6 (Ausgang01) ist als Ausgang aktiviert
  pinMode(Ausgang02, OUTPUT);                 // Pin 7 (Ausgang02) ist als Ausgang aktiviert
  pinMode(Ausgang03, OUTPUT);                 // Pin 8 (Ausgang03) ist als Ausgang aktiviert
}
//====================Setup Ende================================================================================
void loop() {
  //-------------Ausgang01 schalten-------------------------------------------
  if (millis() - Sekundenablauf01 >= Pausezeit01) { // 1000msec abgelaufen?
    Ausgangsstatus01 = ! Ausgangsstatus01;          // Status wechseln
    digitalWrite (Ausgang01, Ausgangsstatus01);     // Ausgang01 LED umschalten
    Sekundenablauf01 = millis();
  }
  //-------------Ausgang02 schalten-------------------------------------------
  if (millis() - Sekundenablauf02 >= Pausezeit02) { // 2000msec abgelaufen?
    Ausgangsstatus02 = ! Ausgangsstatus02;          // Status wechseln
    digitalWrite (Ausgang02, Ausgangsstatus02);     // Ausgang02 LED umschalten
    Sekundenablauf02 = millis();
  }
  //-------------Ausgang03 schalten-------------------------------------------
  if (millis() - Sekundenablauf03 >= Pausezeit03) { // 3000msec abgelaufen?
    Ausgangsstatus03 = ! Ausgangsstatus03;          // Status wechseln
    digitalWrite (Ausgang03, Ausgangsstatus03);     // Ausgang03 LED umschalten
    Sekundenablauf03 = millis();
  }
}
//=======================Loop Ende==============================================================================

Benutzeravatar
Admin
Administrator
Beiträge: 1194
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: millis() anstelle von delay()

Beitrag von Admin »

Wichtig ist, dass man die Millis zwar als Ersatz für delay() nutzt, nicht aber auf die selbe Art. Wenn ich ein delay(1000) im Code habe, dann bleibt das PRogramm an dieser Stelle stehen und macht 1000ms also eine Sekunde gar nichts mehr.

Das Programm mit den millis() wirkt ganz anders. Hier mal eine Probe. Da wird eine Ausgang, z.B. für eine LED, oder ein Relais im Sekundentakt umgeschalten.

Code: Alles auswählen

// Deklarationen:
//-----------------------Ausgang1 - PIN6-------------------------------------
const byte Ausgang01 = 6;          // Pin 6 ist für LED01
byte Ausgangsstatus01 = 0;
unsigned long Sekundenablauf01 = 0; // Ausgang Schaltzeit auf 1000ms 1 Sekunde einrichten
const unsigned long Pausezeit01 = 1000;

void setup(){
 pinMode(Ausgang01, OUTPUT);                 // Pin 6 (Ausgang01) ist als Ausgang aktiviert
}

void loop() //------------ Loop beginn--------------------------------------------------------------------------------------------------
{
  //-------------Ausgang01 schalten-------------------------------------------
  if (millis() - Sekundenablauf01 >= Pausezeit01) { // 1000msec abgelaufen? // Ist eine Sekunde abgelaufen?
// Immer wenn eine Sekunden abgelaufen ist, kommt das Programm einmal hier rein und fürt das heir aus.
    Ausgangsstatus01 = ! Ausgangsstatus01;          // Status wechseln
    digitalWrite (Ausgang01, Ausgangsstatus01);     // Ausgang01 LED umschalten
    Sekundenablauf01 = millis(); // Hier wird wieder eine neuen Sekunde Pause eingestellt
  }
// Wenn diese Sekunde noch nicht abgelaufen ist, wird das übersprungen und es geht hier weiter

} // ------------------Loop Ende, es geht wieder oben beim Loop beginn weiter.
Hier wird das Programm also nicht gestoppt, sondern es läuft weiter. Der Teil der eine Sekunden nichts machen soll wird einfach eine Sekunde lang übersprungen / umgangen. Alles was in diesem Teil zwischen den spitzen Klammern steht, wird nur einmal in der Sekunde ausgeführt. Der ganze Loop wird aber weiterhin alle paar Millisekunden wieder ausgeführt. Das heißt, es werden weiterhin alle paar ms Tasten abgefragt, Sensoren abgefragt, und, und, und. Es geht also keine Aktion verloren. Man braucht keinen Interuppt, um irgend einen Pups nicht zu übersehen!!
Benutzeravatar
Admin
Administrator
Beiträge: 1194
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: millis() anstelle von delay()

Beitrag von Admin »

Hier habe ich in einer anderen Rubrik noch einen Erklärungsversuch gemacht. Vielleicht ist der einläuchtender.

Franz
Antworten

Zurück zu „Programmierung der 8Bit Controller“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste