Seite 1 von 1
Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 12:39
von mollyman
Hallo zusammen
ich bin dabei ein Programm zu schreiben, das auf dem Raspberry eine Gui(TKINTER) anzeigt.
In der Gui wird festgelegt wie und wann Servos, Sound und LEDS aktiviert/gestellt/ausgegeben werden.
Das ganze funktioniert sehr gut
Gestartet werden soll der Zyklus über eine Infrarot Fernbedienung.
Dazu habe ich mir passenden Code für Lirc herausgesucht:
Code: Alles auswählen
sockid=lirc.init("black", blocking = False)
while True:
codeIR = lirc.nextcode()
if codeIR != KEY_OK:
Training()
Jetzt geht es darum, dass dieser Code unabhängig von der GUI starten soll, wenn ein Signal über den Lirc Socket kommt.
Aber genau da ist mein Problem. ich weiß nicht wie und die google Suchen dazu haben mir nicht wirklich geholfen.
AUs meiner Sicht müsste es mit einem Interrupt laufen, aber wie ?
Danke im voraus
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 13:25
von noisefloor
Hallo,
also rein prinzipiell du musst halt auf dem Socket lauschen und wenn das richtige Signal reinkommen den Code ausführen. Machst du ja schon im gezeigten Code. Wo ist denn genau den Problem... Kann ich gerade nicht nachvollziehen...
Gruß, noisefloor
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 13:35
von mollyman
HI
das Problem ist, dass er nicht auf die Signale reagiert während die GUI läuft
Code: Alles auswählen
sockid=lirc.init("black", blocking = False)
def GUI()
.
.
.
. Frames, Labels und Buttons usw.
while True:
codeIR = lirc.nextcode()
if codeIR != KEY_OK:
Training()
root.mainloop()
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 13:39
von noisefloor
Hallo,
du musst ja auch den Code unabhängig von der GUI starten - sagst du ja selber. Da darfst auch in eine GUI nie sowas wie `while True` einbauen. Die Kontrolle muss beim `mainloop()` bleiben, sonst reagiert die GUI nicht.
Also entweder startest du den LIRC-Teil in einem eigenen Skript oder einem eigenen Thread und lässt dann die GUI und den LIRC-Teil über eine Socket, eine NamedPipe, eine Queue, ... miteinander kommunizierten.
Ich denke, ich würde hier einen Thread nehmen und die Queue zur Kommunikation.
Gruß, noisefloor
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 14:04
von __deets__
Der socket aus der Rückgabe ist ein filedeskriptor. Der benachrichtigt dich, wenn es neue Daten gibt. Dazu einfach den FD mit createfilehandler registrieren für lese-Ereignisse, und im callback dann next aufrufen.
https://docs.python.org/2/library/tkint ... e-handlers
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 14:06
von mollyman
HI noisefloor
und genau da scheitere ich.
Wie kann ich das machen, dass die Lirc Schleife separat läuft.
Wenn ich die Aufrufe vor der GUI komme ich nicht in die GUI.
Es muss parallel sein aber wie geht das bei Python
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 14:07
von mollyman
__deets__ hat geschrieben:Der socket aus der Rückgabe ist ein filedeskriptor. Der benachrichtigt dich, wenn es neue Daten gibt. Dazu einfach den FD mit createfilehandler registrieren für lese-Ereignisse, und im callback dann next aufrufen.
https://docs.python.org/2/library/tkint ... e-handlers
Danke, das hört sich gut an. ich schaue mir das gleich an
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 16:47
von mollyman
mollyman hat geschrieben:__deets__ hat geschrieben:Der socket aus der Rückgabe ist ein filedeskriptor. Der benachrichtigt dich, wenn es neue Daten gibt. Dazu einfach den FD mit createfilehandler registrieren für lese-Ereignisse, und im callback dann next aufrufen.
https://docs.python.org/2/library/tkint ... e-handlers
Danke, das hört sich gut an. ich schaue mir das gleich an
Ich habe die Anleitung nicht wirklich verstanden.
Es gibt keine Fehlermeldung aber auch keine GUI mehr:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Tkinter import *
import Tkinter as tk
import time
import pygame
import lirc
.....
# Gui Grundlagen definieren
root = Tk() # Fenster erstellen
root.wm_title("Pistol Shoot Trainer") # Fenster Titel
root.wm_geometry('480x320+0+0')
root.config(background = "#FFFFFF") # Hintergrundfarbe des Fensters
# Socket fuer die Fernbedienung
sockid=lirc.init("black", blocking = False)
....
def Training():
if Modus == 1:
....
GPIO.output(06, True)
return
def callback(sockid, mask):
if codeIR == [KEY_OK]:
Training
return
def GUI():
rightLabel1 = Label(buttonFrame, text="Pistol Shoot Trainer", font = "Verdana 27 bold", background="#58FA58")
rightLabel1.grid(row=0, column=0, padx=1, pady=3, columnspan=5)
....
BT42 = Button(buttonFrame, text="Ende", height=1, width=4, font = "Verdana 12 bold", command=herunterfahren)
BT42.grid(row=5, column=2, padx=5, pady=5,)
# File Handler (Descriptor) fuer Socket
RemoteDaten = tk.Tk()
mask= tk.READABLE
RemoteDaten.tk.createfilehandler(sockid , mask, Training())
root.mainloop() # GUI wird upgedated. Danach keine Elemente setzen
buttonFrame = Frame(root, background="#58FA58")
buttonFrame.grid(row=0, column=0, padx=10, pady=10)
...
GUI()
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 17:22
von __deets__
Du sollst ja auch einen callback übergeben. Und ihn nicht gleich aufrufen, so wie du es tust. Und Training muss dann natürlich auch die Argumente nehmen dir jeder filedeskriptor callback nimmt.
Re: Interrupt ? Event ? für Lirc
Verfasst: Samstag 24. Februar 2018, 18:01
von mollyman
__deets__ hat geschrieben:Du sollst ja auch einen callback übergeben. Und ihn nicht gleich aufrufen, so wie du es tust. Und Training muss dann natürlich auch die Argumente nehmen dir jeder filedeskriptor callback nimmt.
Da scheint das Problem zu sein, ich habe offensichtlich nicht verstanden, was ein callback ist. auch das was ich dazu googlen konnte hat mir dabei nicht geholfen.
kannst du das bitte mir erklären
Re: Interrupt ? Event ? für Lirc
Verfasst: Sonntag 25. Februar 2018, 11:17
von __deets__
Ein callback ist ein “callable”, also etwas das aufrufbar ist. Wenn du in deiner GUI einen Button haben willst, und der Button soll etwas tun wenn man ihn drückt. Zb einen Hupton abspielen. Dann erzeugst du einen Button in etwa so
button = Button(frame, command=hupen) # Achtung: keine Klammern hinter hupen!
und dann ist hupen dein callback. Wenn der Benutzer auf den Button drückt, dann ruft der Button das command auf. Und weil du eben hupen reingereicht hast, ruft er halt hupen auf.
Das Prinzip ist generalisierbar. Callbacks benutzt man, wenn man Dinge tun will als Reaktion auf ein Ereignis. ZB auch wenn ein LIRC Ereignis reinkommt.
Was du getan hast ist einfach gleich bei Programmstart laut los zu hupen. Und nie wieder aufzuhören. Weil du dienen Callback Training gleich aufrufst mit den () dahinter.
Re: Interrupt ? Event ? für Lirc
Verfasst: Sonntag 25. Februar 2018, 16:46
von mollyman
HI
ok ich glaube es wird jetzt etwas klarer.
Wenn ich das richtig verstanden habe, reagiert dieser Code,
Code: Alles auswählen
RemoteDaten.tk.createfilehandler(sockid , mask, Training)
nur wenn über sockid ein Object kommt und ruft dann die Funktion Training auf .
Das wäre aber falsch, weil ich ja erst prüfen möchte was im Objekt ist.
dann müsste es dann so sein? :
Code: Alles auswählen
def Training():
if Modus == 1:
....
GPIO.output(06, True)
return
def callback(sockid, mask):
if codeIR == [KEY_OK]:
Training()
return
....
def GUI():
RemoteDaten.tk.createfilehandler(sockid , mask, callback)
habe ich das so richtig verstanden ?
Re: Interrupt ? Event ? für Lirc
Verfasst: Sonntag 25. Februar 2018, 17:23
von __deets__
Ob das richtig ist weiß ich nicht, weil ich nicht wirklich verstehe was du da machst. Aber der callback sieht besser aus, ja, weil er richtig angegeben ist & auch die zwei notwendigen Parameter bekommt.
Was in dem callback steht sieht aber falsch aus, weil da irgendwelche Namen stehen, die nirgendwo herkommen, und weil der eigentliche aufruf an lirc den du am Anfang noch gezeigt hast auch fehlt.
Re: Interrupt ? Event ? für Lirc
Verfasst: Montag 26. Februar 2018, 08:33
von mollyman
HI
zum Programm selbst.
Das ist eine Trainingsanlage, die Lampen (LED) und einen Servo steuert.
Auf der GUI (3,5 Zoll display) habe ich eine Reihe Buttons, mit denen Variablen definiert werden . Damit werden die Zyklen konfiguriert in denen die Servos und LED leuchten.
Das ist z.B. so ein Zyklus Gelbe LED und Servo 90 Grad für 10 Sek dann rote LED und Servo 180 Grad für 7 Sekunden und grüne LED 90 Grad für 3 sekunden und dann weiter mit rote Led und Servo 180 ... 5 Widerholungen.
Der Anwender steht aber 2 m entfernt. daher soll der Zyklus über ein Fernbedienung gestartet werden. Dazu die Einbindung von LIRC.
Der Raspi wird gestartet die GUI wird aufgerufen, der Zyklus definiert und dann geht der Anwende rin Position und startet den Ablauf mit der Fernbedienung.
Sorry ich hatte etwas vergessen:
so ist es "komplett":
Code: Alles auswählen
import lirc
...
sockid=lirc.init("black", blocking = False)
..
def Training():
if Modus == 1:
....
GPIO.output(06, True)
return
def callback(sockid, mask):
codeeIR = lirc.nextcode()
if codeIR == [KEY_OK]:
Training()
return
....
def GUI():
# File Handler (Descriptor) fuer Socket
RemoteDaten = tk.Tk()
mask= tk.READABLE
RemoteDaten.tk.createfilehandler(sockid , mask, callback)