GPIO_interrupt-Steuerung

Alle Fragen zur Programmierung, die nicht in die speziellen Themen passen
Antworten
Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

GPIO_interrupt-Steuerung

Beitrag von Leopard » Mi 13. Feb 2019, 19:24

Hallo Gambas-Freunde,

ich habe mit Gambas meine ersten Schrittchen gemacht (Ein- ud Ausgabe von Signalen auf den Standard-GPIO funktioieren problemlos (ist ja auch kein Hexenwerk)).

Jetzt arbeite ich daran, spontan auftretende Zustandsänderungen an den Eingängen abfangen / auswerten zu können, ohne dabei über ein Zeitfunktion periodisch deren Zustand abzufragen (z.B. mit digitalRead(17)), um auch bei sehr schnell aufeinanderfolgenden Zustandsänderungen keine zu verpassen oder das System sehr stark zu belasten.

Mein aktueller Ansatz geht in die Richtung mit der Funktion wiringPiISR() aus der WiringPi-Bibliothek. Mit dem nachfolgenden (Mini-) Programm wird ein Form mit einem Label angezeigt.

Code: Alles auswählen

 ‘Um den nachfolgenden Code auszführen brauchst du ein Form und ein Label. 

Library "/usr/lib/libwiringPi"

Public Extern wiringPiSetupGpio() As Integer
Public Extern pinMode(pin As Integer, pud As Integer)
Public Extern pullUpDnControl(pin As Integer, mode As Integer)
Public Extern digitalRead(pin As Integer) As Integer
Public Extern digitalWrite(pin As Integer, value As Integer)
Public Extern wiringPiISR(aa As Integer, bb As Integer, cc As Pointer) 

Public TestZaehler_FunktionAufruf As Integer

Public Sub Form_Open()

TestZaehler_FunktionAufruf = 0

wiringPiSetupGpio()

pinMode(17, 0)     'GPIO17 soll ein Eingang sein

TestFunktion1()
'ruft zu Testzwecken die Function TestFuktion1 auf

wiringPiISR(17, 1, TestFunktion1)


Public Function TestFunktion1()
' 'Diese Function wird aufgerufen, wenn am GPIO17 ein Ereignis aufgetreten ist: steigende Flanke 

TestZaehler_FunktionAufruf = TestZaehler_FunktionAufruf + 1

Label1.Text = "Die Function Testfunktion1 wurde " & TestZaehler_ProzedurAufruf & " Mal aufgerufen"

End


Das kleine Projekt startet ohne Fehler. Wenn ich jedoch an den GPIO17 (Pin11) 3,3V (Pin1) anlege, kommt folgende Fehlermeldung:

Bild

Leider hab ich keine zielführende Hilfe oder Hinweise zu "wiringPiISR()" gefunden, schon gar nicht im Zusammenhang mit Gambas.
In der Bibliothek pigpio habe ich auch keine vergleichbare Funktion gefunden, mit der ein Interrupt-Ereignis ausgewertet werden könnte. Vor langer Zeit habe ich sowas schon mal in Python realisiert. Vielleicht kann man das ja mit einer Shell-Anweisung erreichen, da kenne ich mich aber nicht aus. Ich bin für jede Hilfe dankbar.

Viele Grüße von

Leopard
Dateianhänge
Bildschirmfoto vom 2019-02-07 19-13-19mod.png
Bildschirmfoto vom 2019-02-07 19-13-19mod.png (79.03 KiB) 457 mal betrachtet

SommerWin
Foriker
Beiträge: 65
Registriert: Do 26. Jan 2017, 20:02
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von SommerWin » Sa 16. Feb 2019, 21:28

Schönen Abend,
vielleicht hilft dieser Link weiter:

http://captainbodgit.blogspot.com/2014/ ... or-to.html

Da ist ein kleines Beispiel mit Gambas enthalten.

Schöne Grüsse
Kurt

Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von Leopard » So 17. Feb 2019, 10:23

Hallo Kurt,

