INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Zeitkontrolle ohne delay mit millis()
24.11.2019, 12:57 (Dieser Beitrag wurde zuletzt bearbeitet: 24.11.2019 20:34 von Franz54.)
Beitrag #1
Zeitkontrolle ohne delay mit millis()
Weil das Thema millis() immer wieder ein Problem zu sein scheint, habe ich hier mal ein Programm eingestellt, das seine drei verschiedenen Zeiten rein durch millis() kontrolliert und steuert.
Ich denke die Erklärung ist so, dass man es verstehen sollte. Das Programm Block2 sorgt im Betrieb dafür, dass die LED am Pin13 (Pin13-LED beim Uno&Mega auf der Platine vorhanden) immer eine Sekunde an ist und eine Sekunde aus. Aber werend der Sekunde aus greift der Programm-Block3, der im 100ms Abstand die selbe LED ein / aus schaltet.
Am Pin11 kann man eine Taste gegen GND anschließen, die dafür sorgt, dass immer sofort nach dem Druck der Taste die selbe LED durchgehend 5 Sekunden an bleibt. Also 5 Sekunden an ist die Quittung dafür, dass der Tastendruck erkannt wurde. So sieht man, dass egal wo sich das Programm gerade befindet IMMER der Tastendruck erkannt und die zugehörige Funktion (5 Sekunden LED an) ausgeführt wird.

Code:
const byte led01 = 13;

const byte Taster01 = 11;      // Pin 11 wird Constant als Taster01 bezeichnet
byte Tasterstatus01 = 0;       // Zum Abfragen des Tatsenpins
byte Tastenmerker01 = 0;       // Zum Merken des aktuellen Tatsenstatus

unsigned long Sekundenablauf01 = 0; // Zeit wenn Taster gedrückt 5000ms
unsigned long Pausezeit01 = 5000;
byte funktion01 = 0;

unsigned long Sekundenablauf02 = 0; // leuchtzeit led01 300ms aussetzen
unsigned long Pausezeit02 = 1000;
byte funktion02 = 0;

unsigned long Sekundenablauf03 = 0; // Serialprint Ausgabe auf 3000ms aussetzen
unsigned long Pausezeit03 = 100;
byte funktion03 = 0;

int startzeit = 0;
int endzeit = 0;

void setup() {
  pinMode(led01, OUTPUT);
  pinMode(Taster01, INPUT_PULLUP);
}

void loop() {
   startzeit = micros();
  // Block 01 >>>>>>>>>>>>>>>
  // Ist Taste gedrückt?------------------------------------------------------------------------
  if (millis() - Sekundenablauf01 >= Pausezeit01)
  {
    Tasterstatus01 = digitalRead(Taster01); // Pin von Taster01 abfragen
    if (Tasterstatus01 == LOW)
    {
      funktion01 = 1;
      Sekundenablauf01 = millis();      // Der 5000ms Timer01 wird gestartet
      digitalWrite (led01, funktion01);
    }
    else {
      funktion01 = 0;
    }
  }
  // Block 01 Ende <<<<<<<<<<<<

  // Wenn die Taste gedrückt wurde, bleibt die LED 5 Sekunden an, -------------------------------
  // weil die nächsten Blocks 2+3 5Sek. lang übersprungen werden -------------------------------
  if (funktion01 == 0)
  { // Taste wurde gedrückt
    // Block 02 >>>>>>>>>>>>>>
    // Alle 1000ms LED13 an / aus--------------------------------------------------------------
    if (millis() - Sekundenablauf02 >= Pausezeit02)
    {
      funktion02 = !funktion02;
      digitalWrite (led01, funktion02);
      Sekundenablauf02 = millis();      // Der 1000ms Time02 wird gestartet
    }
    // Block 02 Ende <<<<<<<<<<<<
    // Block 03 >>>>>>>>>>>>>>>>>
    // Wenn LED13 für 1000ms aus ist, dann LED13 im 100ms Tackt an / aus----------------------
    if ((millis() - Sekundenablauf03 >= Pausezeit03) && (funktion02 == 0))
    {
      funktion03 = !funktion03;
      digitalWrite (led01, funktion03);
      Sekundenablauf03 = millis();      // Der 100ms Time03 wird gestartet
    }
    // Block 03 Ende <<<<<<<<<<<<
  } // Tastensteuerung Ende
  endzeit = micros();
  Serial.println(endzeit-startzeit);
}
// Loop Ende ----------------------------------------------------------------------------------

Ein kompletter Durchlauf dieses Programmes hier dauert übrigens auf einem Arduino-Mega 16 - 20 microsekunden. Also 16-20 Millionstel Sekunden. Das nur mal, weil so oft für jeden Käse gleich Interrupte programmiert werden. Hier sieht man, dass eine Abfrage eines Pins in dem Programm alle 16-20 Millionstel Sekunden durchgeführt wird. Also z.B. die Abfrage der Taste auf Pin11 in dem Programm.

Es wird also in einer Sekunde 50.000x der Pin11 abgefragt. Natürlich ist es übel, wenn man z.B. einen einzigen delay(1); im Programm hat, wird aus 50.000x gleich nur noch 1000x pro Sekunde !!!
Mit einem einzigen delay(100); im Programm wird nur noch 10x in der Sekunde die Pin11 Abfrage durchgeführt !!! Also der ganze Loop wird nur noch 10x pro Sek. durchfahren!!! Wenn ich jetzt hier ins Programm einen delay(1000); einbaue, dann wird es schon extrem unwarscheinlich dass ich die Taste zu dem Zeitpunkt drücke, wo der Pin auch abgefragt wird. 1 Sekunde geht nichts, dann wird für 10 Millionstel Sek. der Port abgefragt, dann wieder eine Sekunde Pause, dann wird wieder für 10 Millionstel Sek. der Port abgefragt, ...........u.s.w. Es ist also wie ein sechser im Lotto, wenn man da die Taste dann drückt, wenn der Port gerade abgefragt wird.

Das sagt wohl deutlich aus, wo das Problem bei den meisten Programmen liegt, wenn die Tastenabfrage nicht mehr funktioniert. Auch die Ausgabe auf ein Display ist eine gewaltige Bremse. Die darf man nur so oft wie unbedingt nötig durchführen.

Franz

https://www.youtube.com/watch?v=Fnzn85oWM_Q
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
24.11.2019, 16:17
Beitrag #2
RE: Zeitkontrolle ohne delay mit millis()
Man könnte für die byte funktion0x auch bool nehmen.

Das braucht zwar genau soviel Speicher, kann aber nur 0/1, LOW/HIGH, true/false annehmen. Dadurch könnte man die inhaltliche Bedeutung dieser 3 Variablen unterstreichen.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle von mir veröffentlichten Codes unterliegen der GPL Version 3
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
24.11.2019, 16:56 (Dieser Beitrag wurde zuletzt bearbeitet: 24.11.2019 17:06 von Franz54.)
Beitrag #3
RE: Zeitkontrolle ohne delay mit millis()
Hi Tommy,
ich habe "bool" jetzt hier oben mal für Tasterstatus01 übernommen. Weil es bei der Taste ja bestimmt nur 0/1 und HIGH/LOW gibt.

Bei den funktionen01 - 03 bin ich bei "byte" geblieben, weil ich oft mal bei diesen Merkern beim Erweitern von Programmen plötzlich mehr "Stufen" brauchte als nur 0 und 1. Deswegen habe ich bool eigentlich immer "verschmäht" Big Grin Aber beim Tasterstatus oder Relaisstatus kann man es eigentlich sicher nehmen, weil die nun mal nur 0/1 Stellung haben können.

Eine Frage dazu. Ich habe gerade mal im Programm dem "Tasterstatus01" im Programm eine 3 zugewiesen, obwohl er jetzt mit "bool" deklariert ist. Das hat den Compiler überhaupt nicht interessiert. Confused

Also bei den Deklarationen:
bool Tasterstatus01 = 0;

Und dann im Loop():
Tasterstatus01 = 3;

Hat der Compiler anstandslos akzeptiert Confused

Was passiert dann im Programm? ........wird der "Tasterstatus01" dann doch wie "byte" behandelt und er übernimmt die "3", oder wie "bool" und er schießt die zugewiesene "3" in den Wind?

Franz

PS: Ich habe es mal eben getestet.
Code:
bool Tasterstatus01 = 0;

