Taste löst Interrupt am GPIO des RPI aus!
Taste löst Interrupt am GPIO des RPI aus!
Wer hat einen funktionierenden Code-Schnipsel, welcher aufgrund eines Tastendrucks einen Interrupt am RaspberrryPi -GPIO auslöst und das auch noch softwaremäßig Tastenentprellt? Geht das auch für mehrere Tasten? Habe im www nichts passendes für Lazarus gefunden. Für Studienzwecke wäre auch eine Dokumentation (Kurzbeschreibung) sehr hilfreich. Ich würde mich über Eure Hilfe sehr freuen.
Danke - Schönen Abend!
Danke - Schönen Abend!
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Schau mal in pascalio nach: https://github.com/SAmeis/pascalio/blob ... fpgpio.pashpt hat geschrieben:Wer hat einen funktionierenden Code-Schnipsel, welcher aufgrund eines Tastendrucks einen Interrupt am RaspberrryPi -GPIO auslöst und das auch noch softwaremäßig Tastenentprellt? Geht das auch für mehrere Tasten? Habe im www nichts passendes für Lazarus gefunden.
Der Code müsste in etwa so aussehen:
Code: Alles auswählen
var
i: TGpioLinuxPin;
begin
i := TGpioLInuxPin.Create(5);
i.Direction := gdIn; // Richtung festlegen
i.InterruptMode := [gimRising, gimFalling]; // bei steigender und fallender Flanke einen Interrupt auslösen (Taster drücken und loslassen)
if i.WaitForInterrupt(-1) then // auf Interrupts warten
Writeln('Interrupt');
else
Writeln('Timeout');
end;