vielen Dank für den Hinweis auf den Link. Er hilft aber leider nicht weiter. Dort wird ein Ansatz verfolgt, der kein echter Interrupt ist, sondern bei nicht allzu häufiger Überwachungsfolge (ca. alle 50 ms) behelfsmäßig nicht allzu kurze und schnelle Zustandsänderungen am Eingang erkennt und immer wieder "nachsieht", auch wenn sich gar nichts geändert hat. Für mein Projekt ist das ganze nicht geeignet: Da kann am Eingang, oder auch an mehreren, lange Zeit alles ruhig sein, dann allerdings können in sehr schneller Folge sehr kurze Ereignis eintreffen, und keines darf übersehen werden bzw. unausgewertet bleiben. Das geht nur mit einem
echten Interrupt.

Auch der Autor des Artikels kennt dieses Problem:
Once again, Gordon Henderson's wiringPi library is probably a good starting point for implementing an interrupt in your code. There are many Python examples out there that you can refer to.

For Gambas enthusiasts the outlook is not so bright. After reading the wiringPi documentation on wiringPiISR, you would expect it to work with Gambas, but unfortunately not. From what I understand, according to Mr. Gambas (Benoit) wiringPi would need to be modified to meet the needs of Gambas.
Der o.g. Beitrag ist schon über 4 Jahre alt, und so habe ich die Hoffnung, dass die Funktion wiringPiISR aus der wiringPi-Bibliothek mittlerweile auch für Gambas nutzbar ist. Die Funktion wiringPiISR ist ja gerade eine echte Interrupt-FunktionWie mein voriger Beitrag zeigt, scheint ja formal auch an der Syntax meines kurzen Codes nichts fehlerhaftes vorzuliegen, denn das Programm startet ja anstandslos. Nur wenn das passiert, wofür es geschrieben wurde - wenn am Eingang ein Ereignis Eintritt - stürzt es ab (nach einer Bearbeitungszeit von ca. 1 Sekunde mit der dort gezeigten Fehlermeldung).

Ich habe die in der Fehlermeldung gebotene Option einen "Fehlerbericht per Mail senden" aktiviert und (im Eingabefeld) mehrfach die Reproduzierbarkeit des Fehlers beschrieben und mit der Angabe meiner Mail-Adresse abgeschickt. Ich weiss nicht an wen diese Maisl gegangen sind und ob man da je einne Antwort erhält. Vielleicht weiss das ja jemeand aus der Community.

Benutzeravatar
cogier
Foriker
Beiträge: 32
Registriert: Do 19. Jul 2018, 16:18
Wohnort: Guernsey, Channel Islands
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von cogier » So 17. Feb 2019, 15:49

ch habe das hier gefunden, das helfen könnte.http://abyz.me.uk/rpi/pigpio/

Ich habe vor einiger Zeit einen'GPIO'-Leser geschrieben, aber er verwendet auch einen Timer. Ich füge es bei, falls es von Interesse ist.

Bild
GPIO.tar.gz
(51.05 KiB) 39-mal heruntergeladen

SommerWin
Foriker
Beiträge: 65
Registriert: Do 26. Jan 2017, 20:02
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von SommerWin » So 17. Feb 2019, 18:39

Sorry... aber ein Interrupt Ereignis muss man immer in einer Scheife abfragen.
Das geht gar nicht anders, selbst in Assembler ist das nicht möglich...
Da wurde ein Teil des Programms in einen bestehenden Interrupt eingebunden und bei einem bestimmten Ereignis ein Flag gesetzt. Das Hauptprogramm fragt dann in einer Scheife permanent dieses Flag ab und reagiert darauf.
Das ganze iss nur so schnell, dass man den Eindruck hat, es geschieht gleichzeitig.

In deinem Fall läuft das Interrupt Programm in der wiringPI Bibliothek und diese löst bei (z.B. Schalter ein/aus an einem bestimmten Port Eingang) ein Ereignis aus. Dann gibt sie entsprechende Daten aus und diese können dann in deinem Programm und da spielt die Programmiersprache keine Rolle weiter verarbeitet werden.
Heisst also, dein Programm muss in einer Schleife permanent den Zustand der wiringPi Flags überprüfen und dann entsprechend verzweigen.