void setup() {
Serial.begin(9600);
}
void loop() {
Tasterstatus01 =3;
Serial-println(Tasterstatus01); // Wurde eine "1" ausgegeben.
}

Also wenn man "bool" deklariert bekommt man im Programm einfach nur nichts höheres als ne "1" in diesen Merker rein.

https://www.youtube.com/watch?v=Fnzn85oWM_Q
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
24.11.2019, 17:05 (Dieser Beitrag wurde zuletzt bearbeitet: 24.11.2019 17:08 von Tommy56.)
Beitrag #4
RE: Zeitkontrolle ohne delay mit millis()
Das liegt an der historischen Definition: Alles was nicht 0 / NULL / nullptr ist, ist true;

Gruß Tommy

Edit: Beim ESP8266 macht er eine 1 aus der 3.

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle von mir veröffentlichten Codes unterliegen der GPL Version 3
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
25.11.2019, 10:32 (Dieser Beitrag wurde zuletzt bearbeitet: 25.11.2019 10:54 von Franz54.)
Beitrag #5
RE: Zeitkontrolle ohne delay mit millis()
Ein kompletter Durchlauf dieses Programmes hier im ersten Beitrag dauert übrigens auf einem Arduino-Mega 16 - 20 microsekunden. Also 16-20 Millionstel Sekunden. Das nur mal, weil so oft für jeden Käse gleich Interrupte programmiert werden. Hier sieht man, dass eine Abfrage eines Pins in dem Programm alle 16-20 Millionstel Sekunden durchgeführt wird. Also z.B. die Abfrage der Taste auf Pin11 in dem Programm.

Es wird also in einer Sekunde 50.000x der Pin11 abgefragt. Natürlich ist es übel, wenn man z.B. einen einzigen delay(1); im Programm hat, wird aus 50.000x gleich nur noch 1000x pro Sekunde !!!
Mit einem einzigen delay(100); im Programm wird nur noch 10x in der Sekunde die Pin11 Abfrage durchgeführt !!! Also der ganze Loop wird nur noch 10x pro Sek. durchfahren!!! Wenn ich jetzt hier ins Programm einen delay(1000); einbaue, dann wird es schon extrem unwarscheinlich dass ich die Taste zu dem Zeitpunkt drücke, wo der Pin auch abgefragt wird. 1 Sekunde geht nichts, dann wird für 10 Millionstel Sek. der Port abgefragt, dann wieder eine Sekunde Pause, dann wird wieder für 10 Millionstel Sek. der Port abgefragt, ...........u.s.w. Es ist also wie ein sechser im Lotto, wenn man da die Taste dann drückt, wenn der Port gerade abgefragt wird.

Das sagt wohl deutlich aus, wo das Problem bei den meisten Programmen liegt, wenn z.B. die Tastenabfrage nicht mehr funktioniert. Auch die Daten-Ausgabe auf ein Display, oder ein Serial.print() mit 9600Baud, ist eine gewaltige Bremse. Die darf man nur so oft wie unbedingt nötig durchführen.

Ich habe mal diese Zeile eingefügt und dann getestet wie lange ein Programmdurchlauf dann dauert.
Code:
Serial.println("Das ist ein Test mit Millis und Micros");

Mit 9600Baud waren das 41620 Microsekunden oder 41,62 Millisekunden.
Mit 115200Baud waren es nur noch 3412 Microsekunden oder 3,412 Millisekunden.
Also auch das ist ein erheblicher Unterschied.

https://www.youtube.com/watch?v=Fnzn85oWM_Q
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Von delay über millis zur Funktion und Klasse Tommy56 5 17.315 06.03.2020 18:05
Letzter Beitrag: Blende8
  Zeitkontrolle mit delay Blende8 10 31.577 07.12.2019 13:08
Letzter Beitrag: Blende8
  Arduino Zugriff auf MySQL Server - !ohne PHP! rkuehle 12 122.286 23.11.2019 22:52
Letzter Beitrag: Joubst
  Blink Without Delay - mal anders erklärt ardu_arne 9 67.056 10.02.2018 17:46
Letzter Beitrag: Claus_M
  millis(), das unbekannte Wesen ardu_arne 1 32.489 06.02.2016 22:17
Letzter Beitrag: Claus_M

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste