Sonntag, 6. November 2016

Raspberry Pi, Temperatur, Luftfeuchtigkeit, rrdtool, gnuplot zur Raumklimaüberwachung (Bewertung Schimmelgefahr)

Vorab, der Post ist inkomplett und beschreibt noch nicht vollständig und umfassend alle Schritte in Hardware und Software, die ich durchgeführt habe. Möglicherweise wird es auch nie komplett werden. Vielleicht sind aber die Fragmente auch so hilfreich.



Die H/W:

  • Raspberry Pi 2 Modell B 1GB
  • fitTek DHT22/AM2302 digital Sensor Feuchtigkeit Temperatur
  • Digital Temperaturfühler Temperatur Sensor DS18b20
  • Zwei 10 kOhm Widerstand 
Die Verkabelung (abgebildet ist ein RasPi3, der aber die gleichen Pinbelegung wie der RasPi2 hat):
  • schwarz: GND
  • rot: +3,3 V
  • blau: GPIO4
  • lila: GPIO5 


Der DHT22 misst Lufttemperatur und relative Luftfeuchtigkeit. Der DS18b20 ist an der Wand montiert und misst die Wandtemperatur.


Die S/W:

Achtung, die Dateirechte der verschiedenen Dateien müssen richtig gesetzt sein, sonst funktioniert es nicht!
 

Das Erstellen der rrd-Datenbank (einmalig)


rrdtool create temphumid.rrd \
        --start [Zahl] \ #Zeit seit Epoche in sekunden
        --step 300 \     #Sekunden (Update Intervall)
        DS:tluft:GAUGE:600:-50:100 \
        DS:ttaupunkt:GAUGE:600:-50:100 \
        DS:ttaupunktwc:GAUGE:600:-50:100 \
        DS:twandwc:GAUGE:600:-50:100 \
        DS:twand:GAUGE:600:-50:100 \
        DS:relhumidity:GAUGE:600:0:100 \
        RRA:AVERAGE:0.5:1:288 \
        RRA:MIN:0.5:1:288 \
        RRA:MAX:0.5:1:288 \
        RRA:AVERAGE:0.5:72:124 \
        RRA:MIN:0.5:72:124 \
        RRA:MAX:0.5:72:124 \
        RRA:AVERAGE:0.5:2016:52 \
        RRA:MIN:0.5:2016:52 \
        RRA:MAX:0.5:2016:52

Erklärung der RRA-Zeilen:
1 x 300s = 5 min
300s x 288 = 86 400s = 24h
1 Datenpunkt pro 5 Minuten für einen Tag (24h)
 

72 x 300s = 21 600 s = 6 h
6h x 124 = 744 h = 31 Tage
1 Datenpunkt pro 6 Stunden für einen Monat
 

2016 x 300s = 1w
1w x 52 = 1a
1 Datenpunkt pro Woche für ein Jahr

Datenbankgröße: 73700 Bytes

Das Auslesen der Sensor-Daten

geschieht über ein kleines python-Script, dass über einen cron-job alle 5 Minuten (=300s) aufgerufen wird.

/home/pi/Schimmel_Pi.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
import Adafruit_DHT
import glob
import time
import os
import subprocess
import rrdtool

# Genauigkeit des AM2302-Sensors (Kombi Temp/Luftfeuchte) laut Datenblatt
TluftAccuracy = 1        # +/-1 °C
RelFeuchtAccuracy = .02  # +/-2 %

# Genauigkeit des DS18B20-Sensors laut Datenblatt
TwandAccuracy = .5       # +/- 0.5 °C


# Initialisierung der Pfade für Auslesen des DS18B20
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'


# Funktionen für DS18B20 Sensor
def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines


def read_temp():
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos + 2:]
        temp_c = float(temp_string) / 1000
        return temp_c


# Berechnungsfunktionen
def DewPoint(Tluft, RelFeucht):
    "Berechnung des Taupunkts aus Lufttemperatur und rel. Luftfeuchtigkeit"
    # Definition von Variablen zur Berechnung des Taupunkts
    # für den Temperaturbereich -45°C bis 60 ° C
    # K1 = 6.112  # hPa
    K2 = 17.62
    K3 = 243.12  # °C

    # Berechnung des Taupunkts
    DewPoint = K3 * ((K2 * Tluft) / (K3 + Tluft) + math.log(RelFeucht)) / \
    (((K2 * K3) / (K3 + Tluft)) - math.log(RelFeucht))

    return DewPoint


# Textdatei oeffnen
fobj_out = open("/home/pi/TempHumidity-daten.txt", "a")