Nachtrag: Ich glaube aber zu verstehen was du willst. Du möchtest, dass dein Gambas Programm ein Teil der Interrupt Routine wird. Das ist denk ich nicht möglich. Dazu fehlen die entsprechenden Befehle, bezweifle auch dass das mit VB geht.
Dazu müsstest du den betreffenden Interrupt zuerst stoppen (z.B. mit dem Maschinenbefehl cli) dann deine Programmroutine (die muss dann übersetzt in Maschinensprache vorliegen) einbinden und dann den Interrupt wieder weiter laufen lassen (Maschinenbefehl SeI).

Schöne Grüsse
Kurt

Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von Leopard » Mo 18. Feb 2019, 13:29

Hallo Kurt,

natürlich wird ein Interrupt realisiert, indem ein (Signal-) Eingang immer wieder in einer (zeitlich wiederkeherenden) Schleife abgefragt wird, ob eine Zustandsänderung vorliegt. Es stellt sich nur die Frage, an welcher Stelle das passiert und in welcher zeitlichen Abfolge.

Natürlich kann man das in seinem eigenen Programm realisieren, wie ja auch schon angesprochen und in vielen Beiträgen gezeigt.

Wie schon erwähnt, nutzt dieser Ansatz nichts bei zeitkritischen Anforderungen an das Programm. Dies wird auch in dem Beitrag

http://wiringpi.com/reference/priority- ... 1,15700248

beschrieben und erkannt. Ich habe die entsprechende Passage aus dem o.g. Beitrag mit "DeepL Übersetzer" übersetzt:

int VerdrahtungPiISR (int pin, int edgeType, void (* function) (void));

Diese Funktion registriert eine Funktion, um Interrupts auf dem angegebenen Pin zu empfangen. Der Parameter edgeType ist entweder INT_EDGE_FALLING , INT_EDGE_RISING , INT_EDGE_BOTH oder INT_EDGE_SETUP . Wenn es sich um INT_EDGE_SETUP handelt, erfolgt keine Initialisierung des Pins. Es wird davon ausgegangen, dass Sie den Pin an anderer Stelle bereits eingerichtet haben (z. B. mit dem Programm gpio ). Wenn Sie jedoch einen der anderen Typen angeben, wird der Pin exportiert und als initialisiert spezifizierten. Dies wird durch einen geeigneten Aufruf des gpio- Hilfsprogramms erreicht, daher muss es verfügbar sein.

Die Pin-Nummer wird im aktuellen Modus bereitgestellt - native wiringPi, BCM_GPIO, physikalisch oder Sys.

Diese Funktion kann in jedem Modus verwendet werden und benötigt keine root-Berechtigungen, um zu funktionieren.

Die Funktion wird aufgerufen, wenn der Interrupt ausgelöst wird. Wenn es ausgelöst wird, wird es vor dem Aufruf der Funktion im Dispatcher gelöscht. Wenn also ein nachfolgender Interrupt ausgelöst wird, bevor Sie den Handler beenden, wird er nicht übersehen. (Es kann jedoch nur einen weiteren Interrupt nachverfolgen. Wenn mehr als ein Interrupt ausgelöst wird, während einer bearbeitet wird, werden diese ignoriert.)

Diese Funktion wird mit hoher Priorität ausgeführt (wenn das Programm mit sudo oder als root ausgeführt wird) und wird gleichzeitig mit dem Hauptprogramm ausgeführt. Es hat vollen Zugriff auf alle globalen Variablen, offene Dateizugriffsnummern usw.

Weitere Informationen zur Verwendung dieser Funktion finden Sie im Beispielprogramm isr.c.

Ich bleibe dabei: der wesentliche Zweck für die Verwendung eines (internen) Interrupts ist es, eine Änderung des Eingangspegels (quasi) im Hintergrund zu erkennen, sodass mein Programm seine andere Aufgaben erledigen kann, ohne ständig - über einen selbst implementierten Timer - Zustandsänderungen abfragen zu müssen.

Und genau dazu dient das Werkzeug aus der wiringPi-Bibliothek

"wiringPiISR (pin, edgeType, function)

