Zu den Abständen: du wartest doch diverse mal zB 0.4 Sekunden. Das ist relativ kurz. Wenn das präzise muss, sollte es ggf anders gemacht werden. Das 0.01 im receive ist eher ein freundlicher Hinweis an den Kernel, mal kurz wen anderes dran zu lassen, aber bitte gleich wieder weiter zu machen. Das wird nie eingehalten, wenn wie gesagt der scheduler schon mit der Auflösung arbeitet - da kommt garantiert immer eine, wenn nicht mehrere zeitscheiben dazwischen, und du wartest implizit immer mehrere 100stel. Schlimm ist das eher nicht, außer du machst Zuviel im anderen Thread. Was wiederum mit dem busywait doof ist... hm.
Schau erstmal das alles prinzipiell klappt, timer-tuning ist Sternchenaufgabe
Python2 /Python 3; Adafruit 16-Kanal PCA9685 und rpi-rf
Sie schreibweise ruft die Funktion nicht so auf, dass sie funktioniert__deets__ hat geschrieben:Du benutzt halt eine veraltete Thread api und machst dir das Leben damit schwerer. Aber das hast du ja so gewollt. Die will halt IMMER zwei Argumente. Du gibst ihr nur eines. Es muss ein zweites dahinter, MIT KOMMA GETRENNT, ein leeres Tupel - () - oder nicht-leer wie bei Start, aber da ist das ja dann in Training selbst ignoriert. Also
start_new_thread(receive, ())
Und das def keine Funktionen wären habe ich nicht behauptet.ich rede davon, was DARIN passiert. Da weist du irgendwelchen Variablen werdet zu. Du GLAUBST das würde dauerhaft sein, isses aber nicht. Teste das mal mit einem simplen Skript.
Und dein Skript ist auch ein Modul. Es hat den speziellen Namen __main__, aber die Semantik ist gleich. Insofern gelten meine Ausführungen eben auch da. Global-Deklarationen auf Modulebene sind sinnlos, weil da alles (Modul-)global IST. Unterschieden wird das nur IN Funktionen, denn da gibt es lokale Variablen, und die will man von globalen unterscheiden.
Code: Alles auswählen
def receive(a):
und
start_new_thread(receive, (99,))
Code: Alles auswählen
def receive(a):
und
start_new_thread(receive, ())
Code: Alles auswählen
def receive():
und
start_new_thread(receive, ())
der komplette CodeSirius3 hat geschrieben:Im letzten Fall machst Du irgendetwas anderes falsch, was Du aber nicht zeigst.
Code: Alles auswählen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tkinter as tk
import Adafruit_PCA9685
import time
import RPi.GPIO as GPIO
import os
import pygame
import _thread
import alsaaudio
import argparse
import signal
import sys
import logging
from rpi_rf import RFDevice
from tkinter import *
#GPIO für LED festlegen
GPIO.setwarnings(False) # Warnungen ausschalten
GPIO.setmode(GPIO.BCM) # Pin Nummern verwenden
GPIO.setup(6, GPIO.OUT) # Pin 31 als Output gruen
GPIO.setup(16, GPIO.OUT) # Pin 36 als Output rot
GPIO.setup(26, GPIO.OUT) # Pin 37 als Output gelb
# Variabelen festlegen
global Kom50, Wiederholungen, SchussZeit, AbzugZeit, Modus, Schieber
# Variabelen Werte zuweisen
SchussZeit = 3 # Dauer der Sichtbarkeit der Scheibe
AbzugZeit = 0 # Zeit um die die Sichtbarkeit der Scheibe reduziert wird
Kom50= 10 # Kommando 50 Reduziert die Zeit für das Laden der Waffe auf 10 Sekunden
Modus = 2 # 1 = Lichtmodus, 2 = Klappenmodus
Wiederholungen = 5 # Duell 5 Wiederholungen ( 1 Schuß pro aufklappen) alle anderen 1
# I2C Board für Servo
pwm = Adafruit_PCA9685.PCA9685(address=0x40) # I2C Board-Adresse
pwm.set_pwm_freq(50) # Festlegung der Frequenz
# Gui Grundlagen definieren
root = Tk() # Fenster erstellen
root.wm_title("Pistol Shoot Trainer") # Fenster Titel
#root.wm_attributes ('-fullscreen', 'true') # Vollbildmodus
root.wm_geometry('480x320+0+0')
root.config(background = "#FFFFFF") # Hintergrundfarbe des Fensters
def exithandler(signal, frame): # Teil des 433 Mhz Prozess Skriptes
#rfdevice.cleanup()
sys.exit(0)
def receive():
print ("receive start")
logging.basicConfig(level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S',
format='%(asctime)-15s - [%(levelname)s] %(module)s: %(message)s', )
parser = argparse.ArgumentParser(description='Receives a decimal code via a 433/315MHz GPIO device')
parser.add_argument('-g', dest='gpio', type=int, default=27,
help="GPIO pin (Default: 27)")
args = parser.parse_args()
signal.signal(signal.SIGINT, exithandler)
rfdevice = RFDevice(args.gpio)
rfdevice.enable_rx()
timestamp = None
while True:
if rfdevice.rx_code_timestamp != timestamp:
timestamp = rfdevice.rx_code_timestamp
rec_num = (str(rfdevice.rx_code))
print (rec_num)
if rec_num == "16404":
start()
return()
else:
print ("test")
time.sleep(0.01)
#rfdevice.cleanup()
#Variabelen setzen für die Schusszeit und die Anzahl der Wiederholungen pro Magazin
def AchtSekunden():
SchussZeit = 8
Wiederholungen = 1
def SechsSekunden():
SchussZeit = 6
Wiederholungen = 1
def VierSekunden():
SchussZeit = 4
Wiederholungen = 1
def ZehnSekunden():
SchussZeit = 10
Wiederholungen = 1
def Duell():
SchussZeit = 3
Wiederholungen = 5
#Variabelen setzen für die Reduzierung der Schusszeit
def AbzugOhne():
AbzugZeit = 0
def Abzug01():
AbzugZeit = 0.1
def Abzug02():
AbzugZeit = 0.2
def Abzug03():
AbzugZeit = 0.3
#Variabelen setzen für Kommando 50. Reduzierung der Ladezeit auf 10 Sek.
def Kommando50Aus():
global Kom50
Kom50= 60
return()
def Kommando50An():
global Kom50
Kom50 = 10
return()
#Variabelen setzen für Modus ( Licht oder Klapp )
def Modus1():
global Modus
Modus= 1
def Modus2():
global Modus
Modus= 2
def start():
print (" start training prozess")
_thread.start_new_thread(Training,())
def rf_modul():
print (" start rf modul")
_thread.start_new_thread(receive, ())
receive()
def change_vol(l):
m = alsaaudio.Mixer('PCM')
int_l = int(l)
m.setvolume(int_l)
current_volume = m.getvolume()
def Training(a):
if Modus == 1:
os.system("sudo xscreensaver-command -activate")
GPIO.output(26, True)
GPIO.output(6, False)
GPIO.output(16, False)
pygame.init()
if Kom50 == 60:
pygame.mixer.music.load("/home/pi/Documents/shoot/WaffeLaden.wav")#Ansage "Laden"
elif Kom50 == 10:
pygame.mixer.music.load("/home/pi/Documents/shoot/50.wav")#Ansage "Laden"
pygame.mixer.music.play()
time.sleep(Kom50)
pygame.mixer.music.load("/home/pi/Documents/shoot/Achtung.wav")#Ansage "Achtung"
pygame.mixer.music.play()
time.sleep(1)
for g in range(Wiederholungen):
GPIO.output(26, False)
GPIO.output(16, False)
GPIO.output(6, True)
time.sleep(7)
GPIO.output(16, True)
GPIO.output(6, False)
time.sleep(SchussZeit)
GPIO.output(16, False)
GPIO.output(6, True)
for g in range(4):
GPIO.output(6, False)
time.sleep(0.4)
GPIO.output(6, True)
time.sleep(0.4)
GPIO.output(6, True)
GPIO.output(26, True)
GPIO.output(16, True)
os.system("sudo xscreensaver-command -deactivate")
elif Modus == 2:
os.system("sudo xscreensaver-command -activate")
GPIO.output(16, False)
GPIO.output(6, False)
GPIO.output(26, True)
pygame.init()
if Kom50 == 60:
pygame.mixer.music.load("/home/pi/Documents/shoot/WaffeLaden.wav")#Ansage "Laden"
elif Kom50 == 10:
pygame.mixer.music.load("/home/pi/Documents/shoot/50.wav")#Ansage "Laden"
pygame.mixer.music.play()
pwm.set_pwm(0, 0, 130)
pwm.set_pwm(1, 0, 130)
pwm.set_pwm(2, 0, 130)
pwm.set_pwm(3, 0, 130)
pwm.set_pwm(4, 0, 130)
time.sleep(Kom50)
GPIO.output(26, False)
pygame.mixer.music.load("/home/pi/Documents/shoot/Achtung.wav")#Ansage "Achtung"
pygame.mixer.music.play()
time.sleep(1)
for g in range(Wiederholungen):
pwm.set_pwm(0, 0, 300)
pwm.set_pwm(1, 0, 300)
pwm.set_pwm(2, 0, 300)
pwm.set_pwm(3, 0, 300)
pwm.set_pwm(4, 0, 300)
time.sleep(7)
pwm.set_pwm(0, 0, 130)
pwm.set_pwm(1, 0, 130)
pwm.set_pwm(2, 0, 130)
pwm.set_pwm(3, 0, 130)
pwm.set_pwm(4, 0, 130)
time.sleep(SchussZeit)
pwm.set_pwm(0, 0, 300)
time.sleep(1)
pwm.set_pwm(0, 0, 130)
GPIO.output(26, True)
GPIO.output(16, True)
GPIO.output(6, True)
os.system("sudo xscreensaver-command -deactivate")
return
def herunterfahren():
GPIO.cleanup()
os.system("sudo shutdown -h now")
def GUI():
rightLabel1 = Label(buttonFrame, text="Pistol Shoot Trainer", font = "Verdana 27 bold", background="#58FA58")
rightLabel1.grid(row=0, column=0, padx=1, pady=1, columnspan=6)
rightLabel4 = Label(buttonFrame, text="Schießzeit", font = "Verdana 10 bold", background="#58FA58")
rightLabel4.grid(row=1, column=0, padx=0, pady=3)
RB11 = Radiobutton(buttonFrame, indicatoron=0, text="Duell", height=1, width=5, font = "Verdana 12 bold", variable=SchussZeit, value=3, command=Duell)
RB11.grid(row=1, column=1, padx=5, pady=8)
RB11.select()
RB12 = Radiobutton(buttonFrame, indicatoron=0, text="8 Sek", height=1, width=5, font = "Verdana 12 bold" , variable=SchussZeit, value=8, command=AchtSekunden)
RB12.grid(row=1, column=3, padx=5, pady=8)
RB13 = Radiobutton(buttonFrame, indicatoron=0, text="6 Sek", height=1, width=5,font = "Verdana 12 bold", variable=SchussZeit, value=6, command=SechsSekunden)
RB13.grid(row=1, column=4, padx=5, pady=8)
RB14 = Radiobutton(buttonFrame, indicatoron=0, text="4 Sek", height=1, width=5,font = "Verdana 12 bold" , variable=SchussZeit, value=4, command=VierSekunden)
RB14.grid(row=1, column=5, padx=5, pady=8)
RB15 = Radiobutton(buttonFrame, indicatoron=0, text="10 Sek", height=1, width=6,font = "Verdana 12 bold" , variable=SchussZeit, value=10, command=ZehnSekunden)
RB15.grid(row=1, column=2, padx=5, pady=8)
rightLabel5 = Label(buttonFrame, text="Zeitabzug", font = "Verdana 10 bold", background="#58FA58")
rightLabel5.grid(row=2, column=0, padx=0, pady=3)
RB21 = Radiobutton(buttonFrame, indicatoron=0, text="Ohne", height=1, width=5, font = "Verdana 12 bold" , variable=AbzugZeit, value=1, command=AbzugOhne)
RB21.grid(row=2, column=1, pady=8, padx=5)
RB21.select()
RB22 = Radiobutton(buttonFrame, indicatoron=0, text="0,1", height=1, width=5, font = "Verdana 12 bold" , variable=AbzugZeit, value=2, command=Abzug01)
RB22.grid(row=2, column=2, pady=8, padx=5)
RB23 = Radiobutton(buttonFrame, indicatoron=0, text="0,2", height=1, width=5, font = "Verdana 12 bold", variable=AbzugZeit, value=3, command=Abzug02)
RB23.grid(row=2, column=3, pady=8, padx=5)
RB24 = Radiobutton(buttonFrame, indicatoron=0, text="0.3", height=1, width=5, font = "Verdana 12 bold" , variable=AbzugZeit, value=4, command=Abzug03)
RB24.grid(row=2, column=4, pady=8, padx=5)
rightLabel6 = Label(buttonFrame, text="Kommando \n50", font = "Verdana 10 bold", background="#58FA58")
rightLabel6.grid(row=3, column=0, padx=0, pady=3)
RB31 = Radiobutton(buttonFrame, indicatoron=0, text="Ohne", height=1, width=7, font = "Verdana 15 bold" , variable=Kom50, value=1, command=Kommando50Aus)
RB31.grid(row=3, column=1, pady=8,columnspan=2)
RB32 = Radiobutton(buttonFrame, indicatoron=0, text="Mit", height=1, width=7, font = "Verdana 15 bold" , variable=Kom50, value=2, command=Kommando50An)
RB32.grid(row=3, column=3, pady=8,columnspan=2)
RB32.select()
rightLabel6 = Label(buttonFrame, text="Modus", font = "Verdana 10 bold", background="#58FA58")
rightLabel6.grid(row=4, column=0, padx=0, pady=3)
RB41 = Radiobutton(buttonFrame, indicatoron=0, text="Licht", height=1, width=7, font = "Verdana 15 bold" , variable=Modus, value=1, command=Modus1)
RB41.grid(row=4, column=1, pady=8,columnspan=2)
RB42 = Radiobutton(buttonFrame, indicatoron=0, text="Dreh", height=1, width=7, font = "Verdana 15 bold" , variable=Modus, value=2, command=Modus2)
RB42.grid(row=4, column=3, pady=8,columnspan=2)
RB42.select()
BT42 = Button(buttonFrame, text="Beenden", height=1, width=10, font = "Verdana 10 bold", command=herunterfahren)
BT42.grid(row=5, column=4, padx=5, pady=5,columnspan=2)
rightLabel7 = Label(buttonFrame, text="Lautstärke", font = "Verdana 10 bold", background="#58FA58")
rightLabel7.grid(row=5, column=0, padx=0, pady=3)
Schieber = Scale(buttonFrame, from_ = 0, to = 100, length = 200, orient =HORIZONTAL,tickinterval = 20,resolution = 5, command=change_vol) # tickinterval = 1,
Schieber.grid(row=5, column=1, padx=5, pady=5,columnspan=3)
Schieber.set(10)
#root.after (0, receive)
root.mainloop() # GUI wird upgedated. Danach keine Elemente setzen
buttonFrame = Frame(root, background="#58FA58")
buttonFrame.grid(row=0, column=0, padx=5, pady=5)
GPIO.output(26, True)
GPIO.output(6, True)
GPIO.output(16, True)
GUI()
rf_modul()
die 0,4 SSekunden sollen nur ein Blinken der LED erzeugen, die anzeigen, dass der Zyklus durch ist. Ob das 0,4 ,02 oder 0,8 sind ist dabei voellig legal__deets__ hat geschrieben:Zu den Abständen: du wartest doch diverse mal zB 0.4 Sekunden. Das ist relativ kurz. Wenn das präzise muss, sollte es ggf anders gemacht werden. Das 0.01 im receive ist eher ein freundlicher Hinweis an den Kernel, mal kurz wen anderes dran zu lassen, aber bitte gleich wieder weiter zu machen. Das wird nie eingehalten, wenn wie gesagt der scheduler schon mit der Auflösung arbeitet - da kommt garantiert immer eine, wenn nicht mehrere zeitscheiben dazwischen, und du wartest implizit immer mehrere 100stel. Schlimm ist das eher nicht, außer du machst Zuviel im anderen Thread. Was wiederum mit dem busywait doof ist... hm.
Schau erstmal das alles prinzipiell klappt, timer-tuning ist Sternchenaufgabe
@mollyman: dann schau Dir nochmal genau an, was Du da machst:
Code: Alles auswählen
def rf_modul():
print (" start rf modul")
_thread.start_new_thread(receive, ())
receive()
Habe den 2. receive Aufruf entfernt. es hat aber nix verändert.
Mir ist aber aufgefallen, dass wenn cih das Fenster schließe dann der receive startet.
die Reihenfolge ist wohl schuld daran.
ein Tausche der Reihenfolge bringt einen neuen Fehler, der aber darauf hindeutet, dass dass das receive arbeitet:
Daraus entnehme ich dass ich das receive Script nicht in einen Thread auslagern kann.
Die GUI kann ich aber auch nicht auslagern.
Jetzt bin ich ziemlich ratlos
Mir ist aber aufgefallen, dass wenn cih das Fenster schließe dann der receive startet.
Code: Alles auswählen
GUI()
rf_modul()
ein Tausche der Reihenfolge bringt einen neuen Fehler, der aber darauf hindeutet, dass dass das receive arbeitet:
Code: Alles auswählen
signal.signal(signal.SIGINT, exithandler)
ValueError: Signal only works in main thread.
Die GUI kann ich aber auch nicht auslagern.
Jetzt bin ich ziemlich ratlos
Mist.
Ich habe keine Ahnung vom parsen .
Leider verstehe ich anhand der jeweiligen Doku weder wie das receive script funktioniert noch was Signal eigentlich wirklich darin macht.
Tja, dann muss ich mir was einfallen lassen.
Dann geht es nicht mit der 433 MHz Lösung.
Danke für eure Hilfe.
Ich habe keine Ahnung vom parsen .
Leider verstehe ich anhand der jeweiligen Doku weder wie das receive script funktioniert noch was Signal eigentlich wirklich darin macht.
Tja, dann muss ich mir was einfallen lassen.
Dann geht es nicht mit der 433 MHz Lösung.
Danke für eure Hilfe.
Das ist Unfug. Natuerlich geht das. Nur eben nicht mit dem aufeinanderkloppen von Skripten, die du nicht verstehst, und die Dinge machen wie zB Kommandozeilen Argumente parsen oder Fehlerbehandlung durchzufuehren auf (in DEINEM FALL) ungeeignete Art und Weise.
Du brauchst weder eine flexible Angabe des verwandten GPIOs (womit der Argument-Parser rausfaellt), noch willst du dein Skript per Ctrl-C abbrechen und danach schoen aufraeumen. Womit die Signal-Behandlung entfaellt.
Alles was du brauchst ist das RFDevice. Vergiss *ALLES* andere. Es ist ein beliebter Anfaengerfehler, alles auf einmal in einem riesen Klumpatsch zum laufen zu bringen.
Starte nur zum ausprobieren mit einem NEUEN Skript, in dem ausser den Zeilen
nix steht. Und arbeite dich dahin, das du das zum funktionieren bekommst. Naechster Schritt: receive im Hintegrund-Thread starten. OHNE das "verbotene" Modul _thread, sondern mit dem dafuer gedachten Modul threading.
Dann hast du eine Grundlage, das in deine bestehende GUI einzubauen.
Du brauchst weder eine flexible Angabe des verwandten GPIOs (womit der Argument-Parser rausfaellt), noch willst du dein Skript per Ctrl-C abbrechen und danach schoen aufraeumen. Womit die Signal-Behandlung entfaellt.
Alles was du brauchst ist das RFDevice. Vergiss *ALLES* andere. Es ist ein beliebter Anfaengerfehler, alles auf einmal in einem riesen Klumpatsch zum laufen zu bringen.
Starte nur zum ausprobieren mit einem NEUEN Skript, in dem ausser den Zeilen
Code: Alles auswählen
from rpi_rf import RFDevice
def receive():
pass
if __name__ == "__main__":
receive()
Dann hast du eine Grundlage, das in deine bestehende GUI einzubauen.
Code: Alles auswählen
def receive():
rfdevice = RFDevice(27)
rfdevice.enable_rx()
timestamp = None
while True:
if rfdevice.rx_code_timestamp != timestamp:
timestamp = rfdevice.rx_code_timestamp
rec_num = (str(rfdevice.rx_code))
if rec_num == "16404":
time.sleep(2)
start()
time.sleep(0.01)
das auch:
Code: Alles auswählen
def rf_modul():
tr = Thread(target = receive)
tr.start()
Na sieht doch gut aus Ich wuerde das time.sleep(2) noch entfernen, und stattdessen in start verschieben, weil das mE eine Entscheidung ist, die da getroffen werden sollte, und mit dem eigentlichen Empfang nichts zu tun hat. Ist aber Kuer.
Dann bau das doch mal in dein Tool ein und schau, ob's besser wird.
Dann bau das doch mal in dein Tool ein und schau, ob's besser wird.
das receive funktioniert im Tool,auch das threading.
Das time Sleep ist noch ein überbleibsel des testens und ist jetzt auch noch rausgeflogen.
Wenn jetzt noch die letzten Einstellungen gespechert werden, wäre das toll.
Ich habe mal mit dem configparser gespielt, aber der scheint nicht so richtig zu funktionieren bei mir.
Seit dem ich die vielen Globals rausgenommen habe scheint die Logik auch nicht mehr zu funktionieren.
Das time Sleep ist noch ein überbleibsel des testens und ist jetzt auch noch rausgeflogen.
Wenn jetzt noch die letzten Einstellungen gespechert werden, wäre das toll.
Ich habe mal mit dem configparser gespielt, aber der scheint nicht so richtig zu funktionieren bei mir.
Seit dem ich die vielen Globals rausgenommen habe scheint die Logik auch nicht mehr zu funktionieren.
ich glaube so richtig habe ich das noch nicht verstanden mit dem Globalen Variabelen.
Das ist das, wass ich bisher verstanden habe:
Das ist das, wass ich bisher verstanden habe:
- Variabelen auf Modulebene OHNE "global" mit Werten versehen gelten nur auf Modulebene
Variabelen auf Modulebene MIT "global" mit Werten versehen gelten auf Modulebeneund in den Funktionen
Variabelen in einer Funktion OHNE "global" mit Werten versehen gelten nur in der Funktion
Variabelen in einer Funktion müssen MIt "global" in der Funktion deklariert werden, bevor sie einen Wert bekommen, damit die sie als die Variabe auf Modulebene erkannt werden.