Edit: eine Dokumentation für pascalio ist ebenfalls verfügbar.
Edit2: Im Beispiel oben muss der timeout ungleich 0 sein (<0 => unendliches Warten auf Interrupt, 0 => kein Warten, >0 => warten auf Interrupt oder timeout). Weiterhin wurde die Methode selbst korrigiert (siehe Github), sodass sie jetzt zuverlässig funktioniert.
Zuletzt geändert von Socke am Do 30. Okt 2014, 20:31, insgesamt 2-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: Taste löst Interrupt am GPIO des RPI aus!
Ganz lieben Dank an Socke, für die schnelle Stellungnahme. Habe natürlich sofort probieren müssen und eine Minimal-Anwendung geschrieben, in der ich auf Kopfdruck in einem Gui-Fenster die Interruptroutine wie vorgeschlagen eingesetzt habe.
Drückt man Button2, kommt ein Fenster mit der Fehlermeldung:
Unable to open file „/sys/class/gpio/edge“.
Ich habe mit dem Filemanger nachgesehen und gesehen, dass „edge“ im Verzeichnis /sys/class/gpio/gpio5/ steht !!! Also eine Ebene drunter...kann also irgendwie nicht stimmen.
Außerdem ist mir noch nicht klar, wie ich eine Int-Service-Routine aufrufen kann und in dieser den Interrupt sperren kann, damit er kein weiteres mal in dieser Zeit ausgelöst werden kann.
Ebenso frage ich mich, ob bei jedem Eingangspin der Interrupt (0) ausgelöst wird, denn dann müßte ich danach ja in der Service-Routine abfragen, welcher Taster (wenn es mehrere sind) gedrückt wurde.
Es ist interessant, dass man im Internet wenig bis gar nix (für Lazarus) über Interrupt Behandlung zu lesen ist. Wäre aber ein interessantes Gebiet zum Basteln und probieren – gerade beim Rpi! Jedenfalls freue ich mich schon auf die nächsten Tipps - danke danke danke !
Code: Alles auswählen
procedure TForm1.Button2Click(Sender: TObject);
begin
i := TGpioLInuxPin.Create(5);
i.Direction := gdIn; // Richtung festlegen
i.InterruptMode := [gimRising, gimFalling];
if i.WaitForInterrupt(0) then // auf Interrupts warten
Label1.caption:='Interrupt'
else
Label1.caption:='Timeout';
end;
Unable to open file „/sys/class/gpio/edge“.
Ich habe mit dem Filemanger nachgesehen und gesehen, dass „edge“ im Verzeichnis /sys/class/gpio/gpio5/ steht !!! Also eine Ebene drunter...kann also irgendwie nicht stimmen.
Außerdem ist mir noch nicht klar, wie ich eine Int-Service-Routine aufrufen kann und in dieser den Interrupt sperren kann, damit er kein weiteres mal in dieser Zeit ausgelöst werden kann.
Ebenso frage ich mich, ob bei jedem Eingangspin der Interrupt (0) ausgelöst wird, denn dann müßte ich danach ja in der Service-Routine abfragen, welcher Taster (wenn es mehrere sind) gedrückt wurde.
Es ist interessant, dass man im Internet wenig bis gar nix (für Lazarus) über Interrupt Behandlung zu lesen ist. Wäre aber ein interessantes Gebiet zum Basteln und probieren – gerade beim Rpi! Jedenfalls freue ich mich schon auf die nächsten Tipps - danke danke danke !
Zuletzt geändert von Lori am So 26. Okt 2014, 13:11, insgesamt 1-mal geändert.
Grund: Highlighter
Grund: Highlighter
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Das war ein Fehler; den gibt es jetzt nicht mehr.hpt hat geschrieben:Drückt man Button2, kommt ein Fenster mit der Fehlermeldung:
Unable to open file „/sys/class/gpio/edge“.
Ich habe mit dem Filemanger nachgesehen und gesehen, dass „edge“ im Verzeichnis /sys/class/gpio/gpio5/ steht !!! Also eine Ebene drunter...kann also irgendwie nicht stimmen.
An die echten Interrupts kommst du nur im Linux-Kernel heran. Da wir hier aber an sogenannten User-Space-Programmen arbeiten, können wir nur auf einen Interrupt warten - das heißt: dein Programm kann in dieser Zeit keine anderen Aktivitäten erledigen. Für den Benutzer sieht das so aus, als ob dein Programm sich aufgehangen hat.hpt hat geschrieben:Außerdem ist mir noch nicht klar, wie ich eine Int-Service-Routine aufrufen kann und in dieser den Interrupt sperren kann, damit er kein weiteres mal in dieser Zeit ausgelöst werden kann.
Daraus folgt auch: solange dein Programm nach einen Interrupt nicht wieder erneut auf einen Interrupt wartet, merkt es nichts von einem erneutem Interrupt. Das hängt natürlich stark davon ab, wie und in welchen Zeitabständen auf Interrupts gewartet wird.
Falls du dennoch eine explizite Verhinderung benötigt, gelten die gleichen Möglichkeiten wie in Multi-Thread-Anwendungen; eine Möglichkeit wäre
Code: Alles auswählen
procedure Interrupt(pin: Integer);
const // InProc hat für alle Prozedur-Aufrufe den selben Speicherbereich
InProc: Longint = 0;
begin
// Falls InProc = 0 ist, diesen auf 1 setzen; Rückgabewert ist der alte Wert von InProc
if InterlockedCompareExchange(InProc, 1, 0) = 0 then
begin
// Interrupt handler
end;
InProc := 0; // für neuen Aufruf frei machen
end;
Wenn du für jeden Schalter einen Thread erstellst und in diesem Thread auf den Interrupt wartest, weißt du, welcher Schalter gedrückt wurde. Andernfalls: ja. Der Baustein MCP23017 bzw. MCP23S17 hat ein Register, in dem gespeichert wird, welche Eingangsleitung sich seit der letzten Abfrage geändert hat; damit kann man den Schalter auch noch viel später ermitteln (wenn der Schalter längst nicht mehr gedrückt ist) - aber das ist ein anderes Thema.hpt hat geschrieben:Ebenso frage ich mich, ob bei jedem Eingangspin der Interrupt (0) ausgelöst wird, denn dann müßte ich danach ja in der Service-Routine abfragen, welcher Taster (wenn es mehrere sind) gedrückt wurde.
Lazarus ist leider nicht ganz so populär, wie man sich das wünschen könnte; Falls du ein wenig von der Programmiersprache C verstehst, kannst du auch danach suchen.hpt hat geschrieben:Es ist interessant, dass man im Internet wenig bis gar nix (für Lazarus) über Interrupt Behandlung zu lesen ist. Wäre aber ein interessantes Gebiet zum Basteln und probieren – gerade beim Rpi! Jedenfalls freue ich mich schon auf die nächsten Tipps - danke danke danke !
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: Taste löst Interrupt am GPIO des RPI aus!
....Das war ein Fehler; den gibt es jetzt nicht mehr. !??
Wie was wo .....
Wie was wo .....
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Ich habe ihn korrigiert und die Aktualisierung zu Github hochgeladen. Wenn du die Bibliothek erneut herunterlädst, hast du auch die Korrektur.hpt hat geschrieben:....Das war ein Fehler; den gibt es jetzt nicht mehr. !??
Wie was wo .....
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: Taste löst Interrupt am GPIO des RPI aus!
Habe die Version SAmeis-pascalio-f0c5698 downgeladen, davon im Verzeichnis src/die fpgpio.
Meine Application legt wohl das Verzeichnis /sys/class/gpio/gpio5/ an, aber versucht scheinbar auf /sys/class/gpio/ zu lesen....
Jedenfalls kommt nach wie vor der Fehler: Unable to open file „/sys/class/gpio/edge“
Mache ich was falsch?! Schönen Tag wünscht HPT
Meine Application legt wohl das Verzeichnis /sys/class/gpio/gpio5/ an, aber versucht scheinbar auf /sys/class/gpio/ zu lesen....
Jedenfalls kommt nach wie vor der Fehler: Unable to open file „/sys/class/gpio/edge“
Mache ich was falsch?! Schönen Tag wünscht HPT
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Du hast alles richtig gemacht.
Den gleichen Fehler gab es ein paar Zeilen weiter noch einmal (beim Lesen statt Schreiben). In commit 1c77bd7 ist der Fehler behoben.
Den gleichen Fehler gab es ein paar Zeilen weiter noch einmal (beim Lesen statt Schreiben). In commit 1c77bd7 ist der Fehler behoben.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Taste löst Interrupt am GPIO des RPI aus!
Dafür gibt es doch Threads. Wenn das Warten auf den Interrupt durch ein Blocking Read auf ein Device-File ( „/sys/class/gpio/gpio5/edge“) gemacht wird bleibt der (Worker-) Thread an dieser Stelle stehen, aber der Main-Thread mit der GUI läuft weiter.Socke hat geschrieben:An die echten Interrupts kommst du nur im Linux-Kernel heran. Da wir hier aber an sogenannten User-Space-Programmen arbeiten, können wir nur auf einen Interrupt warten - das heißt: dein Programm kann in dieser Zeit keine anderen Aktivitäten erledigen. Für den Benutzer sieht das so aus, als ob dein Programm sich aufgehangen hat.
Oder ist das bei den "User Space Interrupts" anders ?
-Michael
Re: Taste löst Interrupt am GPIO des RPI aus!
schönen Nachmittag
jedenfalls will es bei mir nicht funktionieren.
Ich habe jetzt einiges probiert, aber wenn ich button2 drücke, kommt nur "Interrupt" aber sonst nichts mehr....
Keine Reaktion des Tasters, welcher hardwaremäßig an Pin18 (12 von der Steckleiste) über einen Pull-up an 3,3Vliegt. D.h. ich habe im Ruhezustand log1 und wenn ich den Taster drücke, log 0. Deshalb habe ich auch die Folge in der Anweisung umgedreht also "i.InterruptMode := [gimFalling, gimRising]; oder auch nur gimFalling.
Hat aber alles nichts gebracht. Was könnte ich weiter ausprobieren?
jedenfalls will es bei mir nicht funktionieren.
Ich habe jetzt einiges probiert, aber wenn ich button2 drücke, kommt nur "Interrupt" aber sonst nichts mehr....
Keine Reaktion des Tasters, welcher hardwaremäßig an Pin18 (12 von der Steckleiste) über einen Pull-up an 3,3Vliegt. D.h. ich habe im Ruhezustand log1 und wenn ich den Taster drücke, log 0. Deshalb habe ich auch die Folge in der Anweisung umgedreht also "i.InterruptMode := [gimFalling, gimRising]; oder auch nur gimFalling.
Hat aber alles nichts gebracht. Was könnte ich weiter ausprobieren?
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Hallo,
ich muss zugeben, die Interrupts sind noch nicht ausführlich getestet. Dabei muss ich zugeben, dass es mir leider noch nicht gelungen ist, voll funktionsfähig in Pascal umzusetzen.
Der folgende Code ist mehr oder weniger eine Übersetzung eines C-Programms nach Free Pascal. Das Original ist zu finden unter: http://elinux.org/GPIO#Using_poll.28.29 ... O_0_change
Das C-Programm (herunterladen in eine Datei gpio-int-test.c; kopilieren mit gcc gpio-int-test.c -o gpio-int-test; ausführen z.B. mit sudo ./gpio-int-test 25) funktioniert halbwegs.
Edit: Die Pascal-Variante funktioniert jetzt! In der Ursprünglichen Version wurde nach /sys/class/gpio/gpio<nr>/edge die Nummer des GPIO-Pins (Variable buf) geschrieben - was natürlich nicht funktionieren konnte. Jetzt wird korrekter Weise der Edge-String geschrieben.
Zum Entprellen kann dir Wikipedia weiterhelfen: https://de.wikipedia.org/wiki/Prellen
ich muss zugeben, die Interrupts sind noch nicht ausführlich getestet. Dabei muss ich zugeben, dass es mir leider noch nicht gelungen ist, voll funktionsfähig in Pascal umzusetzen.
Der folgende Code ist mehr oder weniger eine Übersetzung eines C-Programms nach Free Pascal. Das Original ist zu finden unter: http://elinux.org/GPIO#Using_poll.28.29 ... O_0_change
Das C-Programm (herunterladen in eine Datei gpio-int-test.c; kopilieren mit gcc gpio-int-test.c -o gpio-int-test; ausführen z.B. mit sudo ./gpio-int-test 25) funktioniert halbwegs.
Edit: Die Pascal-Variante funktioniert jetzt! In der Ursprünglichen Version wurde nach /sys/class/gpio/gpio<nr>/edge die Nummer des GPIO-Pins (Variable buf) geschrieben - was natürlich nicht funktionieren konnte. Jetzt wird korrekter Weise der Edge-String geschrieben.
Code: Alles auswählen
(* Copyright (c) 2011, RidgeRun
* Source: http://elinux.org/GPIO#Using_poll.28.29_to_monitor_for_GPIO_0_change
*
* Pascal Port: 2014, Simon Ameis <simon.ameis@web.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the RidgeRun.
* 4. Neither the name of the RidgeRun nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)
program gpio_int_test;
{$mode objfpc}{$H+}
uses
baseunix, unix, ctypes;
const
clib = 'c';
// libc function headers
// avoid dependency on UNIT libc; it is available only on i386
function fflush(__stream:cint):longint;cdecl;external clib name 'fflush';
procedure perror(__s:Pchar);cdecl;external clib name 'perror';
function atoi(__nptr:Pchar):longint;cdecl;external clib name 'atoi';
(*****************************************************************
* Constants
****************************************************************)
const
SYSFS_GPIO_DIR = '/sys/class/gpio';
POLL_TIMEOUT = (3 * 1000); // 3 seconds
MAX_BUF = 64;
(****************************************************************
* gpio_export
****************************************************************)
function gpio_export(gpio: cuint): cint;
var
fd: cint;
buf: Ansistring;
begin
fd := fpOpen(SYSFS_GPIO_DIR + '/export', O_WRONLY);
if (fd < 0) then
begin
perror('gpio/export');
exit(fd);
end;
str(gpio, buf);
fpWrite(fd, Pchar(buf), Length(buf));
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_unexport
****************************************************************)
function gpio_unexport(gpio: cuint): cint;
var
fd: cint;
buf: Ansistring;
begin
fd := fpOpen(SYSFS_GPIO_DIR + '/unexport', O_WRONLY);
if (fd < 0) then
begin
perror('gpio/export');
exit(fd);
end;
str(gpio, buf);
fpWrite(fd, PChar(buf), Length(buf));
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_set_dir
****************************************************************)
function gpio_set_dir(gpio: cuint; out_flag: Boolean): cint;
var
fd: cint;
buf: Ansistring;
begin
str(gpio, buf);
buf := SYSFS_GPIO_DIR + '/gpio' + buf + '/direction';
fd := fpOpen(buf, O_WRONLY);
if (fd < 0) then
begin
perror('gpio/direction');
exit(fd);
end;
if (out_flag) then
fpWrite(fd, 'out', 3)
else
fpWrite(fd, 'in', 2);
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_set_value
****************************************************************)
function gpio_set_value(gpio: cuint; value: Boolean): cint;
var
fd: cint;
buf: Ansistring;
begin
str(gpio, buf);
buf := SYSFS_GPIO_DIR + '/gpio' + buf + '/value';
fd := fpOpen(buf, O_WRONLY);
if (fd < 0) then
begin
perror('gpio/set-value');
exit(fd);
end;
if (value) then
fpWrite(fd, PChar('1'), 1)
else
fpWrite(fd, PChar('0'), 1);
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_get_value
****************************************************************)
function gpio_get_value(gpio: cuint; var value: Boolean): cint;
var
fd: cint;
buf: Ansistring;
ch: Char;
begin
str(gpio, buf);
buf := SYSFS_GPIO_DIR + '/gpio' + buf + '/value';
fd := FpOpen(buf, O_RDONLY);
if (fd < 0) then
begin
perror('gpio/get-value');
exit(fd);
end;
fpRead(fd, @ch, 1);
value := (ch <> '0');
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_set_edge
****************************************************************)
function gpio_set_edge(gpio: cuint; edge: Ansistring): cuint;
var
fd: cint;
buf: Ansistring;
begin
str(gpio, buf);
buf := SYSFS_GPIO_DIR + '/gpio' + buf + '/edge';
fd := FpOpen(buf, O_WRONLY);
if (fd < 0) then
begin
perror('gpio/set-edge');
exit(fd);
end;
fpWrite(fd, PChar(edge), length(edge));
fpClose(fd);
exit(0);
end;
(****************************************************************
* gpio_fd_open
****************************************************************)
function gpio_fd_open(gpio: cuint): cint;
var
fd: cint;
buf: Ansistring;
begin
str(gpio, buf);
buf := SYSFS_GPIO_DIR + '/gpio' + buf + '/value';
fd := FpOpen(buf, O_RDONLY or O_NONBLOCK);
if (fd < 0) then
begin
perror('gpio/fd_open');
end;
exit(fd);
end;
(****************************************************************
* gpio_fd_close
****************************************************************)
function gpio_fd_close(fd: cint): cint;
begin
Result := fpClose(fd);
end;
(****************************************************************
* Main
****************************************************************)
function main(argc: cint; argv: PPChar; envp: PPChar): cint;
var
fdset: Array[0..1] of pollfd;
nfds: cint;
gpio_fd, timeout, rc: cint;
len: TSize;
buf: String[MAX_BUF];
gpio: cint;
value: Boolean;
begin
nfds := 2;
if (argc < 2) then
begin
WriteLn('Usage: gpio_int_test <gpio-pin>', LineEnding);
WriteLn('Waits for a change in the GPIO pin voltage level or input on stdin.');
Writeln('Author: RidgeRun - Pascal Port: Simon Ameis');
exit(-1);
end;
gpio := atoi(argv[1]);
gpio_export(gpio);
gpio_set_dir(gpio, False);
gpio_set_edge(gpio, 'rising');
gpio_fd := gpio_fd_open(gpio);
timeout := POLL_TIMEOUT;
while True do
begin
FillByte(fdset, SizeOf(fdset), 0);
fdset[0].fd := StdInputHandle;
fdset[0].events := POLLIN;
fdset[1].fd := gpio_fd;
fdset[1].events := POLLPRI;
rc := fpPoll(@fdset[0], nfds, timeout);
if (rc < 0) then
begin
Writeln(ErrOutput, LineEnding, 'poll() failed.');
exit(-1);
end else
if (rc = 0) then
begin
write('.');
end;
if(fdset[1].revents and POLLPRI) <> 0 then
begin
len := FpRead(fdset[1].fd, @buf[1], MAX_BUF);
gpio_get_value(gpio, value);
writeln(LineEnding, 'poll() GPIO ', gpio, ' interrupt occured; value: ', value);
end;
if (fdset[0].revents AND POLLIN) <> 0 then
begin
FpRead(fdset[0].fd, @buf[1], 1);
writeln(LineEnding, 'poll() stdin read ', buf[1]);
end;
fflush(StdInputHandle);
end;
gpio_fd_close(gpio_fd);
exit(0);
end;
begin
ExitCode := main(argc, argv, envp);
end.
Zuletzt geändert von Socke am Mo 27. Okt 2014, 21:28, insgesamt 2-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Taste löst Interrupt am GPIO des RPI aus!
Blockiert "gpio_get_value" bis zur nächsten Änderung ?
Wenn ja: Um eine GUI am Laufen zu halten darf man es nur in einem Worker Thread aufrufen.
Wenn nein: wie kann man die nächste Änderung (die Original-Frage ging um "Interrupt") erkennen, ohne ein "Busy-Pollen" zu veranstalten ? (Auch hier braucht man vermutlich einen Worker-Thread, der den Interrupt an die GUI mit "Synchrionize", "Queue" oder "QueueAsyncCall" signalisiert.)
-Michael
Wenn ja: Um eine GUI am Laufen zu halten darf man es nur in einem Worker Thread aufrufen.
Wenn nein: wie kann man die nächste Änderung (die Original-Frage ging um "Interrupt") erkennen, ohne ein "Busy-Pollen" zu veranstalten ? (Auch hier braucht man vermutlich einen Worker-Thread, der den Interrupt an die GUI mit "Synchrionize", "Queue" oder "QueueAsyncCall" signalisiert.)
-Michael
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
Nein gpio_get_value liest nur den aktuellen Wert (der sich theoretisch zwischen Interrupt und Lesen ändern kann). Der Systemcall fpPoll blockiert bis zu einem Interrupt bzw. bis zu einem Timeout.mschnell hat geschrieben:Blockiert "gpio_get_value" bis zur nächsten Änderung ?
Mit dem Code wollte ich das generelle Vorgehen verdeutlichen: zuerst suche ich nach C-Programme und übersetze diese nach Pascal; dann wird der Code in PascalIO integriert. Da meine Pascal-Variante noch nicht zuverlässig funktioniert, bin ich über Fehlerhinweise dankbar.
Das Blocking-Problem habe ich bisher ausgelassen; als Lösung hatte ich da ein paar Komponenten im Sinn, die das ganze Threading und Synchronisation kapseln. Die zu implementieren hat für mich noch keinen Sinn, solange die Grundlagen noch nicht funktionieren.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Taste löst Interrupt am GPIO des RPI aus!
Genau !Socke hat geschrieben:Das Blocking-Problem habe ich bisher ausgelassen; als Lösung hatte ich da ein paar Komponenten im Sinn, die das ganze Threading und Synchronisation kapseln.
Ein Beispiel wie sowas gut gemacht werden kann ist AsyncPro (was es aber bis jetzt nur für Delphi/Windows gibt): Intern wird (z.B. zu Empfang asynchroner Daten) ein Thread aufgesetzt. Die Klasse stellt aber Main-Thread-Events zur Verfügung, in denen man die Bearbeitungs-Funktionen angibt, die dann ganz normal im GUI-Thread der Applikation laufen. Der Anwender merkt von den Threads nichts, bekommt aber Events als "Interrupt", so wie der OP sich das vermutlich vorstellt.
-Michael
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Taste löst Interrupt am GPIO des RPI aus!
TThread.Synchronize() arbeitet auschließlich mit einem einzigen Thread (dem Mainthread in Lazarus-Anwendungen). Da ich in eingebettenen Systemen viel eher eine N-zu-N-Kommunikation zwischen den Threads bevorzuge, hatte ich das noch nicht implementiert.mschnell hat geschrieben:Ein Beispiel wie sowas gut gemacht werden kann ist AsyncPro (was es aber bis jetzt nur für Delphi/Windows gibt): Intern wird (z.B. zu Empfang asynchroner Daten) ein Thread aufgesetzt. Die Klasse stellt aber Main-Thread-Events zur Verfügung, in denen man die Bearbeitungs-Funktionen angibt, die dann ganz normal im GUI-Thread der Applikation laufen. Der Anwender merkt von den Threads nichts, bekommt aber Events als "Interrupt", so wie der OP sich das vermutlich vorstellt.
Vielleicht kannst du mal einen Blick auf den Quelltext oben werfen und nach Fehlern suchen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein