StromMonitor

Ziel und Funktionsweise

Bau eines Netzwerkfähigen lokalen StromMonitors, der via S0-Schnittstelle Daten erhebt und aufbereitet, bis zur Text/Grafik Präsentation im lokalen Netz.

Vorüberlegung

Wie viel Strom ruft man pro Minute, Tag, Monat, Jahr ab? Die Jahresabrechnung gibt zwar den Jahresverbrauch in KWh, aber für den genaueren Überblick muss man loggen…

Klassisch geht das per Papier und Schreibzeug, aber man verliert schnell die Lust.

Liste von Hand

Alternative: Elektronisch

Wie geht das?

Das hängt vom Stromzähler ab, der vor Ort ist. In Konstanz dieser:

Konstanzer Stromzaehler

Der hat zwar keine bidirektionale Schnittstelle mit Abfragemöglichkeit, aber eine kleine unscheinbare Öffnung,

IR-LED der S0-Schnittstelle

Hier verbirgt sich eine IR-LED, die also 10000 mal blinkt, bis 1 KWh bezogen wurde,

Kann man das zählen?

Let’s test

Zum Testen

  • 1 IR-Transistor ( unter 1 Euro)
  • 1 LED (unter 20 ct)
  • 1 Widerstand 47 Ohm (unter 20 ct)
  • Spannungsquelle 5-6 Volt (1 x 1,5 V Batterien, Netzteil, o. ä.)
  • zum Verbinden oder aufbauen Kabel, Krokoklemmen, Breadboard, (was Ihr so nehmt)
  • Pappe, Kabelbinder, Tesafilm, etc zum Fixieren
Schaltplan Testaufbau

Beim Verbinden auf die Polarität achten

  • LED langes Bein plus
  • IR-Transistor Langes Bein minus

IR-Transistor in Reihe mit dem Vorwiderstand und der LED an die Spannungsquelle hängen.

Testaufbau mit 5V Spannung IR-Transistor und LED

Alles Richtig? Dann muss die LED (Verbrauch vorausgesetzt) blinken …

zusätzliches Material für den StromMonitor

Raspberry Pi
  • 1 Raspberry PI oder ähnliches Embedded System, egal welches, (Hauptsache, Ihr könnt ein OS aufsetzen und kommt an die GPIOs, bei mir lag ein PI B + rum) (zwischen 6 und 36 Euro Neuwert)
  • SD-Karte ( 4-10 Euro Neuwert)
  • Netzteil ( ca 8 Euro Neuwert)
  • LAN/WLAN-Anschluss (0 - 8 Euro, je nach Modell uind lokalen Möglichkeiten)

Vorbereitung

Den PI mit Betriebssystem füttern und LAN/WLAN einrichten (ich finde den Zugang per SSH und / oder VPN besonders bequem, wer steht schon gern im Keller mit Monitor und Keyboard).

Verkabelung

Schaltplan Strom-Monitor

Damit der PI auch die Daten empfangen kann, hängen wir den IR-Transistor an GPIO 23/ PIN 16 und verbinden ihn mit auf der anderen Seite mit PIN 6 /GND

Damit wir uns wohlfühlen und eine optische Rückmeldung im Keller haben, kommt zwischen Pin 1 (3.3V) und PIN 11 /GPIO 17 die LED mit dem Vorwiderstand von eben.

Software

Ich habe die Software in 2 Häppchen zerlegt.

  • Strom.py arbeitet kontinuierlich. Zum einen wird ein Thread angestossen, der die LED als Rückmeldung kurz triggert, zum anderen wird eine Logzeile mit Standard-Linux Zeitstempel und den Sensor-Datenstrom (Anzahl der Impulse/ Minute) jede Minute in die Datei imp_min.txt geschrieben.

Quelltext:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  strom.py
#
#  StromMonitor Anzeige, konkret:
#  SENSOR in imp/min wandeln
#
#  Author: Kresse
#
#
#
#  Version 06 - 11 : 30 Jan 17
#  Version 13-14   : 4  Feb 17
#  Version 15      : 6  Feb 17
#  Version 16      : 13 Mar 17
'''
	Ziel
	Stromzaehler-Impulse mit dem PI
	loggen,
	ggf grafisch Darstellen


	Ziele:
	IR-Diode an PIN 16
	dann Impulse/min protokollieren
	Darstellung in Impulse/min, KW/h
	Zusammenfassung Stündlich:
	KW/h , min, max
	RRD ?

	Kontroll-LED an Pin 11
'''

import rrdtool
import sys,random
import time

