bambambam
Posts: 3
Joined: Wed Feb 14, 2018 8:03 am

Uhrzeit - While-Schleifen-Steuerung

Wed Feb 14, 2018 8:32 am

Hallo zusammen,

Aktuell habe ich folgendes Problem und würde mich freuen, wenn mir jemand unter die Arme greifen würde:

Ich arbeite derzeit an einer Tablettenbox, die abhängig von der Uhrzeit und von erfolgter / nicht erfolgter Öffnung (Kontaktschalter im Deckel der Box) Dinge tun soll, beispielsweise ein Buzzer in bestimmten Abständen auslösen oder LED's leuchten lassen.

Ich habe das Projekt mit Micropython auf einem ESP8266 begonnen, bin nun aber auf Python und den Raspberry umgestiegen, da mir Mikrokontroller noch etwas zu weit weg sind.

Hier mal ein "Ablauf":

Code: Select all

Schalter = 0
Während Uhrzeit zwischen 6 und 9 prüfe dauerhaft:
	wenn schalter = 1:
		aktiviere grüne LED
	wenn schalter = 0
		aktiviere rote LED
		lasse Buzzer alle 15 Minuten piepen
Wenn Uhrzeit 18:59:
	Schalter = 0
Während Uhrzeit zwischen 19 und 21 prüfe dauerhaft:
	wenn schalter = 1:
		aktiviere grüne LED
	wenn schalter = 0
		aktiviere rote LED
		lasse Buzzer alle 15 Minuten piepen
Wenn Uhrzeit 8:59:
	Schalter = 0
Ich habe Zweifel, ob ich wirklich eine ellenlange Verschachtelung von while-Schleifen benutzen kann.
Außerdem: Der Buzzer soll alle 15 Minuten piepen, wenn der Schalter nicht betätigt wurde. Allerdings muss das Programm in der Lage sein, während der 15 Minuten dauerhaft zu prüfen, ob der Schalter zwischenzeitlich betätigt wurde. Und genau DA komme ich nicht weiter.

Hier mal mein ursprünglicher und sehr bugbehafteter Micropython-Code für dijeningen, die es interessiert:

Code: Select all

#SMARTPILLBOX
import machine, neopixel, time, btree, utime, ntptime
try:
        f = open("mydb", "r+b")
except OSError:
        f = open("mydb", "w+b")
def ledonoff(rgb1, rgb2, rgb3):
        np = neopixel.NeoPixel(machine.Pin(4), 4)
        np[0] = (rgb1, rgb2, rgb3)
        np[1] = (rgb1, rgb2, rgb3)
        np[2] = (rgb1, rgb2, rgb3)
        np[3] = (rgb1, rgb2, rgb3)
        np.write()
def buzzertrigger(sec):
        buzzer = machine.Pin(5, machine.Pin.OUT)
        buzzer.on()
        time.sleep(sec)
        buzzer.off()
db = btree.open(f)
np = neopixel.NeoPixel(machine.Pin(4), 4)
buzzer = machine.Pin(5, machine.Pin.OUT)
tast = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
ti = utime.localtime()
db[b"0"] = b"deactivated"
while true:
        first = tast.value()
        time.sleep(0.01)
        second = tast.value()
               if '6' <= ti[3] <= '9':
                       if first and not second:
                               db[b"0"] = b"activated"
                       elif db[0] is not b"activated":
                               print('Pill not taken')
                               buzzertrigger(0.5)
                               ledonoff(255, 0, 0)
                       else:
                               print('Pill already taken')
                               ledonoff(0, 255, 0)
               elif '19' <= ti[3] <= '21':
                       if first and not second:
                               db[b"0"] = b"activated"
                       elif db[0] is not b"activated":
                               print('Pill not taken')
                               buzzertrigger(0.5)
                               ledonoff(255, 0, 0) 
                       else:
                               print('Pill already taken')
                               ledonoff(0, 255, 0)
               else:
                       #DEEPSLEEP
        time.sleep(900)

ghans
Posts: 7718
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany

Re: Uhrzeit - While-Schleifen-Steuerung

Wed Feb 14, 2018 10:24 am

Ich glaube du solltest dich mit Multithreading mit Python beschäftigen, insbesonders mit der Klasse threading.Timer .
Alternativ mal node-RED, wo man gar nicht mehr programmieren muss.

ghans
• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org

bambambam
Posts: 3
Joined: Wed Feb 14, 2018 8:03 am

Re: Uhrzeit - While-Schleifen-Steuerung

Fri Mar 09, 2018 4:10 pm

Hallöchen,

Ich habe mich mal mit threading auseinander gesetzt. Ich bin noch nicht so ganz dahinter gestiegen. Ich habe den Code jetzt mal in normalem Python mit entsprechenden Librarys geschrieben. Wenn ich jedoch meinen Code ausführe, bleibt er einfach stehen, und zwar in der callback-Function.

Kann mir jemand erklären, was da eigentlich passiert bzw. warum das Programm beim Drücken des Schalters hängen bleibt?

