Inhaltsverzeichnis
Interrupts
Interrupts sind ein wichtiger Bestandteil jeder Controller Programmierung. Leider findet man im Netz zuviele Informationen darüber, (darunter leider auch viele Wiedersprüchliche), auf den Arduino Seiten sowie in der Sprache wird das Thema aber nur sehr Stiefmütterlich behandelt.
Was ist ein Interrupt?
Also ein Interrupt ist ein Unterbrechung des „normalen“ Programms. Wird ein INT ausgelöst, schaut der Controller nach, ob der Interrupt behandelt wird und wo das Programm steht, dann sichert er den augenblicklichen Stand wichtiger Register und des Adresszählers und springt dann zu der Behandlungsroutine. Ist die Fertig, wird der ursprüngliche Zustand wiederhergestellt nnd auch das Adressregister und dann geht's an der Stelle einfach weiter.
Viele Quellen können Interrupts auslösen, z.B. die Timer, serielle Schnittstelle, A/D Wandler, WatchDog und sogar jeder Pin des Controllers.
Für uns gibt es 2 wichtige Interruptquellen.
- External Interrupt Request EIR genannt.
Das ist der Interrupt, der per attachInterrupt beim Arduino auf verschiedene Pins gelegt werden kann.
Beim Uno (also bei den 328 basierten Arduinos) sind das die Pin 2 und 3. Wobei Pin 2 den Interrupt 0 und Pin 3 den Interrupt 1 auslöst. Ausgelöst kann bei LOW am Pin, oder bei fallender Flanke, oder steigender Flanke, oder bei jedem Pegelwechsel.
Bei Uno gibt's dann insgesamt 4 EIR (Pin3, 2, 0, 1 Reihenfolge = Nummer). Beim Mega sinds derer 6 ( 2, 3, 21, 20, 19, 18)
WICHTIG: Für jeden Pin gibt es eine eigene Interruptroutine.
- PinChangeInterrupt
Der PinChangeInterupt (PCI) kann durch einen Pegelwechsel auf jeden Pin des Arduinos getriggert werden. Man kann die Pins maskieren, damit nur gewünschten Pins einen Interrupt werfen. Aber im Gegensatz zum EIR gibt es beim PCI nur eine Interruptroutine. In der muss man alle Pins behandeln. D.h. zunächst muss man feststellen welcher Pin überhaupt den Interrupt geworfen hat.
Wichtig wird das ganze, wenn man mehr als 1 Kanal der Fernsteuerung benutzen will. z.B. für einen Kreuzmischer. MIt dem EIR kann man beim UNO max. 2 Kanäle verwenden, beim Uno 4 und beim Mega 6. MIt dem PCI kann man soviele Kanäle überwachen wie man freie Pins am Arduino hat.
Mir persönlich reichten 2 Kanäle bisher eigentlich immer. Deswegen implementiert auch die RCReceiver Bibliothek auch der Weg über den EIR und nicht den PinChange Interrupt.
Wie kann ich das benutzen?
Für die Interrupt Behandlung gibt es 2 Funktionen. Diese heben wir hier schon kennen gelernt. Um jetzt z.B. einen Wechsel am Pin 3 zu behandeln, müssen wir folgendes programmieren:
void setup() { ... // RC Interrupthandler registrieren attachInterrupt(1, RcIntHandler, CHANGE); // INterrupt 1 ist Pin 3 ... } /* Interrupthandler zum messen der RC Implusdauer */ void RcIntHandler() { cli(); ... sei(); }
Nun wird bei jedem Wechsel des Pegels am Pin 3 unsere Funktion RcIntHandler()
aufgerufen. Das können wir uns natürlich für die MEssung des Empfängersignales zu nutze machen.
Mit LOW als letzten Parameter, eine kleinen Lichtschranke und einem kleinen Schutz gegen Prellen, könnten wir z.B. auch einen Rundenzähler für eine Autorennbahn bauen.
Ausblick
Es gibt auf jedem Pin des Controllers einen sog. PCINT# also einen PinChangeInterrupt, d.h. der Controller kann auf jeden Pegelwechsel an jedem Pin einen Interrupt auslösen. Allerdings sind nur 3 Behandlungsfunktionen möglich. Die Pins werden somit in 3 Gruppen zusammengefasst. Man kann allerdings für jeden Pin sagen, ob dieser einen Interrupt auslösen soll oder nicht. Das ganze ist nicht ganz so komfortabel wie der INT#, aber für viele Anwendungsfälle reicht das vollkommen aus. Dazu gibt es auch fertige Bibliotheken für den Arduino. Eine Empfehlung kann ich aber nicht geben, weil ich noch keine der Bibliotheken ausprobiert habe.