# Zeit und Datum erfassen
Datum = time.strftime("%d.%m.%Y")
Uhrzeit = time.strftime("%H:%M:%S")

# Auslesen des DHT22/AM2302 Sensors ("22""), der auf GPIO5 ("5")
# angeschlossen ist
humidity, temperature = Adafruit_DHT.read_retry(22, 5)
RelFeucht = humidity / 100
Tluft = temperature

# Auslesen des DS18B20 Sensors
Twand = read_temp()
TwandWorstCase = Twand - TwandAccuracy

#Berechnung Taupunkt
Taupunkt = DewPoint(Tluft, RelFeucht)
TaupunktWorstCase = DewPoint(Tluft + TluftAccuracy,
                             RelFeucht + RelFeuchtAccuracy)

## Ausgabe
#print("Lufttemperatur:               {0:.1f} °C".format(Tluft))
#print("Rel. Feuchtigkeit:            {0:.1f} %".format(RelFeucht * 100))
#print("Wandtemperatur:               {0:.1f} °C".format(Twand))
#print("Wandtemperatur (incl. Fehler):{0:.1f} °C".format(TwandWorstCase))
#print("Taupunkt                      {0:.1f} °C".format(Taupunkt))
#print("Taupunkt (incl. Messfehler)   {0:.1f} °C".format(TaupunktWorstCase))

#if Twand <= Taupunkt:
    #print("Achtung! Schimmelgefahr!!!!")
#elif TwandWorstCase <= TaupunktWorstCase:
    #print("Grenzwertig Schimmelbildung möglich!")
#else:
    #print("Keine Schimmelgefahr")

# Ausgabe in Datei
fobj_out.write(Datum + " " + Uhrzeit + "\t"
               + '%5.1f' % Tluft + "\t"
               + '%5.1f' % Taupunkt + "\t"
               + '%5.1f' % TaupunktWorstCase + "\t"
               + '%5.1f' % TwandWorstCase + "\t"
               + '%5.1f' % Twand + "\t"
               + '%5.1f %%' % (RelFeucht * 100) + "\n")

fobj_out.close()

# Ausgabe in rrd-Datenbank
ret = rrdtool.update('/home/pi/temphumid.rrd','N:%s:%s:%s:%s:%s:%s' %(Tluft, Taupunkt, TaupunktWorstCase, TwandWorstCase, Twand, (RelFeucht * 100))) ;
if ret:
 print rrdtool.error()

#p = subprocess.Popen("/usr/bin/gnuplot /home/pi/GnuPlotTempHumidity.plt",
#     shell=True)
#os.waitpid(p.pid, 0)



cronjob mit root-Privilegien (wegen Sensor-Auslesen)

*/5 * * * * /usr/bin/python /home/pi/Schimmel_Pi.py > /home/pi/cron-python.log

 

Die Ausgabe(über Webserver)

Ausgabe der rrd-Daten

/var/www/html/index_rrd.php


