INHALT
Was sind externe Interrupts und Hardware-Interrupts bei Arduino? Wie benutzt man Interrupts in einem Programm? Schauen wir uns einfache Beispiele für Interrupts in der Arduino IDE an, in welchen Fällen Interrupts verwendet werden können und wie man sie richtig behandelt. Wir werden Beispielprogramme mit Erklärungen vorstellen und auf die Punkte hinweisen, die bei der Verwendung von Interrupts im Code zu beachten sind.
Bestandteile:
- Arduino Uno / Arduino Nano / Arduino Mega
- Widerstände
- Knöpfen
- Breadboard
- Dupont-Kabel
Unterbrechungen lassen sich einfach anhand eines Beispiels aus dem täglichen Leben erklären. Angenommen der Briefträger bringt Ihnen heute einen sehr wichtigen Brief. Um ihn schneller zu lesen, schauen Sie alle 10 Minuten in Ihren Briefkasten. Dadurch vergeuden Sie Ihre Zeit auf unproduktive Weise. Bei Arduino würde dies bedeuten, dass ständig ein Sensor abgefragt wird und der Prozessor dadurch Ressourcen verschwendet.
Sie können dem Postboten eine Nachricht hinterlassen, damit er den Brief in die Hand gibt, statt ihn wie üblich in den Briefkasten zu legen. Auf diese Weise müssen Sie nicht ständig den Briefkasten kontrollieren und können Ihren Aktivitäten nachgehen. Wenn der Postbote an der Tür klingelt, müssen Sie Ihre Arbeit stoppen, die Tür öffnen und den Brief entgegennehmen. Danach können Sie wieder mit Ihrer Arbeit fortfahren.
Welche Interrupts gibt es in der Arduino IDE Sprache
Interrupts in der Arduino IDE funktionieren ähnlich. Der Mikrocontroller kann beispielsweise auf eine Taste warten, die der Benutzer drückt. Dafür kann man im Programm den Befehl digitalRead() verwenden oder einen Hardware-Interrupt nutzen. Man kann auch einen Hardware-Interrupt nutzen, um Zeit bei der Abfrage des Knopfes zu sparen. Sobald der Knopf gedrückt wird, führt das Hardware-Signal eine Funktion im Arduino-Programm aus.
Die Tabelle zeigt, welche Pins für Interrupts genutzt werden können. Wenn ein Stift auf der Platine nicht mit der Interrupt-Funktion zusammenarbeitet, wird das Programm nicht funktionieren. Interrupts werden ausgelöst, indem das digitale Signal am Eingang geändert wird, und Sie können die Änderung auswählen, die Sie überwachen möchten. Dafür müssen Sie den dritten Parameter in der Funktion attachInterrupt() anpassen.
Syntax des Funktion: attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
digitalPinToInterrupt(pin) – Es ist wichtig, einen bestimmten Pin für die Verarbeitung des externen Interrupt-Signals anzugeben.
ISR – Name der Funktion, die bei Unterbrechung aufgerufen wird
mode – Art des zu bearbeitenden Übergangs (Zustandsänderung), z. B. Stufe abwärts, Stufe aufwärts usw. Die folgenden Werte sind möglich:
- RISING: Wenn das Signal von LOW zu HIGH wechselt
- FALLING: Wenn das Signal von HIGH auf LOW wechselt
- CHANGE: Wenn das Signal von LOW auf HIGH oder von HIGH auf LOW wechselt.
- LOW: Der Interrupt wird jedes Mal ausgelöst, wenn das Signal LOW ist.
Verwendung von Interrupts mit Beispielen in Arduino
Im ersten Beispiel überwacht der Computerchip immer die Zustände der Taste. Wenn die Taste gedrückt wird, schaltet sich die Lampe an. Durch Nutzung von Pin 2 im Interrupt-Modus braucht der Mikrocontroller die Taste nicht abzufragen. Wenn das Signal am Pin, der Interrupts unterstützt, verändert wird, unterbricht der Arduino die Ausführung des Hauptprogrammcodes, ohne den Taster fortwährend abfragen zu müssen.
Programm für Einschalten einer LED ohne Interrupts
#define LED 10 #define BUTTON 2 byte ledState = LOW; void setup() { pinMode(LED, OUTPUT); pinMode(BUTTON, INPUT); } void loop() { if (digitalRead(BUTTON) == HIGH) { ledState = !ledState; } digitalWrite(LED, ledState); }
- Prüfe kontinuierlich, ob die IF-Bedingung erfüllt ist, da sonst unnötig Mikroprozessor-Ressourcen und Zeit verschwendet werden.
Im folgenden Beispiel wird eine einfache Lösung für die Tastensteuerung umgesetzt. Dazu wird eine Funktion an den digitalen Eingang 2 angeschlossen, die durch Drücken der Taste aktiviert wird. Der Hauptprogrammcode in void loop() wird dann angehalten und die Funktion void blinkLed() ausgeführt. Ein großer Vorteil dieser Methode ist, dass die Taste nun nicht mehr manuell im Programm abgefragt werden muss.
Programm mit einem Hardware Interrupt Arduino
#define LED 10 #define BUTTON 2 volatile byte ledState = LOW; void setup() { pinMode(LED, OUTPUT); pinMode(BUTTON, INPUT); attachInterrupt(digitalPinToInterrupt(BUTTON), blinkLed, RISING); } void loop() { } void blinkLed() { ledState = !ledState; digitalWrite(LED, ledState); }
- Beachten Sie, dass es in der Hauptschleife von void loop() keine Befehle gibt.
Was bei der Arbeit mit Interrupts zu beachten ist
Machen Sie die Interrupts-Funktion so schnell wie möglich
Führen Sie die Interrupt-Funktion schnellstmöglich aus, da sie die Ausführung des Hauptcodes Ihres Programms stoppt. Wenn umfangreiche Berechnungen oder lange Aktionen bei einer externen Unterbrechung ausgeführt werden müssen, sollten sie in der void loop() belassen werden. Nur die Zustandsvariablen ändern, die für die benötigten Operationen relevant sind, innerhalb der Unterbrechungsfunktionen.
Verwenden Sie keine Zeitfunktionen in Interrupts
Der Befehl delay() in der Unterbrechungsfunktion wird nicht funktionieren. Wenn Sie die millis()-Funktion als Zeitzähler verwenden, erhalten Sie beim Verlassen der Interrupt-Funktion den zuletzt gespeicherten Wert. Dies liegt daran, dass der Wert von millis() innerhalb der Interrupt-Funktion nicht aktualisiert wird. Wenn man millis() nutzt, um ein Klappern der Taste zu verhindern, empfiehlt es sich, dies in der void loop() durchzuführen.
Verwenden Sie den Port Monitor nicht während Interrupts
Wenn Sie sich in einer Unterbrechung befinden, können Daten, die über serielle Befehle gesendet oder empfangen werden, verloren gehen. Sie können innerhalb des Interrupts Serial.println() verwenden, um das Programm zu debuggen, um sicherzustellen, dass der Interrupt ausgelöst wird. Es ist jedoch besser, ein Flag innerhalb des Interrupts zu setzen und dieses Flag innerhalb von void loop() abzufragen.
Verwenden Sie volatile, um Variablen zu deklarieren
Variablen, die in ISR-Funktionen oder normalen Funktionen verwendet werden, müssen als volatile deklariert werden. Dadurch wird dem Compiler signalisiert, dass sich diese Variablen jederzeit ändern können und der Mikrocontroller bei jedem Zugriff die Variable neu laden muss, anstatt sich auf eine Kopie zu verlassen. Andernfalls kann der Optimierungsalgorithmus die Variable vollständig aus der ausführbaren Datei entfernen.
Schlussfolgerung. Die Nutzung der attachInterrupt-Funktion von Arduino IDE ist sehr praktisch, wenn man sicherstellen möchte, dass der Mikrocontroller keine Veränderungen des zu überwachenden Signals verpasst. Bei der Anwendung von Tastendruck-Interrupts sollte man jedoch darauf achten, diese nicht zu häufig zu verwenden. In manchen Situationen ist es besser eine einfache Sensorabfrage durchzuführen.
Schreibe einen Kommentar