Berechnung in Schleifen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Thombo
User
Beiträge: 3
Registriert: Mittwoch 20. August 2014, 19:11

Hallo Forum,

ich baue mir gerade eine Temperaturüberwachung mit einem Raspberry Pi für meine KWL Anlage - http://de.wikipedia.org/wiki/Kontrollie ... C3%BCftung
Soweit habe ich alles am laufen, allerdings stehe ich nun vor dem Problem dass ich gerne die Energieeffizienz meiner KWL-Anlage automatisch berechnen möchte.

Die Formel lautet: Wirkungsgrad = (Zulufttemperatur - Frischlufttemperatur) / (Ablufttemperatur - Frischlufttemperatur) * 100

Ich würde nun gerne bei der Schleife

Code: Alles auswählen

for path in pathes:
ansetzen wollen.
Diese Schleife fragt die Sensoren ab und liefert die aktuelle Temperatur. Die Abfrage der Sensoren dauert aber immer und sollte nicht zu häufig / schnell hintereinander ausgeführt werden, daher würde ich gerne die ausgelesenen Werte aus "data" berechnen.

Ich müsste also irgendwie die Berechnung (data[3] - data[1]) / (data[2] - data[3]) *100 eingebaut bekommen. Wer kann mir dabei helfen?
Das Skript habe ich im Internet gefunden, ich selber bin Python-Neuling.
http://www.kompf.de/weather/pionewiremini.html


Hier das Skript:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import re, os, rrdtool, time

# function: read and parse sensor data file
def read_sensor(path):
  value = "U"
  try:
    f = open(path, "r")
    line = f.readline()
    if re.match(r"([0-9a-f]{2} ){9}: crc=[0-9a-f]{2} YES", line):
      line = f.readline()
      m = re.match(r"([0-9a-f]{2} ){9}t=([+-]?[0-9]+)", line)
      if m:
        value = str(float(m.group(2)) / 1000.0)
    f.close()
  except (IOError), e:
    print time.strftime("%x %X"), "Error reading", path, ": ", e
  return value

# define pathes to 1-wire sensor data
pathes = (
  "/sys/bus/w1/devices/28-000004e12842/w1_slave",
  "/sys/bus/w1/devices/28-000004e1378f/w1_slave",
  "/sys/bus/w1/devices/28-000004e1485c/w1_slave",
  "/sys/bus/w1/devices/28-000004e24d48/w1_slave"
)

# read sensor data
data = 'N'
for path in pathes:
  data += ':'
  data += read_sensor(path)
  i =  read_sensor(path) # Zu Debugzwecken - diese Zeile sollte wieder raus da hier die Sensoren nochmals abgefragt werden!
  print i
  time.sleep(1)

data += ':'
bypass = open("/sys/class/gpio/gpio10/value", "r")
bypassline = bypass.readline().rstrip()
bypass.close()
data += bypassline

print data
# insert data into round-robin-database
rrdtool.update(
  "/mnt/ramdisk/kwl.rrd",
  data)

Wenn ich das Skript wie oben stehend ausführe erhalte ich durch print die Ausgabe:

12.562
20.437
19.187
15.25
N:12.5:20.437:19.125:15.25:1



Ziel ist es später eine Ausgabe

Code: Alles auswählen

N:12.5:20.437:19.125:15.25:1:83.42
zu erhalten.

12.562 (data[1])
20.437 (data[2])
19.187 (data[3])
15.25 (data[4])
83.42 (errechnet durch die Formel data[3] - data[1]) / (data[2] - data[3]) *100
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui... das Script ist an vielen Stellen eher gruselig.

Also erst einmal ist es ein Problem, dass das Script die Rückgabewerte als Strings erfasst. Du willst aber mit etwas rechnen, also müsstest Du die Ergebnisse aus Zeile 34 erst einmal wieder in Strings konvertieren. Dazu musst Du die Zeile umformulieren, damit Du an das Ergebnis herankommst, bevor es mit dem bestehenden String konkateniert wird. Dann könntest Du das in einen ``float``-Wert wandeln und eine Funktion schreiben, die die Formel berechnet und das Ergebnis zurückliefert. Mit dem Ergebnis kannst Du dann tun und lassen, was Du willst.

Aber... das ist streng genommen nur Flickschusterei! Ich würde mich an die Kernprobleme wagen und diese beheben! Damit wird es nämlich ungleich einfacher, leserlicher und idiomatischer... und zwar, indem man die Daten und die *Ausgabe* der Daten trennt! ``read_sensor`` könnte sehr wohl einfach einen Zahlenwert zurückliefern und diese Werte könnte man erst einmal sammeln, z.B. in einer Liste. Nach dem Abarbeiten aller Sensoren, kann man diese Daten dann zu Berechnungen verwenden und diese ebenso in das gewünschte Format für das Speichern in der Datei bringen. Dazu kann man dann auch die idiomatisch richtigen Mittel zum Erstellen von Strings nutzen, anstelle von ``+``.

- Nach Zeile 4 die Funktion definieren:

Code: Alles auswählen

# Namen musst Du selber ggf. übersetzen ;-)
def calc_efficiency(zulufttemperatur, frischlufttemperatur, ablufttemperatur):
    return # hier die Formel rein
- Also in Zeile 16 musst Du nur das ``str`` um die Berechnung entfernen.
- Anstelle von Zeile 31 dann dieses hier (ungetestet):

Code: Alles auswählen

