Wert von Pythonscript in CSV Datei speichern

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Hallo,
ich braeuchte mal eure Hilfe. Um es vorweg zunehmen, mein Wissen um Python und Co
ist nicht weltbewegend. Ich habe den folgenden Code zusammengestellt. Er funktioniert so auch,
obwohl es bestimmt professioneller geht. Nun mein Problem. Wie kann ich den Wert der mit
" print("%1.2f" % delta ) "
ausgegeben wird, extra noch in eine txt oder csv Datei schreiben?
Ich habe dieses Forum schon durchsucht und verschieden Sachen gefunden, aber ich bekomme es nicht
in die Reihe das fuer michzu nutzen.
Ich bin fuer jede Hilfe dankbar.

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import datetime

# Variablen initialisieren
Tic = 0    # Zaehler
stopp = 0  # Zeitpunkt steigende Flanke 
start = 0  # Zeitpunkt fallende Flanke
delta = 0  # Zeitdifferenz zwischen start und stopp

# GPIO initialisieren
GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.IN) 

# internen Pullup-Widerstand aktivieren.
GPIO.setup(21, GPIO.IN, pull_up_down = GPIO.PUD_UP)

# Callback-Funktion fuer beide Flanken
def measure(channel):
  global start
  global stopp
  global delta
  if GPIO.input(21) == 0:       # fallende Flanke, Startzeit speichern
    start = time.time()
  else:                         # steigende Flanke, Endezeit speichern
    stopp = time.time()
    delta =  stopp - start       # Zeitdifferenz berechnen
    print("%1.2f" % delta )  
    
    
# Interrupt fuer beide Flanken aktivieren
GPIO.add_event_detect(21, GPIO.BOTH, callback=measure, bouncetime=50)#bouncetime=200

try:
  while True:
    # nix Sinnvolles tun
    Tic = Tic + 1
    #print "Tic %d" % Tic
    time.sleep(1)

# reset GPIO settings if user pressed Ctrl+C
except KeyboardInterrupt:
  GPIO.cleanup()
  print("\nBye!")
Zuletzt geändert von Anonymous am Mittwoch 22. Februar 2017, 17:47, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@erz55: Callback-Routinen sind nicht dazu da, Daten zu speichern oder groß auszuwerten. Am besten verwendest Du eine Queue, um die Ereignisse in das Hauptprogramm (das ja im Moment noch arbeitslos ist) zu übergeben:

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import Queue
 
# Callback-Funktion fuer beide Flanken
def measure(queue):
    # Flanke und Zeit speichern
    queue.put((GPIO.input(21) == 0, time.time()))
   
def main():
    # GPIO initialisieren
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(21, GPIO.IN)
    
    # internen Pullup-Widerstand aktivieren.
    GPIO.setup(21, GPIO.IN, pull_up_down = GPIO.PUD_UP)

    queue = Queue.Queue()
    # Interrupt fuer beide Flanken aktivieren
    GPIO.add_event_detect(21, GPIO.BOTH, callback=lambda _: measure(queue), bouncetime=50)
 
    try:
        while True:
            edge, zeit = queue.get()
            if edge:
                start = zeit
            else:
                delta = start - zeit
                print("%1.2f" % delta)
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
    print("\nBye!")

if __name__ = '__main__':
    main()
Dort ist es dann auch nicht schwer, statt des print eine Ausgabe in eine Datei zu schreiben.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Hallo Sirius3,

erstmal vielen Dank fuer die schnelle Antwort. Habe es gleich getestet.
Als Ausgabe kommt allerdings ein negativer Wert ( z.B. -2.18).
Ist es auch moeglich die Ausgabe so zu machen, das die Zeit zusammen gezaehlt wird?
Also Taster druecken - Zeit lauft - Taster loslassen - Zeit wird gespeichert und ausgegeben - Taster wieder druecken -
Zeit laeuft - Taster loslassen - Zeit wird dazugezaehlt und ausgegeben.
Wie gesagt , ich hab wirklich nicht viel Ahnung von der ganzen Sache. Und es ist auch keine Faulheit von mir.
Deshalb habe ich auch noch keinen Schimmer, wie man es macht den Wert in eine Datei auszugeben.
Kannst du mir bitte helfen.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein bisschen zu versuchen zu verstehen was da passiert bei DEINEM Projekt solltest du schon. Und die Grundlagen der Arithmetik sind ja auch seit der Grundschule bekannt. Wenn da eine negative Zahl bei rum kommt, woran kann denn das liegen? Wo wird denn gerechnet, und was laeuft da falsch?
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Da hast du schon rech und das mit dem Negativwert hab ich rausgekriegt
( Start und Zeit getauscht). Das mit der Grundschule ist aber schon wieder
reichlich 50 Jahre her. :D :D :D
Fuer das andere waere bisschen Hilfe nicht schlecht.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

In eine Datei zu schreiben ist ja nicht wirklich schwierig:

Code: Alles auswählen

with open("/pfad/zur/datei", "w") as outf:
    wert = 1.0
    outf.write("{}\n".format(wert))