from threading import Thread



#mal ganz was grundsätzliches
# Linux = True
# Raspberry = True
# Test  = True


import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)

#
#
# PIN 16 GPIO 23
# Kontakt Stromzähler
# IR Transistor schaltet gegen Masse
#
messpunkt = 16
GPIO.setup( messpunkt, GPIO.IN, pull_up_down= GPIO.PUD_UP)
#
# PIN 11 GPIO 17
# led Kontrolleuchte
# LED wird gegen 3,3 V geschaltet
#
led1 =11
GPIO.setup(led1,GPIO.OUT)

'''   ERZEUGE EINE Datenbank DATEI mit 80 kB
	  (Beschickung kann gerne noch optimiert werden)
	  WIRD NUR BEIM ERSTEN PROGRAMMSTART BENÖTIGT,
	  danach AUSKOMMENTIEREN, sonst bricht das PYTHON-SKRIPT
	  mit Fehler ab!

rrdtool.create( 'POWER.rrd' ,'--no-overwrite','--step', '60', \
'DS:counter:GAUGE:86400:0:100000', \
'RRA:LAST:0.5:15:96', 'RRA:AVERAGE:0.5:15:96','RRA:LAST:0.5:1:4320', \
'RRA:AVERAGE:0.5:1:4320', 'RRA:LAST:0.5:1440:30', \
'RRA:AVERAGE:0.5:1440:30','RRA:LAST:0.5:10080:520','RRA:AVERAGE:0.5:10080:520')
'''

def ZaehlerHoch():
	#
	global impulse_gesamt
	global led1
	impulse_gesamt +=1
	# print time.ctime()
	#    print "*",
	#
	led1thread = Thread(target=led1anaus , args=(0.1,))
	led1thread.start()
	# ENDE Zaehlerhoch

def led1anaus(s):
	global led1
	GPIO.output (led1,False)
	#
	time.sleep(s)
	GPIO.output (led1,True)
	#
#

def Ausgabe(Schreibwert):
	#
	#
	print " Das sind derzeit:",(Schreibwert )," Impulse in dieser Minute."
	print " Das ist vergleichbar mit ",(Schreibwert * 0.006),"KWh"
	#
	rrdtool.update('POWER.rrd','N:%s' %(Schreibwert))
	#
	with open("imp_min.txt","a") as datei:
		datei.write(str(time.time())+","+str(Schreibwert)+"\n")
	#
#
#
#
#        startzeit= time.ctime()

while True:
		zeit_1min= time.time() + 60
		impulse_gesamt = 0
		impulse= False
		Vorimpulse = False
		while time.time() < zeit_1min:
				#
				vorimpulse = impulse
				#
				#

				if GPIO.input(messpunkt) == True:
						impulse = True
				else:
						impulse = False
				#
				#
				if impulse == True and vorimpulse == False:
						ZaehlerHoch()
				#
				# Ende While
		#
		Ausgabethread = Thread(target=Ausgabe , args=(impulse_gesamt,))
		Ausgabethread.start()
		#print impulse_gesamt
#
GPIO.cleanup()

RRD-Tool

RRDTOOL ist eine zyklische “Round Robin Datenbank”. Immer wieder werden Daten in einen begrenzten Platz abgelegt und (die jeweils letzten Daten sind ja die relevanten). Ältere werden zusammengefasst, damit man auf kleinem Raum viele Informationen hat.

Also wird eine RRDTOOL-Datenbank angelegt und dann befüllt (ich hab das Anlegen nur beim ersten Start gemacht und dann einfach beim Restart auskommentiert…), diese wird ebenfalls minütlich beschickt

imp_min.txt wird dann vom Programm impAuswertung.py ausgewertet.

Quelltext:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  impAuswertung.py
#
#  Copyright 2017 tom <tom@Durban>
#
#
#
#  VERSION 01    Feb 2017
#  Version 02  6 Feb 2017
#  Version 03  7 Feb 2017
#  Version 05 12 Feb 2017
#  Version 08 19 Feb 2017
#

'''
	Ziel
	Stromzaehler-Impulse aus der imp_min.txt lesen

	Ziele:
	Angabe am Jeweiligen Tag verbrauchte KWh


'''

import time
liste = open ("imp_min.txt","r")
liste_imp = list()
liste_zeit = list()
akk_imp = 0


