Günstig Temperatur, Luftfeuchte und Energie messen mit Raspberry Pi oder PC

Drahtloses Anbinden von Temperatursensoren und Energiemesser. Und das noch günstig. Sehr hilfreich war dieser Beitrag. Er beschreibt die Anbindung von drahtlosen Sensoren an Fhem. Fhem wollte ich jetzt (noch) nicht aufsetzen, deshalb realisierte ich meine eigene Anbindung in der die Temperaturkurven auf dem Webserver des Raspi angezeigt werden.Bildschirmfoto 2014-03-19 um 21.28.26

Zutaten: Ein Raspi (kann aber auch ein NAS, PC oder Mac sein). Ein Jeelink (arduino mit 868 MHz Sender/Empfänger auf einem USB-Stick) (Versand dauert ca. 4 Tage). Einen (oder mehrere, ich habe inzwischen 7) passende Temperatursensoren. (Gibt es auch mit Luftfeuchtemesser).

Verarbeitung: Der Jeelink muss mit dem passenden Sketch bestückt werden. Danach lauscht er nach senden Thermostationen und gibt das Ergebnis über seine serielle Schnittstelle aus. Zum Auslesen habe ich mir folgendes Perl-Script erstellt (alpha):

#!/usr/bin/perl
$|++;

# LaCrosse auslesen
# Interpretation:
# OK
# 9
# 1 Byte: addr
# 1 Byte: battery, type, channel
# 2 Byte: temperature 
# 1 Byte: battery_low, humidity

use strict;
use warnings;

use Device::SerialPort;

my $device1 = 'F0'; 
my $device2 = '68'; 
my $device3 = 'E0'; 
my $device4 = 'CC'; 
my $device5 = '58'; 
my $device6 = 'D4'; # Fensterbrett war 38
my $device7 = '54'; 
my $device8 = 'DC'; 
my $device9 = '94'; 

my $port;
my %devices = ($device1 => 'n', $device2 => 'n', $device3 => 'n', $device4 => 'n', $device5 => 'n', $device6 => 'n', $device7 => 'n', $device8 => 'n', $device9 => 'n');
	my $sec;
	my $min;
	my $hour;
	my $mday;
	my $mon;
	my $year;
	my $wday;
	my $yday;
	my $isdst;
	my @myvalues;
	my $hygro;

 sub check_output{

     my $answer;
     my $answer1;
     # my( @bytes, $channel,$cmd,$addr,$data,$power,$consumption );
     my( @bytes, $addr, $battery_new, $type, $channel, $temperature, $battery_low, $humidity ); 
      my $state;
      my $readonly;

	my @array;
	my $len;

 while(1){    
	print STDERR "wait for read\n";
    $answer1 = $port->read(255);
   	print STDERR "\n>" . $answer1 . "<-\n";

	#print "read\n";
    if ($answer1 ne "") {
    	$answer = $answer . $answer1;
    	#print "\n>" . $answer . "<\n";
		if( $answer =~ m/^OK.*\n/ ) {
			last;
		}
		$len = length($answer);    	
		if ($answer ne "" && $len > 1000){ #something went wrong
			print STDERR "---- delete length $len too long----\n";
			print STDERR ">" . $answer . "<\n";
			$answer = "";
			}
		if (length($answer) >= 2){
			if (substr($answer, 0, 2) ne "OK"){ #something went wrong
				print  STDERR  "---- delete wrong start----\n";
				$answer = "";
				}
			}

    }
    sleep(2);
}
#Falls mehrere Zeilen geliefert werden, 
@array=split(/\n/, $answer);

foreach (@array){
$answer = $_;
#  if( $answer =~ m/^OK.*\n/ ) {
  if( $answer =~ m/OK 9 \d+ \d+ \d+ \d+ \d+/ ) {
    @bytes = split( ' ', substr($answer, 5) );

 $addr = sprintf( "%02X", $bytes[0] );
$battery_new = ($bytes[1] & 0x80) >> 7;
$type = ($bytes[1] & 0x70) >> 4;
$channel = $bytes[1] & 0x0F;
$temperature = ($bytes[2]*256 + $bytes[3] - 1000)/10;
$battery_low = ($bytes[4] & 0x80) >> 7;
$humidity = $bytes[4] & 0x7f; 

 # we simply write the temperatur at the hash
	print STDERR "Adr: " . $addr;
    print STDERR " Batt_new: " . $battery_new;
    print STDERR " Type: " . $type;
    print STDERR " Chan: " . $channel;
    print STDERR " Temp: " . $temperature;
    print STDERR " Batt_low: " . $battery_low;
    print STDERR " Hum: " . $humidity . "\n";
  $devices{$addr} = $temperature;
  if ($addr eq 'E0'){
  	$hygro = $humidity;
  }

  #Wenn neue Adresse, dann hier ausgeben

    $answer ="";

} 

 }#for each
}  # sub check_output

# -------------
# Hauptprogramm

    # Set up the serial port
    #print "Start\n";

    $port = Device::SerialPort->new("/dev/ttyUSB0");
#    $port = Device::SerialPort->new("/dev/tty.usbserial-AM01YRW0");

    # 19200, 81N on the USB ftdi driver
    $port->baudrate(57600); # you may change this value
    $port->databits(8); # but not this and the two following
    $port->parity("none");
    $port->stopbits(1);
    $port-> write_settings;
    $port-> lookclear;
     #print "start";

