Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:sensors:1_wire

Dallas 1-wire Sensoren

Derzeit haben wir mehrere Möglichkeiten 1-Wire Sensoren auszulesen.

Raspberrypi

Den Raspberrypi kann man gut zum Einlesen der Sensoren verwenden. Ich benutzt hierzu zwei Raspberrypi, einen für die Datenbank und einen für die Temperatursensoren. Es ist eine blöde Idee einen Rapberry als Datenbankserver zu nehmen, ich hatte jetzt schon 2 SD-Karten-Schäden innerhalb von 4 Monaten.

Raspberry Pi-Erweiterung_klein
Raspberry Pi-Erweiterung_groß
http://www.raspiprojekt.de/anleitungen/schaltungen/9-1wire-mit-temperatursensor-ds18b20.html

Bei mir musste zusätzlich das Script /etc/modules modufiziert werden:

# 1wire
w1-gpio   pullup=1  ( nicht bei den Raspberry Pi-Erweiterungen)
w1-therm

Eine Übersicht über die Sensoren bekommt man mit „ls /sys/bus/w1/devices/“.

Mit dem Befehl „cat /sys/bus/w1/devices/*/w1_slave“ kann man dann die Sensoren abfragen.

In der Datenbank des Volkszähler müssen die einzelnen Kanäle angelegt werden. Die Kanalnummer müssen dann in das script übernommen werden einrichtung.

Um das ganze dann in die Volkszählerdatenbank zu bekommen brauchen wir wieder perl:

„apt-get install libdevice-serialport-perl“

Das Abfragescript selber „get1wire.pl“, das Script mit „chmod ugo+x get1wire.pl“ ausführbar machen:

#!/usr/bin/perl

# welche werte sollen geholt werden?
my %Daten = (      # Name => [ Adresse onewire, uuid-Volkszaehler , Faktor ]
                        "WWKessel"   => ["28-0000022c2dd7", "834c8be0-293c-11e3-8abd-911b2ff9df4c" , 0.001] , # in GradC
                        "WWVorlauf"  => ["28-0000022bef46", "860f8b30-2940-11e3-92d2-b39a45aed701" , 0.001] , # in GradC
                        "HzRueckl"   => ["28-0000022bfba8", "793354f0-2941-11e3-8965-b9f953ac51a9" , 0.001] , # in GradC
                        "HzVorl"     => ["28-0000022bfbf2", "9482c580-2941-11e3-a953-0f05013168f3" , 0.001] , # in GradC
                        "Abgas"      => ["28-0000022c0f2d", "be748340-2941-11e3-8286-edbdc7c926b3" , 0.001] , # in GradC
                        "HzKessel"   => ["28-0000022c1388", "d96476a0-2941-11e3-81f9-27853072856e" , 0.001] , # in GradC
                        "WWRueckl"   => ["28-0000022c2742", "3336aa50-2942-11e3-8a3c-61212ee448b1" , 0.001] , # in GradC
                        "HzRaum"     => ["28-0000023cc9e7", "4e3a22c0-2942-11e3-af9b-1b95cbbaf179" , 0.001] , # in GradC
);


# ****************** Werte lesen
while (($name) = each(%Daten)){

  $addr = $Daten{$name}[0] ;
  $fak  = $Daten{$name}[2] ;

  # Abfragen
  $sensor_temp = `cat /sys/bus/w1/devices/${addr}/w1_slave 2>&1`;
  #print $sensor_temp ;

  # checken
  if ( !($sensor_temp =~ /\ YES/ ) ) {
    delete $Daten{$name};
    print "CRC == FALSE\n";
    next;                     #wieder zu while hochspringen
  }
  if ( ($sensor_temp =~ /85000/ ) ) { # t=85000 ist der defaultwert ohne Wandlung
    delete $Daten{$name};
    print "t=85000\n";
    next;                     #wieder zu while hochspringen
  }

  # decodieren
  $sensor_temp =~ /t=(\-?\d+)/i;    # ALT: geht nicht bei Minusgraden$sensor_temp =~ /t=(\d+)/i;

  $val = (($1*$fak)-0);

  if ($val == 0) {
    delete $Daten{$name};
    print "t=0\n";
    next;                     #wieder zu while hochspringen
  }


  # Wert im Hash ablegen
  $Daten{$name}[3] = $val ;

  # plotten
  print " --> $name = $val\n";

}
# ****************** Wert in die Datenbank schreiben
if (1) {

use LWP::UserAgent;

while (($name) = each(%Daten)){
    $uuid =  $Daten{$name}[1] ;
    $val =  $Daten{$name}[3] ;
    print $uuid . " : " . $val . "\n";


    my $server_endpoint = "http://rasp1/middleware.php/data/${uuid}.json?value=" . $val;
    #print "serverget = " .  $server_endpoint . "\n";

    # set custom HTTP request header fields
    my $req = HTTP::Request->new(POST => $server_endpoint);
    $req->header('content-type' => 'application/json');
    $req->header('x-auth-token' => 'kfksj48sdfj4jd9d');

    # add POST data to HTTP request body
    $req->content(" ");

    my $ua = LWP::UserAgent->new;
    my $resp = $ua->request($req);
    if ($resp->is_success) {
      my $message = $resp->decoded_content;
      print "Received reply: $message\n";
    } else {
      print "HTTP GET error code: ", $resp->code, "\n";
      print "HTTP GET error message: ", $resp->message, "\n";
    }

  }
}

Das Script sollte dann manuell ausgeführt werden. Wenn alles erfolgreich war, dann kann das Script auch vom Cron ausführen lassen:

Mit crontab -e können dann im Intervall die Daten ausgelesen werden und in der Datenbank gespeichert werden. Achtung: Leerzeile am Ende nicht vergessen. Das Script wird mit der folgenden Einstellung alle 1min ausgeführt.

# m h  dom mon dow   command
*/1 *   *   *   *  /root/bin/get1wire >/dev/null 2>&1

log_onewire.sh

Dieses Bash Script fragt den 1-Wire Bus mit Digitemp ab und loggt die Daten in die Middleware. Die Sensoren müssen dazu direkt am Rechner angeschlossen sein.

https://github.com/volkszaehler/volkszaehler.org/blob/master/misc/controller/1wire/log_onewire.sh

log_onewire_ecmd.sh

Diese Variante liest Sensoren aus, die an einen ethersex kompatiblen Mikrocontroller angeschlossen sind, aus. Dazu wird ECMD genutzt. Das Skript sollte als Cron-Job auf dem Middleware-Server laufen.

https://github.com/volkszaehler/volkszaehler.org/blob/master/misc/controller/1wire/log_onewire_ecmd.sh

Mit einem aktuellen Ethersex und aktiviertem „Onewire naming support“ kann man jetzt auch die Sensoren mit ihrem Namen abfragen. Dazu muss man mit dem entsprechenden ecmd „1w name set x 1234567890abcdef Sensor1“ einer Sensor-ID einen Namen zuweisen. Mit „1w name save“ wird das persistent im EEPROM gespeichert. Dann kann man immer mit „1w get Sensor1“ statt „1w get 1234567890abcdef“ die Temperatur abfragen. Das „x“ bezeichnet die Stelle in der Sensoren-Tabelle. Defaultmäßig ist Platz für 10 Sensoren. Muss man den Sensor mal austauschen, reicht eine neue Zuordnung Sensor-ID → Name und man muss nichts an seinen Scripten ändern.

control6.src

Dieses ethersex Control6-Skript loggt direkt gegen eine volkszaehler.org Middleware. Es sind keine weiteren serverseitigen Skripts oder Cron-Jobs mehr notwendig.

Um Control6 nutzen zu können muss dieses erst noch aktiviert und konfiguriert werden,

Dazu aktiviert ihr Ethersex → General Setup → control6 scripts (EXPERIMENTAL) Ethersex → Network → DNS support → DNS-Server IP address

Konfiguriert wird es unter Ethersex → Protocols → httplog clientt (EXPERIMENTAL)