while True:
	#
	zeile = liste.readline() # just reads one line
	#
	if not zeile:
		break
	else:
		#print (zeile)
		Trenner1= zeile.index(",")
		if Trenner1 >0 :
			#
			zeit =eval( zeile[0:zeile.index(",")])
			liste_zeit.append(zeit)#
			imp = eval(zeile[zeile.index(",")+1:-1])
			liste_imp.append(imp)
			akk_imp += imp
			#print zeile , imp
print "Gesamtimpulse       : ",akk_imp #
#print (liste_imp)
print "Anzahl der Messungen :",(len(liste_imp))
print "Minimum Imp/min      :",(min(liste_imp))
print "Maximum Imp/min      :",(max(liste_imp))
#
#
#Suche einen Datem zusammen und zaehle diese
#
#
imp_d = 0
imp_h = 0
print
print "*** Erster Tag nicht vollstaendig!          ***"
print time.ctime(liste_zeit[0])[0:16],": *** Beginn***"


for x in range(1,len(liste_imp)):
	#
	#
	if time.ctime(liste_zeit[x])[11:13] != time.ctime(liste_zeit[x-1])[11:13]:
		#
		#  Stunde voll
		#
		#print time.ctime(liste_zeit[x-1])[0:16],": "," {p:8.3F}  KWh ".format(p=(imp_h/10000.0))
		imp_h=0
		#
	if time.ctime(liste_zeit[x])[0:3] != time.ctime(liste_zeit[x-1])[0:3]:
		#
		#  Tag voll
		#
		print time.ctime(liste_zeit[x-1])[0:11],": "," {p:8.3F}  KWh ".format(p=(imp_d/10000.0))
		imp_d=0
		#
	imp_d +=(liste_imp[x])
	imp_h +=(liste_imp[x])
#
#
# print x   # Anzahl der Datensätze
print time.ctime(liste_zeit[x-1])[0:16],": "," {p:8.3F}  KWh ".format(p=(imp_d/10000.0))
print "*** LETZTER Tag nicht vollstaendig! ***"

Zum Schluss wird das ganze per Bash zur Ausgabe gedrängt ;) Zum einen werden zwei RRDTOOL Graphiken erzeugt: Impulse/min über 24 h Mittlere Impulse/Min über 7 Tage. Als Drittes gibt es eine Textausgabe mit der KWh-Abnahme pro Tag.

Als lokale “Veröffentlichungsvariante” habe ich folgendes installiert: Die Dateien werden dann auf ein eingehängtes CIFS-Verzeichnis kopiert, das lokal als Web-Server fungiert.

Das folgende Bash-Skript wird dazu per cronjob alle 3 Stunden angestartet,

Quelltext:

#!/usr/bin/bash
rrdtool graph power24.png --start -24h --title "Impulse pro Minute" --vertical-label "Imp"    DEF:Imp=POWER.rrd:counter:AVERAGE LINE1:Imp#ff0000:"IMP"
rrdtool graph power7d.png --start -7d --title "Mittlere Impulse pro Minute" --vertical-label "Imp"    DEF:Imp=POWER.rrd:counter:AVERAGE LINE1:Imp#ff0000:"IMP"
cp power7d.png REMOTEWEB/STROM
cp power24.png REMOTEWEB/STROM
python impleser.py >ausgabe.txt
cp ausgabe.txt REMOTEWEB/STROM

Darstellung

Damit kann ich im Hausnetz die Dateien dann problemlos per Weblink abrufen.

Als Graphiken:

Wochenverteilung
Tagesprofil

Und als Text:

Gesamtimpulse       :  4282664
Anzahl der Messungen : 61776
Minimum Imp/min      : 14
Maximum Imp/min      : 807

*** Erster Tag nicht vollstaendig!          ***
Sat Feb  4 14:10 : *** Beginn***
Sat Feb  4  :      6.547  KWh
Sun Feb  5  :     12.131  KWh
Mon Feb  6  :     10.275  KWh
Tue Feb  7  :      9.481  KWh
...

Was bringt das?

Mir hat das ganze beim Aufsetzen viel zum Nachdenken/Nachschlagen/Probieren gegeben.

Das Projekt ist dann gut und gerne umzusetzen,

  • wenn man sich auf den PI einlässt,
  • gern ein bisschen Python skriptet,
  • mal mit RRDTOOL spielen will
  • und einen besseren Überblick über den täglichen Verbrauch haben möchte.

Bei uns gab es danach im Familienkreis tatsächlich Überlegungen, wie man die Abnahme reduzieren könnte…

Viel Spaß und keep hackin'

Viele Andere Stromzähler und Gedanken zur Auswertung habe ich auf Volkszaehler.org gefunden. Den Konstanzer Zähler allerdings nicht.