my $i;
$i = 7;        
while($i > 0){    

print STDERR "Durchlauf Nr: $i \n";

$port-> lookclear;
sleep(4);
check_output();

$i = $i -1;

#sleep(900);
#exit;

#debug

 # output block; put at the end
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
    $mon = $mon +1;
    $mon = sprintf("%02d", $mon);
    $mday = sprintf("%02d", $mday);
    $hour = sprintf("%02d", $hour);
    $min = sprintf("%02d", $min);
    $sec = sprintf("%02d", $sec);
    $year = $year + 1900;
	#@myvalues = values %devices;

# ToDo Aufräumen, muss auch weiterlaufen wenn bei einem Gerät die Batterie leer ist	
if  ($devices{$device1} eq "n") {
 print STDERR "na 1  $device1 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device2} eq "n") {
 print STDERR "na 2  $device2 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device3} eq "n") {
 print STDERR "na 3  $device3 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device4} eq "n") {
 print STDERR "na 4  $device4 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device5} eq "n") {
 print STDERR "na 5  $device5 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device6} eq "n") {
 print STDERR "na 6  $device6 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device7} eq "n") {
 print STDERR "na 7 $device7 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device7} eq "n") {
 print STDERR "na 8 $device8 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device9} eq "n") {
 print STDERR "na 9 $device9 nicht gefunden\n";
 sleep(4);
 next;
}
	print "$year-$mon-$mday" . "_" . "$hour:$min:$sec";
	print " $devices{$device1}";
	print " $devices{$device2}";
	print " $devices{$device3}";
	print " $hygro";
	print " $devices{$device4}";
	print " $devices{$device5}";
	print " $devices{$device6}";
	print " $devices{$device7}";
	print " $devices{$device8}";
	print " $devices{$device9}";
	print "\n";
 # output block; put at the end

 #nochmal alle aufzaehlen
 print STDERR "Alle erfolgreich gefunden\n";

exit;

$i = $i -1;
sleep(58);
     #print "slept";

 }
    print STDERR "Abbruch nicht genug gefunden\n";
 	print "$year-$mon-$mday" . "_" . "$hour:$min:$sec";
	print " $devices{$device1}";
	print " $devices{$device2}";
	print " $devices{$device3}";
	print " $hygro";
	print " $devices{$device4}";
	print " $devices{$device5}";
	print " $devices{$device6}";
	print " $devices{$device7}";
	print " $devices{$device8}";
	print " $devices{$device9}";
	print "\n";

Dazu noch einen cronjob, der die ausgabe des Perl-scripts parst durch gnuplot schickt und die entstandene Grafikdatei auf den Webserver schiebt. – Fertig.

Detaillierend zu Sebastians Frage:

Die Ausgabedatei sieht z.B. ungefähr so aus (Pro Zeile Datum, Uhrzeit, dann die Werte mit blank getrennt n wenn kein Wert).:

2020-08-18_02:21:17 33.7 n 24.8 61 n -19 n 11.5 21.7 25.4 22 80 23.5 76 25.5 64 25.4 63 17.4 n 26.5 25.2 25.5 26 26 23.1 71 24.2 66 24.4 61
2020-08-18_02:31:18 33.7 n 24.8 61 n -18.9 n 11.4 21.6 25.4 22 79 23.5 76 25.5 64 n n 17.4 n 26.5 25.2 25.5 26 25.9 23.1 71 24.1 66 24.4 61
2020-08-18_02:41:14 33.7 n 24.8 61 n -19 n 11.4 21.6 25.4 22 79 23.5 76 25.5 64 25.4 63 17.2 n 26.4 25.2 25.5 26 25.9 23.1 71 24.1 66 24.4 61
2020-08-18_02:51:18 33.7 n 24.8 61 n -18.9 n 11.4 21.6 25.4 22 79 23.5 76 25.5 64 25.4 63 17.2 n 26.4 25.2 25.4 26 25.9 23 71 24.1 66 24.3 60

Darauf kann mann dann den gnuplot loslassen mit dem Befehl “gnuplot datei”. Die Datei steuert den gnuplot und kann z.B. so aussehen:


set key left #legende nach links
set xtics rotate
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set format x "%d. %Hh"
set grid
set title "Johannes Temp Small Monitor"
set ylabel "C"
set xlabel "\n1 hour interval"
set terminal gif small size 800, 440 transparent
set output "/home/pi/bin/tc2small.gif"

plot "/home/pi/bin/temperatureout.txt" using 1:6 title "Sensor 1" with lines,\
"/home/pi/bin/temperatureout.txt" using 1:8 title "Sensor2" with lines, \
"/home/pi/bin/w4.txt" using 1:2 title "OpenWeather" with lines, \
"/home/pi/bin/weatherout_wunder3.txt" using 1:2 title "Wunderground" with lines

die entstandene gif Datei schiebe ich dann mittels ftp auf den Webserver.

Mittlerweile schreibe ich parallel dazu die Daten in eine mysql Datenbank und erstelle mittels Grafana die Auswertung. Das schaut dann ca. so aus wie unten.

 

Wie verbindet man den Jeelink mit dem Raspberry PI: link

2 thoughts on “Günstig Temperatur, Luftfeuchte und Energie messen mit Raspberry Pi oder PC

  1. Hallo Johannes, interessanter Beitrag. Bisher verwende ich den Jeelink, die Technoline-Sensoren und FHEM. Würde auch gerne auf eine reine scriptbasierte Ausgabe der Daten (und ggf. das Speichern in einer MySQL-Datenbank) umsteigen. Kannst du bitte “Dazu noch einen cronjob, der die ausgabe des Perl-scripts parst durch gnuplot schickt und die entstandene Grafikdatei auf den Webserver schiebt.” etwas genauer beschreiben? Danke und viele Grüße, Sebastian

Leave a Reply

Your email address will not be published. Required fields are marked *