Seite 1 von 2

Schleife in vorhandenes Skript erstellen

Verfasst: Freitag 2. Oktober 2020, 10:02
von krischeu1
Hi,
ich habe mir als Codefledderer ein Skript zusammengebaut, welches die Unterbrechungen zählt und die Uhrzeit als Unixzeit in eine Textdatei schreibt, die später zum Auslesen und Grafischer Darstellung genutzt wird.

Leider bin ich zu blöd i = i + 1 an die richtige Stelle zu bringen. Das sollte am Besten in der Textdatei Kommagetrennt neben der Uhrzeit stehen.
Kann mir da jemand helfen.

Code: Alles auswählen

import RPi.GPIO as GPIO
import os, time
from time import strftime,localtime
 
RECEIVER_PIN = 23
 
def callback_func(channel):
    if GPIO.input(channel):
        print("Sensor1: Lichtschranke wurde unterbrochen")
        date_local = strftime("%Y-%m-%d %H:%M:%S", localtime())
        ticks = time.time()
        print(date_local)
        print(ticks)
        with open("/home/pi/Documents/sensors/sensor01_tageswert.txt","a+") as sensor01:
        #    sensor01.write(date_local)
            sensor01.write(str(ticks))
            sensor01.write("\n")
        # alternativ kann ein Script / Shell Befehl gestartet werden
        # os.system("ls")
 
if __name__ == '__main__':
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    GPIO.setup(RECEIVER_PIN, GPIO.IN)
    GPIO.add_event_detect(RECEIVER_PIN, GPIO.RISING, callback=callback_func, bouncetime=200)
        
    try:
        while True:
            time.sleep(0.25)
    except:
        # Event wieder entfernen mittels:
        GPIO.remove_event_detect(RECEIVER_PIN)

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Freitag 2. Oktober 2020, 11:03
von Sirius3
In einem Callback sollte möglichst wenig passieren, Dateienöffnen geht eigentlich gar nicht. Der Dateimodus a+ ist eigentlich nie sinnvoll. `as` bei Import ist zum Umbenennen da, `GPIO` wird aber gar nicht umbenannt. `os` wird importiert, aber gar nicht benutzt.
Warnungen sind dazu da, um sie zu beheben, nicht um sie zu ignorieren. Dazu muß aber zum Schluß auch GPIO.cleanup aufgerufen werden.
Nakte except sollte man nicht benutzen, da werden wirklich alle Fehler abgefangen und eine Fehlersuche unmöglich.

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
 
RECEIVER_PIN = 23
 
def callback(queue, channel):
    queue.put(time.time())

def main():
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.RISING, callback=partial(callback, queue), bouncetime=200)
        with open("/home/pi/Documents/sensors/sensor01_tageswert.txt", "a") as sensor01:
            while True:
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}\n")
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()
Wenn Du ein i = i + 1 noch in die Datei schreiben willst, dann pack das doch einfach mit in den String:

Code: Alles auswählen

sensor01.write(f"{ticks}, i = i + 1\n")
Falls Du einen Zähler willst, der sollte jetzt trivial einbaubar sein.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Freitag 2. Oktober 2020, 19:06
von krischeu1
Hi,
Leider kommt kein Eintrag hinzu.
Kannst du da noch mal schauen?
Grüße
Heinz

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Freitag 2. Oktober 2020, 19:12
von krischeu1
Achso,
mir ist auch noch aufgefallen, daß beim unterbrechen nun etwas neues passiert.
Wenn ich unterbreche, kommt die Meldung "Lichtschranke unterbrochen". Wenn das Licht dann wieder auf den Photowiderstand trifft, kommt auch die Meldung "Lichtschranke unterbrochen".

Grüße
Heinz

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Freitag 2. Oktober 2020, 19:12
von krischeu1
Achso,
mir ist auch noch aufgefallen, daß beim unterbrechen nun etwas neues passiert.
Wenn ich unterbreche, kommt die Meldung "Lichtschranke unterbrochen". Wenn das Licht dann wieder auf den Photowiderstand trifft, kommt auch die Meldung "Lichtschranke unterbrochen".

Grüße
Heinz

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Samstag 3. Oktober 2020, 09:39
von Sirius3
Willst du die Daten sofort parallel dazu lesen? Dann brauchst du noch ein flush nach dem write.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Samstag 3. Oktober 2020, 14:53
von krischeu1
mir würde ein flush nach i = 120 reichen

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Montag 12. Oktober 2020, 18:45
von krischeu1
Hi,
leider kommt nun folgendes im LOG
1602524641.0321817, i = i + 1

i=i+1 sollte halt Zählen

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Montag 12. Oktober 2020, 19:05
von krischeu1
Hier die aktuelle Version mit dem Zählerproblem

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
 
RECEIVER_PIN = 23
 
def callback(queue, channel):
    queue.put(time.time())

def main():
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.RISING, callback=partial(callback, queue), bouncetime=200)
        with open("/home/pi/Documents/sensors/sensor01_tageswert.txt", "a+") as sensor01:
            while True:
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}, i = i + 1\n")
                sensor01.flush()
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Montag 12. Oktober 2020, 19:11
von sparrow
Aber das ist doch genau das, was du wolltest.
krischeu1 hat geschrieben: Freitag 2. Oktober 2020, 10:02Leider bin ich zu blöd i = i + 1 an die richtige Stelle zu bringen. Das sollte am Besten in der Textdatei Kommagetrennt neben der Uhrzeit stehen.
Wenn du eunen Zähler möchtest, musst du eine Variable entsprechend hochzählen.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 17:01
von krischeu1
Im LOG kommt aber immer:
112341234.12341 i=i+1
1234123412.1234 i=1+1
12341234.123412 i=i+1

Es hätte aber eher sein sollen
112341234.12341 1
1234123412.1234 2
12341234.123412 3

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 17:22
von Sirius3
Für einen Zähler bietet sich `itertools.count` an:

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
from itertools import count

RECEIVER_PIN = 23
OUTPUT_FILENAME = "/home/pi/Documents/sensors/sensor01_tageswert.txt"

def callback(queue, channel):
    queue.put(time.time())

def main():
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.RISING, callback=partial(callback, queue), bouncetime=200)
        with open(OUTPUT_FILENAME, "a+") as sensor01:
            for counter in count(1):
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}, {counter}\n")
                sensor01.flush()
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 17:37
von krischeu1
Das ist sooo cool. Und ich probier schon ewig mit dem i=i+1 rum.

Vielen Dank Sirius3.

Das letzte Problem wäre jetzt noch, warum Zählt die Funktion die Unterbrechung der Lichtschranke UND wenn der Lichstrahl wieder auf den Photowiderstand kommt?
bzw. wie kann ich wirklich nur die Unterbrechungen zählen?

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 19:40
von krischeu1
Hi,
warum kann man den counter bei einem Stand von z.B. 6 nicht wieder auf 1 zurück setzen?
Wie kann man das angehen?

Grüße
Heinz

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
from itertools import count

RECEIVER_PIN = 23
OUTPUT_FILENAME = "/home/pi/Documents/sensors/sensor01_tageswert.txt"

def callback(queue, channel):
    queue.put(time.time())

def main():
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.FALLING, callback=partial(callback, queue), bouncetime=200)
        with open(OUTPUT_FILENAME, "a+") as sensor01:
            for counter in count(1):
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}, {counter}\n")
                print (counter)
                if counter == 6:
                    print ("Counter ist 6")
                    count = 1
                else: 
                    print ("Counter ist nicht 6")
                sensor01.flush()
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 19:43
von __deets__
Wenn du counter meinst, musst du schon counter schreiben.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 19:47
von krischeu1
Geändert ...
__deets__ hat geschrieben: Mittwoch 14. Oktober 2020, 19:43 Wenn du counter meinst, musst du schon counter schreiben.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 19:49
von Sirius3
Natürlich hat das Ändern der Laufvariable einer for-Schleife keinen Einfluß auf den Wert im nächsten Durchgang. Das wäre ja auch sehr verwirrend.
Du willst also immer wieder durch die Folge 1,2,3,4,5,6 durchgehen, dafür gibt es itertools.cycle:

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
from itertools import cycle

RECEIVER_PIN = 23
OUTPUT_FILENAME = "/home/pi/Documents/sensors/sensor01_tageswert.txt"

def callback(queue, channel):
    queue.put(time.time())

def main():
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.FALLING, callback=partial(callback, queue), bouncetime=200)
        with open(OUTPUT_FILENAME, "a+") as sensor01:
            for counter in cycle([1, 2, 3, 4, 5, 6]):
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}, {counter}\n")
                sensor01.flush()
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 20:21
von krischeu1
So funktioniert das nun mit den 60 Impulsen und dass er danach erst die Werte schreibt.
Leider fängt er aber auch wieder bei 0 an zu Zählen. Naja. Bin noch dran.
Aber so langsam wird das.


Grüße
Heinz

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue
from functools import partial 
from itertools import cycle

RECEIVER_PIN = 23
OUTPUT_FILENAME = "/home/pi/Documents/sensors/sensor01_tageswert.txt"

def callback(queue, channel):
    queue.put(time.time())

def main():
    liste01=[]
    for zaehler01 in range (60):
       liste01.append(zaehler01)
         
    try:
        queue = Queue()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(RECEIVER_PIN, GPIO.IN)
        GPIO.add_event_detect(RECEIVER_PIN, GPIO.FALLING, callback=partial(callback, queue), bouncetime=200)
        with open(OUTPUT_FILENAME, "a+") as sensor01:
             for counter in cycle(liste01):
                ticks = queue.get()
                print("Sensor1: Lichtschranke wurde unterbrochen")
                sensor01.write(f"{ticks}, {counter}\n")
                sensor01.flush()
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 20:26
von Sirius3
Eine Liste erzeugt man mit `list`: `list(range(60))`, ist aber gar nicht nötig, weil man auch das range-Objekt direkt verwenden kann.
Der Lichtschrankeneingang scheint wohl zu flackern.

Re: Schleife in vorhandenes Skript erstellen

Verfasst: Mittwoch 14. Oktober 2020, 20:29
von krischeu1
Sirius3 hat geschrieben: Mittwoch 14. Oktober 2020, 20:26 Eine Liste erzeugt man mit `list`: `list(range(60))`, ist aber gar nicht nötig, weil man auch das range-Objekt direkt verwenden kann.
Der Lichtschrankeneingang scheint wohl zu flackern.
Da flackert leider nix. Finger rein. Unterbechung wird gezählt. Ich halte das noch unterbrochen für ca. 5 Sekunden. Dann wieder Finger weg. Strahl ist wieder auf dem Sensor. Und das wird dann auch wieder gezählt.