Timer mit Arduino – Alternative zu Delays

Die Delay-Funktion in Arduino ist sehr nützlich. Sie hält das laufende Programm um eine angegebene Zeit an. Doch hier liegt ebenfalls das Problem. Oft will man, dass das Programm weiter läuft, um z. B. auf Eingaben oder Sensorwerte reagieren zu können. Hier helfen Timer-Funktionen weiter.

Beispiel mit Delay-Funktionen

int led = 13;

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

void loop() {
  digitalWrite(led, HIGH);
  delay(1000);            
  digitalWrite(led, LOW);
  delay(1000);           
}

Hier hilft das Konzept der Timer-Funktion. Dabei wird zu einem bestimmten Zeitpunkt eine Art Stoppuhr gestartet. Ist eine bestimmte Zeit erreicht, wird ein Ereignis ausgeführt.

Das Arduino-Board hat zwar keine eingebaute Uhr, zählt aber doch die Millisekunden seit dem letzten Start mit. Der Befehl, mit dem man die Millisekunden erhalten kann heißt:

millis()

Er liefert eine ganze Zahl im Wertebereich long zurück (Der Variablentyp long ist wie int, jedoch mit größerem Wertebereich bis 2 147 483 647).

Wir können millis() also als Referenzpunkt verwenden. D.h., wir speichern die aktuellen Millisekunden zu einem bestimmten Zeitpunkt in der Variable myTimer. Nun prüfen wir im weiteren Programmverlauf regelmäßig, ob dieser gespeicherte Zeitpunkt plus einer festgelegten Intervallzeit kleiner ist, als die aktuelle Zeit: Ist (Aktuelle Zeit > Startzeitpunkt + Intervall)?

if (millis() > myTimeout + myTimer) {

Sobald diese Bedingung war ist, wird der Inhalt in den geschweiften Klammern ausgeführt. Im Beispiel wird also eine Variable ledState umgekehrt und ihr Wert per digitalWrite() an eine LED geschickt. Wichtig ist, dass wir die Variable myTimer auf die aktuelle Zeit setzen:

myTimer = millis(); 

Stell es dir so vor, als ob du eine Stoppuhr zurücksetzt . Insgesamt sieht das Programm dann so aus:

const int ledPin =  10;

int ledState = LOW;
long myTimer = 0;
long myTimeout = 1000;

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

void loop() {
  if (millis() > myTimeout + myTimer ) {
    myTimer = millis();

    if (ledState == LOW) ledState = HIGH;
    else ledState = LOW;

    digitalWrite(ledPin, ledState);
  }
}

Dieses Vorgehen hilft bei vielen Programmen, die man nicht mit einem Delay blockieren will. Sehen wir uns ein Programm an, das zwei LEDs in unterschiedlichen Geschwindigkeiten blinken lässt:

const int ledPin1 =  10;
const int ledPin2 =  8;

int ledState1 = LOW;
long myTimer1 = 0;
long myTimeout1 = 700;

int ledState2 = LOW;
long myTimer2 = 0;
long myTimeout2 = 200;


void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}

void loop() {
  if (millis() > myTimeout1 + myTimer1 ) {
    myTimer1 = millis();

    if (ledState1 == LOW) ledState1 = HIGH;
    else ledState1 = LOW;

    digitalWrite(ledPin1, ledState1);
  }

  if (millis() > myTimeout2 + myTimer2 ) {
    myTimer2 = millis();

    if (ledState2 == LOW) ledState2 = HIGH;
    else ledState2 = LOW;

    digitalWrite(ledPin2, ledState2);
  }
}

Der Modulo Trick – Ein einfacher Timer mit Arduino

Manchmal will man aber einfach nur eine regelmäßige Funktion ohne delay()-Befehle ausführen. Dafür gibt es einen eleganten Weg: Der Modulo-Operator %. Dieser liefert den Rest einer Division. Teilt man z.B. millis() durch 1000 wird eine Zahl von 0 bis 999 zurückgeliefert. Damit lässt sich doch was anfangen. Wenn du jetzt diese Zahl darauf prüfst, ob sie größer oder kleiner als z.B. 500 ist, hast du eine Blink-Funktion ohne das Variablen-Wirrwarr.

int led = 13;

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

void loop() {
  if (millis() % 1000 > 500) {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }
}

Ich hoffe, du findest das genau so cool, wie ich. Viel Spaß damit :-)

Hast du weitere Fragen? Probier doch mal unser brandneues Forum zu Arduino aus!

2 thoughts on “Timer mit Arduino – Alternative zu Delays

  1. Hallo Stefan,

    vielen Dank für Deinen Beitrag, Du hast mir echt wirklich gut weitergeholfen! Die Erklärung sehr anschaulich, gerade mit den beiden unterschiedlichen Timern am Ende. Das kann ich in meinem Programm gut verwenden!

    Viele Grüße
    Leo

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Ich akzeptiere

 

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.