Das musst du nun nur noch geschickt einbauen.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Da war ich wohl zu langsam. Ich hab es mal so probiert:

Code: Alles auswählen

try:
        while True:
            edge, zeit = queue.get()
            if edge:
                start = zeit
            else:
                delta = zeit - start
                print("%1.2f" % delta)
                s = ("%1.2f" % delta)
                f = file("verbrauch.csv", "w")
                f.write(s)
                f.close()
                
Das geht auch. Jetzt probier ich mal das von dir.
Was muss ich jetzt noch machen um das hinzubekommen?
Taster druecken - Zeit lauft - Taster loslassen - Zeit wird gespeichert und ausgegeben - Taster wieder druecken -
Zeit laeuft - Taster loslassen - Zeit wird dazugezaehlt und ausgegeben.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@erz55: Du mußt halt die neue Dauer auf die alte Zeitdauer draufaddieren.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Muss ich das so verstehen:
Wert aus Datei "verbrauch.csv" lesen.
Gelesener Wert plus aktueller Wert und diesen neuen Wert
wieder in Datei schreiben.
Das ist mir zu hoch.

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import Queue

# Callback-Funktion fuer beide Flanken
def measure(queue):
    # Flanke und Zeit speichern
    queue.put((GPIO.input(21) == 0, time.time()))

def main():
    # GPIO initialisieren
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(21, GPIO.IN)
   
    # internen Pullup-Widerstand aktivieren.
    GPIO.setup(21, GPIO.IN, pull_up_down = GPIO.PUD_UP)
 
    queue = Queue.Queue()
    # Interrupt fuer beide Flanken aktivieren
    GPIO.add_event_detect(21, GPIO.BOTH, callback=lambda _: measure(queue), bouncetime=50)
 
    try:
        while True:
            edge, zeit = queue.get()
            if edge:
                start = zeit
            else:
                delta = zeit - start
                print("%1.2f" % delta )
                s = ("%1.2f" % delta )
                f = file("verbrauch.csv", "w")
                f.write(s)
                f.close()
                
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
    print("\nBye!")
 
if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@erz55: wenn Du es schon beschreiben kannst, dann kann es ja nicht mehr zu hoch sein. Aber so kompliziert brauchst Du es Dir ja nicht zu machen, da Du ja weißt, welchen Wert Du im Schritt davor in die Datei geschrieben hast, brauchst Du ihn nicht wieder lesen.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Soweit versteh ich das schon. Der Wert "delta" wird in die Datei geschrieben.
Jetzt kommt der neue Wert, ist ja auch "delta" und ueberschreibt sofort das alte "delta".
An welcher Stelle soll ich die beiden "delta" addieren. :K
Etwa so:

Code: Alles auswählen

try:
        while True:
            edge, zeit = queue.get()
            if edge:
                start = zeit
            else:
                delta = zeit - start
                dauer = delta + delta
                print("%1.2f" % dauer )
                s = ("%1.2f" % dauer )
                f = file("verbrauch.csv", "w")
                f.write(s)
                f.close()
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Du solltest dir unbedingt Anfänger Tutorials zu Python durchlesen.

Code: Alles auswählen

    try:
            dauer = 0
            while True:
                edge, zeit = queue.get()
                if edge:
                    start = zeit
                else:
                     # delta = zeit - start
                    dauer += zeit - start
                    print("%1.2f" % dauer )
                    s = ("%1.2f" % dauer )
                    f = file("verbrauch.csv", "w")
                    f.write(s)
                    f.close()
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

wobei die Klammern bei print und der Zuweisung zu s überflüssig sind, dass der String zweimal erzeugt wird unschön ist, statt "file" "open" zum Öffnen von Dateien verwendet wird und man Dateien am besten mit dem with-Statement öffnet.

Code: Alles auswählen

            dauer = 0
            while True:
                edge, zeit = queue.get()
                if edge:
                    start = zeit
                else:
                     # delta = zeit - start
                    dauer += zeit - start
                    s = "%1.2f" % dauer
                    print s
                    with open("verbrauch.csv", "w") as f:
                        f.write(s)
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Haette ich so nicht hin bekommen.
Danke an alle die mir weiter geholfen haben.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Hallo nochmal,
ich moechte die Datei "verbrauch.csv" unter /var/www/html erstellen lassen,
so das ich im Netzwerk drauf zugreifen kann.
Bekomme aber immer die Fehlermeldung:
Traceback (most recent call last):
File "/var/www/html/verbrauch.py", line 45, in <module>
main()
File "/var/www/html/verbrauch.py", line 33, in main
f = file("verbrauch.csv", "w")
IOError: [Errno 13] Permission denied: 'verbrauch.csv'

Muss ich da die Berechtigungen aendern?

Danke
BlackJack

@erz55: Ich würde in ``/var/www/html/`` einen symbolischen Link auf die tatsächliche Datei setzen, dann braucht man dort nicht anderen Schreibrechte gewähren.

