Teil 13 des Rasberry Pi I2C Projektes

Multitasking | Multithreadding | Timer | Interrupts

Weiter geht es mit einer grundlegenden Frage, wie werden zeitlich wiederkehrende Routinen abgearbeitet?

Problemstellung

Bei der Programmierung gibt es ein Hauptprogramm, welches die Kontrolle übernimmt. In diesem Fall gibt es innerhalb des Hauptprogrammes (main) eine Sektion um die Initialisierung durchzuführen, als letztes wird dann gtk_main gestartet. Nachdem gtk_main gestartet ist obliegt die Kontrolle quasi dem GTK Manager. Der GTK Manager reagiert u.a. auf Events der grafischen Oberfläche und ruft dann subroutinen auf. Die Kontrolle geht aber immer wieder zum GTK Manager zurück.

Der GTK Manager reagiert auf events in der grafischen Oberfläche. Beispielsweise auf Auswahl eines anderen Wertes in einem Feld oder umlegen eines Schalters

Die Aktualisierung des Spannungswertes der AD-Kanäle kann also nur erfolgen, wenn durch einen Benutzer eine Interaktion über die grafische Oberfläche initiert wird. Das kann über einen REFRESH Button, eine Auswahl in einem Feld, ein klick auf ein Widget der Fall sein. Vorteilhaft ist jedoch wenn die Aktualisierung kontinuierlich und OHNE Interaktion durch einen Benutzer erfolgt, also automatisch in einem zeitlichen Intervall.

Diese Aktualisierung erfolgt parallel zu dem laufenden GTK_MAIN, dem GTK Manager. Ziel ist es ein zeitliches definiertes parallel laufendes Programm zu etablieren, welches im gleichen Environment läuft. Für diese Aufgabe gibt es bei Microcontrollern TIMER. Diese lösen bei einem Überlauf einen Interrupt aus und starten dann eine definierte Unterroutine. Darüber wird eine Parallelisierung erreicht. Alternativ kann man weitere Threads starten. Egal welches Verfahren man nimmt – ziel ist Parallelisierung von Aufgaben zu def. Zeiten.

Lösungsansatz

GTK bringt das nötige Werkzeug dafür mit und macht es generell einfach damit zu arbeiten. Die Funktion welche genau das realisiert ist:

guint g_timeout_add (guint interval, GSourceFunc function, gpointer data);

Innerhalb GTK_MAIN gibt es eine Event Loop. g_timeout_add reiht die Routine zeitlich basiert in die MAIN EVENT LOOP ein. Ist die zeitliche Komponente erreicht sorgt die Event Loop dafür das die benannte Subroutine gestartet wird. Dieses kann ein einmaliges Event oder ein periodischer Aufruf durch den Event Loop Manager sein. Damit die Subroutine wiederholt eingereiht wird ist bei der Rückgabe an die Main Event Loop der Rückgabewert auf TRUE zu setzen. Damit erkennt die Event Loop das die Routine erneut aufgerufen werden soll.

return TRUE;

Mit dieser Information erkennt der MAIN LOOP EVENT HANDLER das es sich um ein periodisches Event handelt.

Um ohne Benutzerinteraktion den Bildschirm mit den aktuellen Spannungswerten zu aktualisieren wird ein „zeitliches Event“ mit g_timeout_add in die Main Event Loop eingetragen. In meinem Fall reicht eine Aktualisierung alle 1.000ms (1Sek) aus. Die aufgerufene Routine fragt den AD-Wandler ab und aktualisiert das GUI. Danach reiht sie den nächsten Start in die Main Event Loop ein. Die Aktualisierung läuft „quasi“ parallel zu GTK_MAIN.

Aktuelles Dashboard