Wie anders könnte man sonst sehr kurze (wenige us lange) und sehr schnell aufeinanderfolgende Zustandsänderungen auswerten (z.B. zählen). Welche Aufgabe hätte dann aber eine Funktion wie "wiringPiISR()", wozu wurde sie entwickelt? Wenn du einen anderen Lösungsweg siehst wäre das natürlich prima.



Beste Grüße
Winfried

Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von Leopard » Mo 18. Feb 2019, 21:19

Hallo cogier, hallo Kurt,

vielen Dank für den Hinweis auf die pigpio-Bibliothek. Ich hab mir die Funktionen der pigpio-Bibliothek noch nicht genauer angesehen, weil ich in verschiedenen Quellen gelesen habe, dass die dort implementierte Funktion für Interrupts unter Gambas nicht funktioniert (wie auch die meisten dieser Funktionen nur unter C oder Python funktionieren). Ich werden mir unter all den vielen Funktionen wohl zunächst mal gpioSetISRFunc vornehmen. Da steckt ISR (=Interrupt-Service-Routine) drin und scheint am ehesten zielführend zu sein.

Ich weiss zwar noch nicht wie, aber vielleicht komme ich da mit einem Beispiel-Code unter C / Python und der Shell-Anweisung unter Gambas weiter.
Ich betrete da aber auch schon mit Shell absolutes Neuland.

Nochmals zurück zum Thema Interrupt.

Vielleicht habe ich ja auch ein grundlegend falsches Verständis von Interrupts. Dann wäre ich dankbar für Hinweise "auf den rechten Weg". Mein vereinfacht dargestelltes Verständnis für das Funktionsprinzip eines Interrupts sieht wie folgt aus:

Das Hauptprogramm verarbeitet seine Routinen oder ist im Standby, falls nichts anliegt.
Am Interrupt-Eingang des PCs (z.B. am GPIO17, der als Interrupt konfiguriert ist) tritt ein Interrupt-Ereignis auf. So erkennt der Prozessor eine Zustandsänderung von Low nach High am GPIO17 nur dann als Interrupt, wenn dieser auf eine steigende Flanke reagieren soll. Dann unterbricht der Prozessor das Hauptprogramm, merkt sich die Stelle, an der das Hauptprogramm in seiner Befehlabfolge gerade stand, und bearbeitet das Unterprogramm „Testprogramm_für _Interrupt“ oder stößt dessen Bearbeitung an. Danach kehrt er an die Stelle des Hauptprogramms zurück, an der er das Hauptprogramm mit Auftreten des Interrupts verlassen hat und bearbeitet das Hauptprogramm weiter.

WiringPi stellt mit seiner Funktion wiringPiISR(PinNr, Ereignisflanke, [optional Verzögerungszeit], auszuführendes Unterprogramm) ein Werkzeug zur Verfügung, mit der ein Interrupt leicht zu realisieren ist.

Mit wiringPiISR(17, 1, „Testprogramm_für _Interrupt“) müsste also mit aufsteigenden Flanke am GPIO17 das Unterprogramm „Testprogramm_für _Interrupt“ gestartet werden.

Man könnte das vielleicht vergleichen – wobei jeder Vergleich (irgendwie) hinkt – mit einem Programm, das alles Mögliche erledigt und in dessen Bedienoberfläche es einen Button1 gibt, der ansonsten eigentlich keine Aufgabe hat und mit dem allgemeinen Programmablauf auch nichts zu tun hat. Mit einer Ausnahme: wenn er angeklickt wird, wird das Hauptprogramm unterbrochen und das Ereignisprogramm „Public Sub Button1_Click“ aufgerufen und ausgeführt, bevor das Hauptprogramm fortgesetzt wird.

Ich bin für alle Hinweise, Ratschläge und besonders konkrete Beispiele sehr dankbar.

Mit besten Grüßen

Winfried

SommerWin
Foriker
Beiträge: 65
Registriert: Do 26. Jan 2017, 20:02
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von SommerWin » Mi 20. Feb 2019, 00:39