<!doctype html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Raumklima</title>
  </head>
  <body>

   <?php

    create_graph("/var/www/html/Raumklima24h.svg", "-1d", "Raumklima letzte 24h");
    create_graph("/var/www/html/Raumklima1w.svg", "-1w", "Raumklima letzte Woche");
    create_graph("/var/www/html/Raumklima1a.svg", "-52w", "Raumklima letztes Jahr");

       function create_graph($graphikdatei_out,$startzeit,$title){
        $options = array(
        "--imgformat=SVG",
        "--disable-rrdtool-tag",
        "--slope-mode",
        "--start", $startzeit,
        "--title", $title,
        "--vertical-label=Temperatur",
        "DEF:tluft=/home/pi/temphumid.rrd:tluft:AVERAGE",
        "DEF:tluftmin=/home/pi/temphumid.rrd:tluft:MIN",
        "DEF:tluftmax=/home/pi/temphumid.rrd:tluft:MAX",
        "CDEF:tluftAREA=tluft,tluftmin,-",
        "CDEF:tluftmaxAREA=tluftmax,tluft,-",
        "DEF:twand=/home/pi/temphumid.rrd:twand:AVERAGE",
        "DEF:twandwc=/home/pi/temphumid.rrd:twandwc:AVERAGE",
        "CDEF:twandwcAREA=twand,twandwc,-",
        "DEF:ttaupunkt=/home/pi/temphumid.rrd:ttaupunkt:AVERAGE",
        "DEF:ttaupunktwc=/home/pi/temphumid.rrd:ttaupunktwc:AVERAGE",
        "CDEF:ttauwcAREA=ttaupunktwc,ttaupunkt,-",
        "VDEF:tluft_aktuell=tluft,LAST",
        "VDEF:twand_aktuell=twand,LAST",
        "VDEF:ttaupunkt_aktuell=ttaupunkt,LAST",
        "VDEF:tluft_min=tluftmin,MINIMUM",
        "LINE1:tluft#cb2424:Lufttemperatur",
        "LINE1:tluftmin",
        "AREA:tluftAREA#fe2e2e80::STACK",
        "AREA:tluftmaxAREA#b6202080::STACK",
        "LINE1:twand#01df01:Wandtemperatur",
        "LINE1:twandwc",
        "AREA:twandwcAREA#01df0180::STACK",
        "LINE1:ttaupunkt#08088a:Taupunkt",
        "AREA:ttauwcAREA#08088a80::STACK",
        "COMMENT:\s",
        "COMMENT:\s",
        "GPRINT:tluft_aktuell:aktuelle Lufttemperatur\: %10.2lf °C",
        "GPRINT:twand_aktuell:aktuelle Wandtemperatur\: %10.2lf °C",
        "GPRINT:ttaupunkt_aktuell:aktueller Taupunkt\:      %10.2lf °C"
        );

        $optionsRelHum = array(
        "--imgformat=SVG",
        "--disable-rrdtool-tag",
        "--slope-mode",
        "--start", $startzeit,
        "--title", $title,
        "--vertical-label=relative Luftfeuchtigkeit",
        "--watermark", `date '+%A %d.%m.%Y %H:%M %Z'`,
        "DEF:relhumidity=/home/pi/temphumid.rrd:relhumidity:AVERAGE",
        "DEF:relhumiditymin=/home/pi/temphumid.rrd:relhumidity:MIN",
        "DEF:relhumiditymax=/home/pi/temphumid.rrd:relhumidity:MAX",
        "CDEF:relhumAREA=relhumidity,relhumiditymin,-",
        "CDEF:relhummaxAREA=relhumiditymax,relhumidity,-",
        "VDEF:relhum_absmin=relhumiditymin,MINIMUM",
        "VDEF:relhum_absmax=relhumiditymax,MAXIMUM",
        "VDEF:relhum_aktuell=relhumidity,LAST",
        "LINE1:relhumidity#005b96:Luftfeuchtigkeit",
        "LINE1:relhumiditymin#b3cde0:min. Luftfeuchtigkeit",
        "AREA:relhumAREA#6497b180::STACK",
        "AREA:relhummaxAREA#03396c80::STACK",
        "LINE1:relhumiditymax#011f4b:max. Luftfeuchtigkeit",
        "COMMENT:\s",
        "COMMENT:\s",
        "GPRINT:relhum_absmax:maximale Luftfeuchtigkeit\: %10.2lf %%",
        "GPRINT:relhum_aktuell:aktuelle Luftfeuchtigkeit\: %10.2lf %%",
        "GPRINT:relhum_absmin:minimale Luftfeuchtigkeit\: %10.2lf %%"
        );

      $relhum_out = substr($graphikdatei_out,0,-4) . "RelHum.svg";

      $ret = rrd_graph($graphikdatei_out, $options);
      if (! $ret) {
        echo "<b>Graph error: </b>".rrd_error()."\n";
        }

      $ret = rrd_graph($relhum_out, $optionsRelHum);
      if (! $ret) {
        echo "<b>Graph error: </b>".rrd_error()."\n";
        }

      }
    ?>


   <h1>Letzter Tag</h1>
   <img src="Raumklima24h.svg" alt="Temperatur-Graphik der letzten 24 h">
   <img src="Raumklima24hRelHum.svg" alt="Rel.Feuchtigkeits-Graphik der letzten 24 h">
   <h1>Letzte Woche</h1>
   <img src="Raumklima1w.svg" alt="Temperatur-Graphik der letzten Woche">
   <img src="Raumklima1wRelHum.svg" alt="Rel.Feuchtigkeits-Graphik der letzten Woche">
   <h1>Letztes Jahr</h1>
   <img src="Raumklima1a.svg" alt="Temperatur-Graphik des letzten Jahres">
   <img src="Raumklima1aRelHum.svg" alt="Rel.Feuchtigkeits-Graphik des letzten Jahres">