Die Zeile im Traceback sieht übrigens so aus als wenn Du entweder Dein Programm in ``/var/www/html/`` abgelegt hast, oder `os.chdir()` verwendet wird. Beides sollte man nicht tun. Und statt `file()` bitte `open()` verwenden.
erz55
User
Beiträge: 9
Registriert: Mittwoch 22. Februar 2017, 15:42
Kontaktdaten:

Sorry hatte mich vertippt. Die Datei die angelegt wird heist
"verbrauch.html" und nicht "verbrauch.csv".
Ich habe das Programm schon ueberall abgelegt und getestet..
Es haengt immer an den Schreibrechten. Da ich allein im Netzwerk bin,
waer es egal mit den Schreibrechten
Mit dem symbolischen Link das muss ich erstmal testen.
Ich moechte den Wert auf "verbrauch.html" von einen anderen PC im Netzwerk
mit Excel einlesen lassen. Da ist ein direkter Zugriff auf die Seite besser.Was muss ich
tun um das Speichern auf /var/www/html zu erreichen?
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@erz55: es wird immer verwirrender. Bisher hast Du nur Zahlen in Deiner Datei, das ist dann eher cvs als html. Und dieses Format ist dann auch für Excel besser geeignet. Und willst Du jetzt einen direkten Zugriff oder einen über einen Webserver?
BlackJack

@erz55: Die Rechte sind nicht egal, auch nicht wenn man alleine im Netzwerk ist. So sollte man gar nicht erst anfangen. Um irgendwo speichern zu können müssen halt die Rechte stimmen. Es muss also entweder mit dem passenden Benutzer ausgeführt werden, oder es müssen die passenden Rechte auf den Verzeichnissen existieren.

Allerdings ist IMHO ein symbolischer Link am einfachsten. Dann muss man im Webbereich nicht allgemein etwas zum schreiben freigeben.
JStefan
User
Beiträge: 2
Registriert: Donnerstag 7. Dezember 2017, 17:39
Wohnort: Südamerika
Kontaktdaten:

Erstmal ein freundliches HALLO in die Runde.
Ich bin Stefan (55), zusammen mit meiner Frau seit 8 Jahren auf drei Achsen in der Weltgeschichte unterwegs...aktuell in Kolumbien. Vor 4 Wochen habe ich einen Raspi 3 gekauft und versuche nun Ihn sinnvoll einzusetzen. Scripen etc. WISSEN / ERFAHRUNG: NULL ansonsten sind wir IT mässig im Obstladen... (mehr unter http://www.tvware.de)

Das erste sinnvolle Python Projekt soll die Überwachung unserer Kühl und Gefrier Kombi werden. Will sagen: Erster Schritt Aufzeichnung folgender Daten:
Laufzeiten der beiden Kühlkompressoren, innen Temperaturen, Außentemperatur, Höhe über NN.

Warum: Diese beiden Geräte sind die grössten elektrischen Verbraucher bei beschränktem Energievorrat (Batterien). Die aktive Lüftung, der Gasdruck etc. sind von mir beeinflussbar und ich denke es gibt Optimierungs Möglichkeiten... wenn Messdaten vorhanden sind und nicht geschätzt werden muss.
Die Hardware Umsetzung ist nicht mein Problem, es scheitert am Wissen um die Weichware...

Zum Thema:
Kopieren ist die höchste Form der Anerkennung...

Ich bin auf diesen Thread hier gestoßen und dachte, das kennst Du doch, denn mit dem Script habe ich auch angefangen (http://www.netzmafia.de/skripten/hardwa ... O_int.html und es wurde weiter entwickelt... gut so. Nun die Frage: Wo liegt der Bug...
Traceback (most recent call last):
File "/home/pi/KSKompressor5_1.py", line 46, in <module>
main()
File "/home/pi/KSKompressor5_1.py", line 32, in main
dauer += zeit - start
UnboundLocalError: local variable 'start' referenced before assignment
ist die Fehler Meldung von Thonny

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import queue as Queue
 
# Callback-Funktion fuer beide Flanken
def measure(queue):
    # Flanke und Zeit speichern
    queue.put((GPIO.input(6) == 0, time.time()))
 
def main():
    # GPIO initialisieren
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(6, GPIO.IN)
   
    # internen Pullup-Widerstand aktivieren.
    # GPIO.setup(21, GPIO.IN, pull_up_down = GPIO.PUD_UP)
 
    queue = Queue.Queue()
    # Interrupt fuer beide Flanken aktivieren
    GPIO.add_event_detect(6, GPIO.BOTH, callback=lambda _: measure(queue), bouncetime=500)
 
    try:
            dauer = 0
            while True:
                edge, zeit = queue.get()
                if edge:
                    start = zeit
                else:
                    dauer = 0
                    dauer += zeit - start
                    s = "%1.2f" % dauer
                    print (s)
                    with open("verbrauch.csv", "a") as f:
                        f.write(s)

               
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
    print("\nBye!")
    
if __name__== '__main__':
    main()
   
Erstmal vielen Dank bei allen bisher Beteiligten... und seit einem Newcommer nicht böse...jeder hat mal angefangen.... Ja ja ich lese es jetzt schon... fang klein an, Tuto's etc. ist klar..

Muchas Gracias
Stefan
Antworten