Code: Select all

# Import needed librarys
import threading
import time
import RPi.GPIO as GPIO
### SET GPIO
GPIO.setmode(GPIO.BCM)
### SET GPIO LED
led_gpio = 17
GPIO.setup(led_gpio, GPIO.OUT)
### SET GPIO SWITCH
switch_gpio = 27
GPIO.setup(switch_gpio, GPIO.IN, pull_up_down=GPIO.PUD_UP)
### SET TIME HOURS
timehours=(time.localtime(time.time())[3])
type(timehours)
### DEFINE GLOBAL TAKEN VARIABLE
global taken
taken = 0
# DEFINE PLACEHOLDER FOR BUZZER
def buzzerbeep():
    while True:
        if taken == 0:
            print("Pill not taken")
            print (taken)
            time.sleep(5)
    
# Define LED Toggle
def toggle_taken(_):
    GPIO.output(led_gpio, not GPIO.input(led_gpio))
    t1.cancel()
    global taken
    taken = 1
    print("Thread T1 cancelled")
    print("I'm on the Exit way")
    time.sleep(5)
    print(taken)
    #exit()
# Define timer
t1 = threading.Timer(1.0, buzzerbeep)
t1.setName('t1')
try:
    while timehours >= 16 and timehours <= 16:
        if taken == 0:
            t1.start()
        else:
            print("BLHJSHKJHDKJHKJDSHKJHDKJHJKHKJHKJH")
    
        GPIO.add_event_detect(switch_gpio, GPIO.RISING, callback=toggle_taken, bouncetime=500)
    print("BLHJSHKJHDKJHKJDSHKJHDKJHJKHKJHKJH")
except KeyboardInterrupt:
        print ("done")
        t.cancel()




smartifahrer
Posts: 509
Joined: Sat Feb 13, 2016 8:10 am

Re: Uhrzeit - While-Schleifen-Steuerung

Fri Mar 09, 2018 5:31 pm

Ich bin kein Python Programierer, aber wenn ich es richtig interpretiere trift das folgende nur zu wenn timehours = 16 ist

while timehours >= 16 and timehours <= 16:

wäre es nicht sinnvoller es dann so zu formulieren

while timehours == 16:

def buzzerbeep():
while True:

Fehlt hier nicht eine Abbruch-Bedingung? Da True ja nicht False werden kann ist es doch eine Endlosschleife.

bambambam
Posts: 3
Joined: Wed Feb 14, 2018 8:03 am

Re: Uhrzeit - While-Schleifen-Steuerung

Sat Mar 10, 2018 6:03 am

Hallo Smartifahrer,

jap, Du hast völlig Recht.

Zu der Uhrzeit: Ich habe 16 beidseitig genommen, weil ich zu dieser Uhrzeit das Skript getestet habe. Prinzipiell sollen da in Zukunft 2 unterschiedliche Uhrzeiten stehen.

Zur While-True: Auch da liegst Du richtig, allerdings habe ich eine marginale Erklärung dafür. Buzzerbeep wird in einem eigenen Thread aufgerufen. Buzzerbeep soll aber alle 5 Sekunden ausgeführt werden (später 15 Minuten). Damit der Thread nicht immer wieder neu gestartet werden muss, habe ich eine While-True eingebaut. Die Abbruchbedingung fehlt, wird aber durch thread.cancel() erreicht, und zwar dann, wenn ich sie brauche.

Ob das alles wirklich Sinn macht, weiß ich nicht. Es funktioniert, aber er bleibt eben immer im Stück nach thread.cancel() hängen.

User avatar
mline
Posts: 1066
Joined: Sun Jan 27, 2013 1:47 pm
Location: Austria, Vienna

Re: Uhrzeit - While-Schleifen-Steuerung

Sat Mar 10, 2018 8:53 am

bambambam wrote:
Sat Mar 10, 2018 6:03 am
Ob das alles wirklich Sinn macht, weiß ich nicht. Es funktioniert, aber er bleibt eben immer im Stück nach thread.cancel() hängen.
Kenn mich mit python nur solala aus... darum weiß ich nicht genau wie sich Timer und Threads da verhalten.

Aber, hast du auch geprüft ob sich ein Timer (den du ja verwendest) genau so verhält wie ein echter Thread?
Ich vermute mal, dass ein Timer ein "return" erwartet und weil du in der Routine ja ne Endlosschleife hast wird aus dieser nie wieder zurückgekehrt. Dein Programm hängt also in der Timer-Routine fest.

Oder es wird versucht den Thread zu beenden, da dieser aber eine Endlosschleife beinhaltet kann das nicht passieren. In vielen anderen Sprachen müsste man innerhalb der Schleife den Zustand des Threads abfragen und die Schleife beenden falls ein Cancel angefordert wurde.

Auf jeden Fall aber solltest du dir Multithreading nochmal ansehen. Denn Timer sind für sowas nicht gedacht.
<~~>

Return to “Deutsch”

Who is online

Users browsing this forum: No registered users and 6 guests