<!--   <h1>Letzter Tag</h1>
   <?php exec('/usr/bin/gnuplot /var/www/html/GnuPlotTempHumidity_last24h.plt'); ?>
   <img src="TempHumidity_last24h.svg" alt="Temperatur und Rel.Feuchtigkeits-Graphik der letzten 24 h">
   <h1>Letzte Woche</h1>
   <?php exec('/usr/bin/gnuplot /var/www/html/GnuPlotTempHumidity_last7d.plt'); ?>
   <img src="TempHumidity_last7d.svg" alt="Temperatur und Rel.Feuchtigkeits-Graphik der letzten Woche">
   <h1>Gesamt</h1> -->
  </body>
</html>
Beispielausgabe rrdtool

 

Ausgabe der nicht reduzierten Daten mit gnuplot

Achtung, Rechenzeit steigt mit wachsender Dateigröße!

/var/www/html/index_gnuplot.php

<!doctype html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Raumklima</title>
  </head>
  <body>
   <h1>Letzter Tag</h1>
   <?php exec('/usr/bin/gnuplot /var/www/html/GnuPlotTempHumidity_last24h.plt'); ?>
   <img src="TempHumidity_last24h.svg" alt="Temperatur und Rel.Feuchtigkeits-Graphik der letzten 24 h">
   <h1>Letzte Woche</h1>
   <?php exec('/usr/bin/gnuplot /var/www/html/GnuPlotTempHumidity_last7d.plt'); ?>
   <img src="TempHumidity_last7d.svg" alt="Temperatur und Rel.Feuchtigkeits-Graphik der letzten Woche">
   <h1>Gesamt</h1>
   <?php exec('/usr/bin/gnuplot /var/www/html/GnuPlotTempHumidity_alles.plt'); ?>
   <img src="TempHumidity.svg" alt="Temperatur und Rel.Feuchtigkeits-Graphik (gesamter Datenbestand)">
  </body>
</html>
und die dazugehörigen gnuplot-Dateien:

/var/www/html/GnuPlotTempHumidity_last24h.plt

set terminal svg size 800,600
set output '/var/www/html/TempHumidity_last24h.svg'
system(sprintf("tail -n 288 /home/pi/TempHumidity-daten.txt > /tmp/TH-daten_last24h.txt"))

reset
fmt = "%d.%m.%Y %H:%M:%S"
fmt_sht = "%d.%m.%Y"
stats '/tmp/TH-daten_last24h.txt' u (strptime(fmt,strcol(1).strcol(2))) nooutput
timepoint_last = STATS_max
timepoint_24before = STATS_max - 60*60*24

#debug-output
#print timepoint_last
#print strftime(fmt,timepoint_last)
#print strftime(fmt,timepoint_24before)
#print STATS_records


set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"

set multiplot layout 2,1 title "Raumklima" font ",14"
set tmargin 2
#
set size 1,0.7
set origin 0,0.26
set title strftime(fmt_sht,timepoint_24before)."-".strftime(fmt_sht,timepoint_last)
set format x "%H:%M"
set grid
set style fill transparent solid 0.5 noborder
set ylabel "Temperatur [°C]"
set xlabel "Meßzeitpunkt"
set key bmargin center horizontal
set xrange [timepoint_24before:timepoint_last]
plot "/tmp/TH-daten_last24h.txt" using 1:3 with lines title "Lufttemperatur", \
     "/tmp/TH-daten_last24h.txt" using 1:6:7 with filledcurves notitle lc rgb "#bbffff",\
     "/tmp/TH-daten_last24h.txt" using 1:7 with lines title "Wandtemperatur", \
     "/tmp/TH-daten_last24h.txt" using 1:6 with lines title "Wandtemperatur (worst case)", \
     "/tmp/TH-daten_last24h.txt" using 1:5:4 with filledcurves notitle lc rgb "#ebebeb", \
     "/tmp/TH-daten_last24h.txt" using 1:5 with lines title "Taupunkt (worst case)", \
     "/tmp/TH-daten_last24h.txt" using 1:4 with lines title "Taupunkt"
#
set size 1,0.3
set origin 0,-0.03
set title "Rel. Feuchtigkeit"
set xdata time
set format x "%H:%M"
set timefmt "%d.%m.%Y %H:%M:%S"
set grid
set ylabel "Rel. Luftfeuchtigkeit [%]"
set xlabel "Meßzeitpunkt"
plot "/tmp/TH-daten_last24h.txt" using 1:8 with lines notitle

unset multiplot
und
/var/www/html/GnuPlotTempHumidity_last7d.plt

set terminal svg size 800,600
set output '/var/www/html/TempHumidity_last24h.svg'
system(sprintf("tail -n 288 /home/pi/TempHumidity-daten.txt > /tmp/TH-daten_last24h.txt"))

