Weltweiter kostenloser Versand ab 120 € Bestellwert – Zahlung mit PayPal und Stripe – Hergestellt in Finnland

Ruuvi Firmware – Teil 4: Button-Interrupt

Ruuvi Firmware-Serie Teil 3 Intro-Bild

In diesem Teil des Tutorials erweitern wir die GPIO-Treiber, um RuuviTag aus dem in Teil 1 implementierten Yield aufzuwecken und die in Teil 3 umgesetzte LED-Cycling-Task zu starten. Den finalen Code dieses Blogposts kannst du auf Ruuvi GitHub im ruuviblog-Branch herunterladen, Tag 3.4.2-alpha.

Bitte folge Teil 1 der Serie für Details zum Klonen des Repositories und Kompilieren des Codes. Die finale Hex-Datei dieses Tutorials kann vom Ruuvi Jenkins heruntergeladen werden.

Babys erster Input

Im letzten Teil unserer Serie hatten wir ein Problem: Unser Tag hatte keinen Input aus der Außenwelt oder von internen Peripheriegeräten. Daher konnten wir nicht schlafen gehen und auf ein Ereignis warten, sondern mussten stattdessen in einer Schleife mit fester Verzögerung laufen – wodurch unser Tag wach bleiben und die Batterie leerziehen musste. Das beheben wir mit Interrupts über die Buttons.

Ruuvi firmware.c Architektur 3.4.0
GPIO-Treiber haben jetzt Interrupts, und ein Tastendruck ruft die LED-Task auf.

GPIO-Interrupt

Schnittstelle

Unsere Schnittstelle definiert mögliche Flanken für den GPIO-Interrupt: High-to-Low, Low-to-High und Toggle. Zusätzlich definieren wir „unknown“ für den Fall der Fälle. Der Interrupt-Event-Typ mit Quell-Pin und Flanke ist definiert; wir geben dieses Event an unsere Pin-Interrupt-Funktion weiter.

Wir haben zwei Initialisierungsfunktionen: eine für das GPIO-Modul und eine für den spezifischen Interrupt. Die Modulinitialisierung bekommt als Parameter die Adresse eines Arrays von Funktionszeigern; so vermeiden wir, das Treibermodul an ein Board-Modul zu binden, in dem die Anzahl der GPIO-Pins definiert wäre.

ruuvi_gpio_interrupt.h
ruuvi_gpio_interrupt.h

Implementierung

Wie zuvor implementieren wir die Funktionalität, indem wir Aufrufe an das Nordic SDK weiterreichen. Außerdem speichern wir eine Lookup-Tabelle mit Zeigern auf Interrupt-Funktionen und leiten Interrupts nach dem Auftreten an die jeweilige Funktion weiter.

Anfang von ruuvi_platform_gpio_interrupt.c
Anfang von ruuvi_platform_gpio_interrupt.c
Ende von ruuvi_platform_gpio_interrupt.c
Ende von ruuvi_platform_gpio_interrupt.c

Button-Task hinzufügen

Wir wollen task_led_cycle() bei einem Tastendruck auslösen. Daher definieren wir zunächst einen Funktionszeiger mit passender Signatur für die Task. Unsere Task-Initialisierung bekommt dann Flanke und Funktionszeiger als Parameter.

task_button.h
task_button.h

Unsere Button-Task-Implementierung kapselt den task_button_fp_t in ruuvi_interface_gpio_interrupt_fp_t und ruft die GPIO-Interrupt-Initialisierung auf. Hier können wir die GPIO-Nummerndefinition aus ruuvi.boards.c einbinden.

task_button.c
task_button.c

Unsere main-Funktion ruft dann task_button_init mit einer festen slope und task_led_cycle als Funktion auf, die bei Tastendruck ausgeführt wird. Wir könnten die #define für slope und action auch in der Application-Configuration-Headerdatei setzen, aber da das hier nur eine Demonstration ist, wie man Interrupts nutzt, bleiben wir vorerst bei den hartcodierten Werten.

main.c
main.c

Stromverbrauch

Wir sind in diesen Teil der Blogserie mit katastrophalem Stromverbrauch gestartet – mit dem Ziel, das zu beheben. Schauen wir, wie gut uns das gelungen ist!

Wenn du das Programm ausführst, fällt dir ein Problem auf: Im Button-Code gibt es kein Entprellen, sodass ein Tastendruck als zwei oder sogar drei Drücke registriert werden kann. Später könnten wir eine RTC für den Button hinzufügen, um den Zeitpunkt des letzten Interrupts zu speichern und Events zu verwerfen, die zu kurz nach der letzten Aktion auftreten.

Leistungsprofil
Unser Schlafstromverbrauch liegt jetzt wieder bei 4,1 μA, gegenüber 3,6 μA im letzten Teil.
Leistungsprofil
Unser maximaler Stromverbrauch hat sich ebenfalls verbessert: auf 2,46 mA, gegenüber 8,10 mA im vorherigen Teil.

Jetzt sind wir wieder bei guten Werten für den Schlafstrom: 4,1 μA. Zwar haben wir den LED-Verbrauch verbessert, weil die CPU schlafen kann, aber die LEDs eingeschaltet zu lassen, verbraucht bei batteriebetriebenem Betrieb weiterhin unnötig viel Strom.

Bleib dran und folge @ojousima und @ruuvicom auf Twitter für #FirmwareFriday-Beiträge!