results = []
for path in pathes:
    results.append(read_sensor(path))
    time.sleep(1)

# jetzt können wir die Werte zur Berechnung nutzen:
#(Du hast in Deiner Formel oben einen Dreher; 
# der Index 3 taucht anders doppelt auf, als "Frischluft")
# k.A. was da nun richtig ist
efficiency = calc_efficiency(results[3], results[1], results[2])

# und nun daraus das Ausgabeformat bauen:
data = "N:{}:{}:".format(":".join(str(value) for value in results), efficiency)
- und dann ab Zeile 40 weiter wie gehabt.

Ganz generell sollte Python-Code übrigens immer mit *vier* Spaces pro Ebene eingerückt werden; nicht mit zwei wie bei dem von Dir gezeigten.

Wenn man das wirklich entrümpeln will, so müsste man mal allen Code von Modulebene in Funktionen verfrachten und ggf. noch einmal die Struktur der Sensoren überdenken; vermutlich könnte man den Namen des Sensors besser mit der Bedeutung des Messwertes in Einklang bringen, etwa über ein Dictionary oder ähnliches. Dazu kommen dann lauter Kleinigkeiten, wie das Nutzen von ``with`` bei Dateioperationen usw.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Thombo
User
Beiträge: 3
Registriert: Mittwoch 20. August 2014, 19:11

Hallo Hyperion,

vielen Dank für deine schnelle Hilfe :D
Ich habe das Skript mit deinen Infos angepasst - das Skript macht erstmal was ich erreichen wollte. Top!

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import re, os, rrdtool, time




def calc_efficiency(zulufttemperatur, frischlufttemperatur, ablufttemperatur):
    dothemath = ((zulufttemperatur - frischlufttemperatur) / (ablufttemperatur - frischlufttemperatur)) * 100
    print dothemath
    return dothemath


# function: read and parse sensor data file
def read_sensor(path):
  value = "U"
  try:
    f = open(path, "r")
    line = f.readline()
    if re.match(r"([0-9a-f]{2} ){9}: crc=[0-9a-f]{2} YES", line):
      line = f.readline()
      m = re.match(r"([0-9a-f]{2} ){9}t=([+-]?[0-9]+)", line)
      if m:
        value = (float(m.group(2)) / 1000.0)
    f.close()
  except (IOError), e:
    print time.strftime("%x %X"), "Error reading", path, ": ", e
  return value

# define pathes to 1-wire sensor data
pathes = (
  "/sys/bus/w1/devices/28-000004e12842/w1_slave",
  "/sys/bus/w1/devices/28-000004e1378f/w1_slave",
  "/sys/bus/w1/devices/28-000004e1485c/w1_slave",
  "/sys/bus/w1/devices/28-000004e24d48/w1_slave"
)

# read sensor data
results = []
data = 'N'
#for i in range(4):
for path in pathes:
    results.append(read_sensor(path))
    time.sleep(1)

#data += ':'
bypass = open("/sys/class/gpio/gpio10/value", "r")
bypassline = bypass.readline().rstrip()
bypass.close()

efficiency = calc_efficiency(results[2], results[0], results[1])
print "Effizienz " + str(efficiency)

#data += bypassline
data = "N:{}:{}:".format(":".join(str(value) for value in results),bypassline)
#data +=  bypassline
data +=  str(efficiency)

print data
# insert data into round-robin-database
rrdtool.update(
  "/mnt/ramdisk/kwl.rrd",
  data)
Das nächste wird es sein auf dem "dreckigen" Skript eins zu machen welches nicht so "gruselig" ist. Der Grundgedanke ist mir nun klar. Nochmals vielen Dank.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Thombo:
Ich muss mal kurz hinterfragen, was Du mit Deiner Wirkungsgradformel bezwecken willst. Thermodynamik liegt bei mir zwar schon Jahre zurück, aber sofern ich mich erinnere, ist doch der Wirkungsgrad definiert als Quotient der abgegebenen Leistung zur aufgenommenen (bzw. Energie). Differenz ist die Verlustleistung/-energie, die z.B. als thermische Energie nicht weiter nutzbar ist im Rahmen des zugrundeliegenden Energieumwandlungsprozesses.
Wie will man das auf eine CPU übertragen? Bei einer CPU dürfte die Verlustleistung gleich der Leistungsaufnahme sein, da es keine primär erwünschte abzugebende Energieform gibt - sprich Wirkungsgrad einer CPU ist 0%.

Falls ich Dich hier missverstanden habe und Du schauen möchtest, ob Dein Luftstrom die thermische Energie zur Genüge wegschaufelt - dafür fehlt Dir in Deiner Betrachtung das Luftvolumen pro Zeit.
Thombo
User
Beiträge: 3
Registriert: Mittwoch 20. August 2014, 19:11

@jerch

es geht um die annähernde Effizienzermittlung der Wärmerückgewinnung meiner KWL Anlage.
Die KWL Anlage saugt immer Frischluft (von draußen) in unser Haus, und bläst die verbrauchte Luft aus dem Haus.
Damit dadurch (vor allen in kalten Jahreszeiten) nicht saukalte rein- und warme Luft ausgeblasen wird, wird die (kalte) einströmende Luft durch die ausströmende (warme) Luft vorerwärmt.
Und wie effizient das ist berechnet die Formel ;-)

Nichts mit CPU und so...
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Thombo:
Oh entschuldige - das mit der KWL Anlage hatte ich übersehen.
Antworten