Service: "volkszaehler.org"   
Path: "middleware.php/data/"
[-] Include unix timstamp
[ ] Include uuid
  UUID: "12345678-9ABC-DEF0-1234-56789ABCDEF0"
     Randomize UUID
--- Debugging Flags
[-] HTTPLOG        

Zusätzlich muss in der Ethersex Datei „protocols/httplog/httplog.c“ die Zeile 50 geändert werden.

  "GET " CONF_HTTPLOG_PATH "?";

wird durch

  "POST " CONF_HTTPLOG_PATH "";

ersetzt.

Dann ganz normal kompilieren. „Include unix timstamp“ funktioniert so nicht für Volkszaehler, siehe unten.

Bitte 1-Wire ID und Middleware UUID einsetzen!
  dnl   Copyright (c) 2008 by Jochen Roessner <jochen@lugrot.de>
  dnl   Copyright (c) 2011 by Justin Otherguy <justin@justinotherguy.org>
  dnl   This program is free software; you can redistribute it and/or modify
  dnl   it under the terms of the GNU General Public License version 2 or later
  dnl   as published by the Free Software Foundation.
  dnl  
  dnl   This program is distributed in the hope that it will be useful,
  dnl   but WITHOUT ANY WARRANTY; without even the implied warranty of
  dnl   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  dnl   GNU General Public License for more details.
  dnl  
  dnl   You should have received a copy of the GNU General Public License
  dnl   along with this program; if not, write to the Free Software
  dnl   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  dnl  
  dnl   For more information on the GPL, please go to:
  dnl   http://www.gnu.org/copyleft/gpl.html
  dnl
  C6_HEADER(`/* This will be in control6.h */')
  char temp_str[5];
  dnl max length of value string: 4 (ex. -12.3)
  CONTROL_START
  	THREAD(1wirelog)
  		dnl get temperature from 1wire bus, change the sensor id!
  		int16_t temp = ONEWIRE_GET(<1-wire id>);
  		itoa_fixedpoint(temp, 1, temp_str);
  		dnl log against the middleware, change the sensor uuid!
  		HTTPLOG("<uuid>.json?value=%s", temp_str);
  		WAIT(300);
  	THREAD_END(1wirelog)
  	ON STARTUP DO THREAD_START(1wirelog) END
  CONTROL_END
  

Für control6 ist bei aktiviertem „Onewire naming support“ ebenfalls eine neuer Befehlt vorhanden. Mit „ONEWIRE_GET_BY_NAME(Sensors1)“ wird die Temperatur des ensprechenden Sensors geliefert. Das hat den großen Vorteil dass man die Firmware nicht neue bauen muss wenn sich der Sensor ändert. Achtung: wenn der Name (noch) nicht existiet wird als Wert „32767“ bzw. nach der Umwandung 3276.7°C geliefert.

Beispiel mit aktiviertem Timestamp und Namensupport :

C6_HEADER(`/* This will be in control6.h */')
dnl
#include "protocols/httplog/httplog.h"
#include "services/clock/clock.h"
dnl
CONTROL_START
  THREAD(onewire)
     dnl wait 30s for ntp time is set 
     WAIT(30);
     int16_t temp2 = ONEWIRE_GET_BY_NAME(Heizung);
     dnl check if temperatur is valid
     if (temp2 < 1300){
       char temp2_str[5];
       itoa_fixedpoint(temp2, 1, temp2_str);
       HTTPLOG("12345678-abcd-efgh-9876-123456789012.json?ts=%lu000&value=%s", clock_get_time(), temp2_str);
     }
     dnl please acivate syslog or remove next 3 lines
     else {
       SYSLOG("Error: Sensor Heizung not found !")
     }
     dnl pause for 300s in summary
     WAIT(270);
  THREAD_END(onewire)
  ON STARTUP DO THREAD_START(onewire) END;
CONTROL_END
hardware/channels/sensors/1_wire.txt · Zuletzt geändert: 2016/02/21 21:11 von justinotherguy