Scripts in einer 60 Sekundenschleife

Code-Stücke können hier veröffentlicht werden.
Antworten
cced
User
Beiträge: 1
Registriert: Dienstag 9. September 2014, 15:32

Hallo zusammen,
Danke, dass ich hier Aufgenommen wurde..
Ich bin (leider schon wieder) ein Absoluter Anfänger im Bereich Python und hoffe auf eure Hilfe.
Ich habe ein bereits fertiges Script, welches mir die Sensordaten eines Wasserdurchflußsensors ausließt.
Das funktioniert auch.
Mein Problem: Ich möchte, das das Script nur 60 Sekunden lang den durchfluß mißt, und dann den ermittelten Wert in Liter / Stunde
in eine MySQL Datenbank schreibt.
Hier erst einmal mein Code:

Code: Alles auswählen

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time, sys

FLOW_SENSOR = 23

GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

global count
global L-hour
count = 0

def countPulse(channel):
   global count
   count = count+1    #Hier wird das Signal des Sensors hochgezählt. Dies soll 60 Sekunden lang passieren.
   L-hour=count*7,5  # danach soll mit dieser Rechnung  Liter / Stunde Berechnet werden
   print L-hour          # Dieser Wert soll in eine MySQLDB eingetragen werden. (SRV:localhost DB: aqua USER:pi PE gEhEiM)
   
GPIO.add_event_detect(FLOW_SENSOR, GPIO.RISING, callback=countPulse)

while True:
    try:

        time.sleep(1)
        
    except KeyboardInterrupt:
        print '\ncaught keyboard interrupt!, bye'
        GPIO.cleanup()
        sys.exit()
Ich danke euch schon im Voraus für eure Unterstützung und Hilfe.

LG Markus
BlackJack

@cced: Dir ist schon klar dass das Skript dort nicht nur nicht läuft sondern nicht einmal am Compiler vorbei kommt? ;-)

Wo ist denn jetzt das Problem? Wenn Du willst das es nicht endlos läuft, dann würde es zum Beispiel Sinn machen keine Endlosschleife rein zu schreiben.

Das ``global`` ist auch sehr unschön. Aber mit objektorientierter Programmierung möchte sich anscheinend kaum ein Raspi-Benutzer auseinandersetzen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@cced
Wenn Du etwas eine bestimmte Zeit machen möchtest, benötigst Du eine Startzeit und schaust dann in bestimmten Abständen nach, wie weit die aktuelle Zeit von der Startzeit entfernt ist:

Code: Alles auswählen

def counter(seconds):
    start = time.time()
    while True:
        elapsed = time.time() - start
        if elapsed > seconds:
            break
        print '{:.0f} seconds'.format(elapsed)
        time.sleep(1)
BlackJack hat geschrieben:Das ``global`` ist auch sehr unschön. Aber mit objektorientierter Programmierung möchte sich anscheinend kaum ein Raspi-Benutzer auseinandersetzen.
Raspi-Benutzer sind noch richtige Männer, die ihre Listen von oben nach unten abarbeiten und dabei alles im Griff behalten! :wink:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@mutetella:
Warum nicht `while elapsed < seconds:`?

@cced:
Evtl. musst Du das `sleep` in der Warteschleife so anpassen, dass Dir kein Event verloren geht (und er falsch messen würde). Das hängt davon ab, wie die callback-Sache in GPIO implementiert ist - also ob 2 aufeinander folgende Events oder ein Event innerhalb eines `sleep` verschluckt werden können. Darüber gibt der GPIO-Sourcecode Aufschluß bzw. kannst Du es auch testen, in dem Du das sleep auf einen sehr großen Wert setzt und prüfst, ob er noch die korrekten Werte misst.
BlackJack

@mutetella: So'n Quatsch, die richtigen Männer unter den Raspi-Benutzern schreiben ihre Programme in Assembler und booten gleich in ihren eigenen Code, ohne lästiges Betriebssystem dazwischen. Python ist was für Weicheier. :mrgreen:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wat? Schreiben? Etwa in einem Editor? Und dann Code durch einen Assembler erhalten? Nee, echte Männer nehmen einen Locher und stanzen sich ihre Lochkarten mit dem Bitmuster des Maschinencodes noch manuell! :P
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Oh my god! Das sagst Du mir jetzt, nachdem ich mir einen Raspi an meine Goldkette gehängt habe und überall herum erzähle, in Python zu programmieren.... Es ist so schwer, ein Mann zu sein!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

jerch hat geschrieben:Warum nicht `while elapsed < seconds:`?
Weil ich ein Mann bin, der seiner Maschine Anweisungen erteilt, die sich gewaschen haben!! Und jetzt will ich nichts mehr davon hören! :evil:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ich hab beim Reinkommen wohl den Bierkasten übersehen :wink:
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Um nochmal zum Ernst der Lage zurückzukommen :wink: : Wenn ich die Ungenauigkeit, die die Prozesse innerhalb der Schleife verursachen, minimieren möchte, würde ich erstmal sowas machen:

Code: Alles auswählen

import sys
import time

def do_something():
    time.sleep(0.5)

def counter(seconds):
    start = time.time()
    elapsed = 0
    while elapsed < seconds:
        action_start = time.time()
        elapsed = time.time() - start
        do_something()
        timeout = time.time() - action_start
        time.sleep(timeout)
    print '{} seconds'.format(elapsed)

if __name__ == '__main__':
    counter(int(sys.argv[1]))
Genau ist das aber auch nicht :( :

Code: Alles auswählen

$ python ./counter.py 10
10.0182778835 seconds
Wie ließe sich die Genauigkeit denn erhöhen?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Assembler und direkt auf der Hardware programmieren, ohne ein Betriebssystem oder zumindest mit einem bei dem nicht mehrere Prozesse laufen bei denen das Betriebssystem nahezu beliebig entscheiden kann wer gerade dran ist und wer nicht.

Man sollte sich halt klar machen was man bei ”normalen” Betriebssystemen wie Linux, MacOS, oder Windows, an Genauigkeit erwarten darf und was nicht. Also selbst ohne eine interpretierte Programmiersprache mit Threads und automatischer Speicherbereinigung geht da nichts ”genau”, ausser vielleicht direkt in Treibern in kleinem Rahmen bei denen man den Rest des Systems komplett ”anhalten” kann.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@mutetella: Du berücksichtigst nicht, dass auch die Befehle außerhalb Deines do_something Zeit brauchen, so dass die tatsächliche Zeit von Deiner synchronisierten Zeit immer weiter abweichen. Das kannst Du schön an einem print innerhalb der Schleife sehen:

Code: Alles auswählen

2.14576721191e-06
1.00165820122
2.00322818756
3.0048520565
4.00651597977
5.00743103027
6.00912308693
7.01078820229
8.01245999336
9.0141890049
10.0159130096
10.0159881115 seconds
Hier meine Version:

Code: Alles auswählen

import sys
import time

def do_something():
    time.sleep(0.5)

def counter(seconds):
    start = time.time()
    for elapsed in xrange(seconds):
        print time.time()-start
        next_time = start + elapsed + 1
        do_something()
        time.sleep(next_time - time.time())
    print '{0} seconds'.format(time.time()-start)

if __name__ == '__main__':
    counter(int(sys.argv[1]))
und die Zeiten:

Code: Alles auswählen

3.81469726562e-06                                                                                    
1.00055193901
2.00055503845
3.00056791306
4.00055289268
5.00053501129
6.00059485435
7.00055599213
8.00055384636
9.00055193901
10.0005438328 seconds
Man sieht, dass die Zeitdifferenzen nach einem kleinen Startschwierigkeit von einer halben Millisekunde dann nur noch um 10 Mikrosekunden schwanken, bis auf eine Außnahme, wo es 50 Mikrosekunden sind, weil wahrscheinlich irgendein anderer Prozess reingespielt hat.
BlackJack

So allgemein noch mal zur Erinnerung: Das Skript läuft auf einem RaspberryPi. Wenn da ein anderer Prozess dazwischen kommt und der gerade auf die SD-Karte schreibt oder auch nur liest, können da *deutlich* grössere Abweichungen entstehen. Linux ist kein Realtime-Betriebssystem. Selbst auf einem normalen PC kann es einem passieren das andere Prozesse das System zumindest kurzeitig so auslasten, dass die Wartezeiten die man mit Sleep genau ”treffen” kann, sehr stark schwanken.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ich würde davon ausgehen, dass die Clock im Raspi hinreichend genau ist für Heimanwenderaufgaben, würde mich allerdings für den Messzeitraum nicht auf den mit sleep eingestellten Wert verlassen, sondern diesen mit Endzeitpunkt - Startzeitpunkt holen. Was ich bei dem Ansatz tricky finde, ist die Frage, wie die Signale an den Pins reinkommen z.B. ob der GPIO-Treiber realtime ist (definierte Abtasterate?), was ja einer Auflösungsgrenze gleich käme. Ist das nicht realtime, wirds garstig - da nicht klar ist, ob nicht zwischendurch aufgrund einer höheren CPU-Belastung Events übersehen wurden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Aber mit objektorientierter Programmierung möchte sich anscheinend kaum ein Raspi-Benutzer auseinandersetzen.
Ich denke das liegt daran, dass im Raspberry Pi-Umfeld Anfänger andere Anfänger belehren, so dass am Schluss alle nur was haben was so semi-funktioniert. Es tut, aber wenn man es schief anschaut fällts auseinander und der Code ist total konfus. Aus dem Umfeld habe ich schon die furchtbarsten Python-Quellcodes gesehen die man sich denken kann. Ist etwas schade, aber da entgegenzuarbeiten ist wie gegen Windmühlen ankämpfen, denke ich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Grossartig, der RaspberryPi macht aus Python das neue PHP. :twisted:
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Vllt wirds Zeit für eine Forumssektion "Raspberry Phyton" :twisted:
Antworten