reset
fmt = "%d.%m.%Y %H:%M:%S"
fmt_sht = "%d.%m.%Y"
stats '/tmp/TH-daten_last24h.txt' u (strptime(fmt,strcol(1).strcol(2))) nooutput
timepoint_last = STATS_max
timepoint_24before = STATS_max - 60*60*24

#debug-output
#print timepoint_last
#print strftime(fmt,timepoint_last)
#print strftime(fmt,timepoint_24before)
#print STATS_records


set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"

set multiplot layout 2,1 title "Raumklima" font ",14"
set tmargin 2
#
set size 1,0.7
set origin 0,0.26
set title strftime(fmt_sht,timepoint_24before)."-".strftime(fmt_sht,timepoint_last)
set format x "%H:%M"
set grid
set style fill transparent solid 0.5 noborder
set ylabel "Temperatur [°C]"
set xlabel "Meßzeitpunkt"
set key bmargin center horizontal
set xrange [timepoint_24before:timepoint_last]
plot "/tmp/TH-daten_last24h.txt" using 1:3 with lines title "Lufttemperatur", \
     "/tmp/TH-daten_last24h.txt" using 1:6:7 with filledcurves notitle lc rgb "#bbffff",\
     "/tmp/TH-daten_last24h.txt" using 1:7 with lines title "Wandtemperatur", \
     "/tmp/TH-daten_last24h.txt" using 1:6 with lines title "Wandtemperatur (worst case)", \
     "/tmp/TH-daten_last24h.txt" using 1:5:4 with filledcurves notitle lc rgb "#ebebeb", \
     "/tmp/TH-daten_last24h.txt" using 1:5 with lines title "Taupunkt (worst case)", \
     "/tmp/TH-daten_last24h.txt" using 1:4 with lines title "Taupunkt"
#
set size 1,0.3
set origin 0,-0.03
set title "Rel. Feuchtigkeit"
set xdata time
set format x "%H:%M"
set timefmt "%d.%m.%Y %H:%M:%S"
set grid
set ylabel "Rel. Luftfeuchtigkeit [%]"
set xlabel "Meßzeitpunkt"
plot "/tmp/TH-daten_last24h.txt" using 1:8 with lines notitle

unset multiplot
und
/var/www/html/GnuPlotTempHumidity_alles.plt


set terminal svg size 800,600
set output '/var/www/html/TempHumidity.svg'

reset
fmt = "%d.%m.%Y %H:%M:%S"
fmt_sht = "%d.%m.%Y"
stats '/home/pi/TempHumidity-daten.txt' u (strptime(fmt,strcol(1).strcol(2))) nooutput
timepoint_last = STATS_max
timepoint_first = STATS_min

set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"

set multiplot layout 2,1 title "Raumklima" font ",14"
set tmargin 2
#
set size 1,0.7
set origin 0,0.26
set title strftime(fmt_sht,timepoint_first)."-".strftime(fmt_sht,timepoint_last)
set format x "%d.%m\n%H:%M"
set grid
set style fill transparent solid 0.5 noborder
set ylabel "Temperatur [°C]"
set xlabel "Meßzeitpunkt"
set key bmargin center horizontal
#set xrange [timepoint_7Tbefore:timepoint_last]
plot "/home/pi/TempHumidity-daten.txt" using 1:3 with lines title "Lufttemperatur", \
     "/home/pi/TempHumidity-daten.txt" using 1:6:7 with filledcurves notitle lc rgb "#bbffff",\
     "/home/pi/TempHumidity-daten.txt" using 1:7 with lines title "Wandtemperatur", \
     "/home/pi/TempHumidity-daten.txt" using 1:6 with lines title "Wandtemperatur (worst case)", \
     "/home/pi/TempHumidity-daten.txt" using 1:5:4 with filledcurves notitle lc rgb "#ebebeb", \
     "/home/pi/TempHumidity-daten.txt" using 1:5 with lines title "Taupunkt (worst case)", \
     "/home/pi/TempHumidity-daten.txt" using 1:4 with lines title "Taupunkt"
#
set size 1,0.3
set origin 0,-0.03
set title "Rel. Feuchtigkeit"
set xdata time
#set format x "%d.%m"
set timefmt "%d.%m.%Y %H:%M:%S"
set grid
set ylabel "Rel. Luftfeuchtigkeit [%]"
set xlabel "Meßzeitpunkt"
plot "/home/pi/TempHumidity-daten.txt" using 1:8 with lines notitle

unset multiplot

Keine Kommentare: