Forum: Mikrocontroller und Digitale Elektronik Problem mit Python / Beschaltung *einfach*


von sunshineh (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

leider bekomme ich jede Minute einen Alarm, obwohl die Lichtschranke gar 
nicht schließt.

Hier ist mein Code. Für nen Tipp wäre ich dankbar, da ich grad den Wald 
vor lauter Bäumen nicht sehe...
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
import RPi.GPIO as GPIO
4
import smtplib
5
import time
6
BtnPin = 11
7
Gpin   = 12
8
Rpin   = 13
9
fromaddr = 'xxx@googlemail.com'
10
toaddrs  = 'xxx@googlemail.com'
11
msg = """From: Raspberry Pi Alarmsystem
12
To: xxx@googlemail.com
13
Subject: Die Lichtschranke wurde unterbrochen
14
Achtung: Ihre Lichtschranke wurde unterbrochen, bitte pruefen sie die Ursache!
15
"""
16
username = xxx@googlemail.com'
17
password = 'xxx
18
def setup():
19
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
20
    GPIO.setup(Gpin, GPIO.OUT)     # Set Green Led Pin mode to output
21
    GPIO.setup(Rpin, GPIO.OUT)     # Set Red Led Pin mode to output
22
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)    # Set BtnPin's mode is input, and pull up to high level(3.3V)
23
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)
24
def Led(x):
25
    if x == 1:
26
        GPIO.output(Rpin, 1)
27
        GPIO.output(Gpin, 0)
28
    if x == 0:
29
        GPIO.output(Rpin, 0)
30
        GPIO.output(Gpin, 1)
31
def Print(x):
32
    if x == 0:
33
        print '    ***********************'
34
        print '    *   Button Pressed!   *'
35
        print '    ***********************'
36
def SendMail():
37
        server = smtplib.SMTP('smtp.gmail.com:587')
38
        server.starttls()
39
        server.login(username,password)
40
        server.sendmail(fromaddr, toaddrs, msg)
41
        server.quit()
42
        time.sleep(60)
43
        print("Mail gesendet")
44
def WriteFile():
45
        date = time.strftime("%x")
46
        zeit = time.strftime("%X2")
47
        fileout = open("/home/pi/Desktop/Lichtschranke.txt","a")
48
        time.sleep(0.1)
49
        fileout.write(date+";"+zeit+"; Die Lichtschranke wurde unterbrochen \n")
50
        time.sleep(0.1)
51
        fileout.close()
52
        print("Log-File geschrieben")
53
def detect(chn):
54
    WriteFile()        
55
    print(GPIO.input(BtnPin))
56
    SendMail()
57
58
def loop():
59
    while True:
60
        pass
61
def destroy():
62
    GPIO.output(Gpin, GPIO.HIGH)       # Green led off
63
    GPIO.output(Rpin, GPIO.HIGH)       # Red led off
64
    GPIO.cleanup()                     # Release resource
65
if __name__ == '__main__':     # Program start from here
66
    setup()
67
    try:
68
        loop()
69
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
70
        destroy()

von Simon T. (simon_t399)


Lesenswert?

Hallo,

was passiert denn, wenn du in "detect" mal alles sein lässt und 
stattdessen dort einfach mal etwas ausgibtst?

Alternativ weiß ich auch nicht ganz genau, was das 
"GPIO.setup(BtnPin..." tut, wenn man einen Pull-Up-Widerstand extern 
eingebaut hat (hast du ja laut dem Bild) und gleichzeitig noch den im 
Chip einschaltet. Also "pull_up_down" ggf. mal weglassen.

von Karl (Gast)


Lesenswert?

Versuch es erstmal mit einem Schalter, anstatt einer Lichtschranke. 
Warum GPIO.BOTH? Was soll das time.sleep(60) in der SendMail()-Funktion?

Wenn man mit Python arbeitet, sollte man mal ein Tutorial über OOP 
lesen, das macht es übersichtlicher.

von sunshineh (Gast)


Lesenswert?

Hallo,

danke für die Antworten. Ich habe bisher noch nichts mit Python gemacht 
und diesen Code aus verschiedenen Teilen im Internet 
zusammengeschustert. Wenn etwas schlecht daran ist, bitte ich um 
Verbesserungsvorschläge oder Tipps zu guten Tutorials.


Die 60 Sekunden hatte ich nur eingefügt, da ich nicht ständig eine 
Email-Benachrichtigungen bekommen wollte. Ich habe nun gemerkt, dass 
dies ein einer schlechten Verbindung gelegen hat und nicht am Code.

Zudem hab ich nun den Eingang der Lichtschranke mit einem Pulldown 
Widerstand belegt und nun bekomme ich (meist) wirklich nur noch eine 
Benachrichtigung, wenn der die Schranke schließt.

Aktuelle Probleme:
1. Beim Unterbrechen der Lichtschranke erhalte ich innerhalb der ersten 
Millisekunden mehrfach die Info, dass die Lichtschranke durchbrochen 
wurde.
Wie bekomme ich dieses "prellen" raus?

2. Zudem möchte ich mich dagegen absichern, wenn die Lichtschranke 
dauernd geschlossen ist (also kaputt ist oder wer was dazwischen 
stellt). Auch in diesem Fall möchte ich eine Benachrichtigung erhalten.
(....Ich habe dies ansatzweise so gemacht, dass ich in der 
Interrupt-Funktion eine while Schleife eingebaut habe, so dass man erst 
1min warten musste, und dann nochmals prüfte, dass hat aber nicht 
hingehauen)

von sunshineh (Gast)


Lesenswert?

Das mit dem Prellen habe ich raus, habe die Bouncetime auf 2000 erhöht 
nun bräuchte ich nur noch eine Lösung für den Dauerkontakt.

von Cihan (Gast)


Lesenswert?

sunshineh schrieb:
> nur noch eine Lösung für den Dauerkontakt
Dafür verwendet man einen Timeout oder Watchdog.
Was willst Du wann im Falle des Dauerkontaktes machen bzw. auslösen?

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

sunshineh schrieb:
> Das mit dem Prellen habe ich raus, habe die Bouncetime auf 2000 erhöht
> nun bräuchte ich nur noch eine Lösung für den Dauerkontakt.
in deiner loop(), die im übrigen sowieso ein time.sleep(1) enthalten 
sollte (schau dir mal die Prozessorauslastung an wenn dein Programm 
läuft) fragst du den Zustand des Eingangs noch mal ab. Wenn der Eingang 
aktiv ist erhöhst du einen Zähler, wenn der Eingang inaktiv ist setzt du 
den Zähler auf Null. Erreicht der Zähler z.B. 10 dann ist der Eingang 
schon 10s aktiv und du kannst dein gewünschtest Ereignis (Mail) 
auslösen.

Sascha

von sunshineh (Gast)


Lesenswert?

Sorry, ich kriegs nicht hin. Wie muss ich meine Main-Schleife anpassen, 
damit es geht?

von sunshineh (Gast)


Lesenswert?

Also nun bin ich schonmal soweit, dass ich in der Main die SleepTime 
eingebunden habe. Nun dachte ich mir, dass ich jedesmal dort den Zustand 
der Lichtschranke abfrage und in einer Variablen hochzähle
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
import RPi.GPIO as GPIO
4
import smtplib
5
import time
6
BtnPin = 13
7
Gpin   = 12
8
Rpin   = 11
9
cnt = 0
10
11
def setup():
12
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
13
    GPIO.setup(Gpin, GPIO.OUT)     # Set Green Led Pin mode to output
14
    GPIO.setup(Rpin, GPIO.OUT)     # Set Red Led Pin mode to output
15
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)    # Set BtnPin's mode is input, and pull down to low
16
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=1000)
17
    
18
def Led(x):
19
    if x == 1:
20
        GPIO.output(Rpin, 1)
21
        GPIO.output(Gpin, 0)
22
    if x == 0:
23
        GPIO.output(Rpin, 0)
24
        GPIO.output(Gpin, 1)
25
def Print(x):
26
    if x == 0:
27
        print '    ***********************'
28
        print '    *   Button Pressed!   *'
29
        print '    ***********************'
30
def SendMail(x):
31
        server = smtplib.SMTP('smtp.gmail.com:587')
32
        server.starttls()
33
        server.login(username,password)
34
        if x == 0:      # server.sendmail(fromaddr, toaddrs, msg1)     
35
                print("Lichtschranke unterbrochen > Mail gesendet")
36
        if x == 1:      # server.sendmail(fromaddr, toaddrs, msg2)
37
                print("Lichtschranke immer noch unterbrochen > erneut Mail gesendet")
38
        server.quit()
39
def WriteFile():
40
        date = time.strftime("%x")
41
        zeit = time.strftime("%X2")
42
        fileout = open("/home/pi/Desktop/Lichtschranke.txt","a")
43
        time.sleep(0.1)
44
        fileout.write(date+";"+zeit+"; Die Lichtschranke wurde unterbrochen \n")
45
        time.sleep(0.1)
46
        fileout.close()
47
        print("Log-File geschrieben")
48
def detect(chn):
49
        time.sleep(0.1)
50
        print("in der detect ", GPIO.input(BtnPin)) 
51
        if GPIO.input(BtnPin) == GPIO.LOW:      # Lichtschranke wurde unterbrochen
52
                WriteFile()
53
                Led(1)
54
                print("detect") # SendMail(0)
55
        if GPIO.input(BtnPin) == GPIO.HIGH:     # Lichtschranke wieder frei
56
                print("wieder frei")
57
                Led(0)
58
def cntUnterbrochen(u):
59
        if u == 0:
60
                cnt = cnt + 1
61
                print("cnt aufaddieren = ", cnt)
62
        if u == 1:
63
                cnt = 0
64
                print("cnt rucksetzen = ", cnt)
65
def loop():
66
        while True:
67
                time.sleep(1)
68
                cntUnterbrochen(GPIO.input(BtnPin))
69
                print("main")
70
              
71
def destroy():
72
    GPIO.output(Gpin, GPIO.HIGH)       # Green led off
73
    GPIO.output(Rpin, GPIO.HIGH)       # Red led off
74
    GPIO.cleanup()                     # Release resource
75
if __name__ == '__main__':     # Program start from here
76
    setup()
77
    try:
78
        loop()
79
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
80
        destroy()

Allerdings bekomm ich hier die Meldung
cnt = cnt + 1
UnboundLocalError: local variable "cnt" referenced before assignment

von Nosnibor (Gast)


Lesenswert?

Er hält cnt für eine lokale Variable in cntUnterbrochen(), weil er's 
nicht besser weiß. Das gibt natürlich Ärger (uninitialisierte Variable).

"global cnt" am Anfang der Funktion klärt das Mißverständnis auf.

von sunshineh (Gast)


Lesenswert?

Funktioniert, danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.