Schönen Abend,
ich weiss nicht ob mein Denkansatz funktioniert aber ich würd das so probieren:
Wenn der Interrupt ausgelöst wird, startet ein eigenständiges Programm mit einem Hinweisfenster.
Die Variablen oder Ausgaben werden nach /tmp abgelegt.
Im Hauptprogramm baut man einen KlickButton ein, der liest die Daten aus /tmp und verarbeitet sie weiter. Somit muss das Hauptprogramm auch nicht unterbrochen oder angehalten werden.

Schöne Grüsse
Kurt

Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von Leopard » Mi 20. Feb 2019, 11:58

Hallo Kurt,

im Prinzip - so glaube ich - meinen wir ja (fast) dasselbe. Unterschiedlicher Meinung sind wir in der Frage, wer oder was den Interrupt anstößt, nicht in dem Punkt, was anschließend (also wenn der Interrupt initialisiert wurde) geschehen soll.

In dem Beitrag http://captainbodgit.blogspot.com/2014/ ... or-to.html den du am Samstag geschickt hast, ist die Problematik ja sauber dargestellt: Der Verfasser beschreibt ja schön, dass die Funktion wirigPiISR aus der wirigPi-Bibliothek der beste Ansatz wäre:
...was ist mit einem Interrupt? Der zweite Ansatz ist die Verwendung eines Interrupts, der im Wesentlichen eine Änderung des Eingangspegels im Hintergrund erkennt, sodass Ihr Programm andere Aufgaben erledigen kann.
Der Verfasser stellt dann aber fest, dass dies in Gambas nicht möglich ist:
Für Gambas-Enthusiasten ist der Ausblick nicht so gut. Nachdem Sie die wiringPi-Dokumentation zu wiringPiISR gelesen haben, würden Sie damit rechnen, dass sie mit Gambas zusammenarbeitet, aber leider nicht.
Deshalb bringt er anschließend einen Lösungsvorschlag, der aber ebenfalls seine Grenze in der für meine Zweck viel zu geringen Abtastrate von 50ms findet:
Dieser Code funktioniert in Ordnung, solange Sie nicht in 50ms mehr als einmal vorkommende Eingangsübergänge zählen müssen (oder wie auch immer das Zeitgeberintervall ist, solange es nicht unangemessen niedrig ist).
Für meine Aufgabenstellung benötige ich eine Samblingrate von 0,5 ... max. 1ms. Dies kann aber eigentlich keine Überforderung des GPIO-Systems und der zugehörigen Systemsoftware darstellen, das ja schließlich an den speziellen Eingängen deutlich schnellere Zustandsänderungen (also höhere Baudraten) bewältigen muss.

Der o.a. Verfasser verweist ja darauf, dass die Auswertung von Interrupts mittels wiringPiISR wenn schon nicht in Gambas so aber doch leicht in Python möglich ist. Ich habe auch schon früher mal Beträge gelesen, in denen in Python-Projekten sehr schnelle Zustandsänderungen an GPIOs dazu benutzt wurden um (echte) Interrupts zu verarbeiten.

Weiss jemand, ob man Python-Code aus Gambas heraus anwenden oder in Gambas integrieren kann. Das wäre dann ein möglicher Lösungsansatz.

Bis bald

Winfried

Leopard
Foriker
Beiträge: 22
Registriert: Di 8. Jan 2019, 15:49
Kontaktdaten:

Re: GPIO_interrupt-Steuerung

Beitrag von Leopard » Mi 20. Feb 2019, 20:19

Hallo,

ich bin beim Stöbern zum Thema Interrupt auf einen sehr interessanten Artikel Raspberry Pi: Interrupt-Verarbeitung mit Python von Prof. Jürgen Plate (Hochschule München) gestoßen, der die Thematik sehr anschaulich und mit einem gut verständlichen Beispiel (leider für Python) erklärt. Auch wenn man - so wie ich - nur sehr rudimentäre Kentnisse in Python hat, ist der Code auch für einen Gambas-Fan nachvollziehbar. Auf jeden Fall aber sind die Abläufe beim Interrupt sehr gut beschrieben. Vielleicht probiere ich das ganze sogar mal in Python aus.

Es lohnt sich wirklich den Artikel mal anzusehen:

http://www.netzmafia.de/skripten/hardwa ... O_int.html

bis bald

Winfried

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste