Mit der eigenen Solaranlage den benötigten Strom zu produzieren klingt gut. Dazu scheint auch die Förderung noch zu stimmen: In unserem Fall gibt es für eingespeisten Strom 39ct/kWh, für selbst verbrauchten Strom dagegen 22ct/kWh plus die gesparten 23ct/kWh aus unserem Ökostromtarif.
Aber auch grundsätzlich macht so eine Solaranlage viel sensibler für der eigenen Stromverbrauch. Jedoch ist es trotz Smart Metering gar nicht so einfach, einen Überblick über den eigenen Stromverbrauch zu bekommen.
Zweiwegezähler
Zunächst braucht man bei einer Solaranlage mit Eigenstromverbrauchsmessung einen Zweiwegezähler. Die Solaranlage wird dann wie folgt verschaltet:

Solarlog 500 an Normzähler?
Sodann: Mit unserem Solarlog 500 ist laut Werbung "auch die Messung und Auswertung des Eigenstromverbrauchs möglich". Also flugs eine email an den Hersteller geschickt:
Sehr geehrte Damen und Herren,zur Überwachung unserer neuen PV-Anlage habe ich mich für den Solarlog 500 entschieden, da hier auch der Eigenstromverbrauch mit protokolliert werden kann. Ich möchte nun die entsprechenden Voraussetzungen schaffen. Im Zählerkasten befindet sich ein Zweirichtungszähler EHZ361Z5 von Hager mit optischem Impulsausgang (10000/kWh) sowie optischem DO-Datenausgang nach IEC 62056-21 (http://download.hager.com/Hager.de/files_download/aktuelles/ehz/ehz_betriebsanleitung_mid.pdf). An den DO-Datenausgang lässt sich ein Auslesekopf EHZ001 montieren, der die Daten über RS232 zur Verfügung stellt (http://download.hager.com/Hager.de/files_download/Dokumentationen/_technik_broschueren/eHZ_09DE0009.pdf, Seite 14). Ein CAT5e-Kabel vom Zählerschrank zum Solarlog 500 ist vorhanden.
Wie muss ich die Kabel mit dem Solarlog 500 verbinden?
Die Antwort kam prompt: So ginge das ja nicht, einfach die bestehenden Zähler zu verwenden. Nein, ein weiterer Verbrauchszähler müsse her, und der müsse einen S0-Ausgang haben, der dann an den S0-Eingang des Solarlog anzuschliessen sei.
Oops. Noch ein Zähler, nochmal der Elektriker, wo doch alle Daten über Infrarot zur Verfügung stehen? Da fühlt sich der Techniker doch herausgefordert, eine Alternative zu entwickelt!
Infrarot-Datenschnittstelle der Stromzähler
Aber der Reihe nach. Zuerst will ich einmal sehen, was die beiden Zähler so an Daten liefern. Der EHZ001 von Hager soll 33€ kosten, und ich würde ja zwei benötigen. Aber im Lego-Regal der Kinder ist doch noch ein Mindstorm IR-Tower? Also flugs einen Rechner zum Zählerschrank, hterm installiert, und den IR-Tower vor die IR-Schnittstelle. Es tut sich etwas, definitiv, aber hterm zeigt nur Bitmüll.
Der zweite Versuch startet mit einer Internet-Recherche. Ich finde zunächst Mathias Lösung, die mir aber etwas zu kompliziert vorkommt, und dann Armin63's Bericht im Photovoltaikforum. Armin braucht nur einen TEKT5400S, einen Widerstand und eine Spannungsquelle. Aber RS232 hat ja noch andere Leitungen, da müsste es doch auch ohne zusätzlichen Trafo gehen? Geht auch, und zwar zum Beispiel mit DTR, man muss dann nur DTR im hterm setzen um Daten zu empfangen:

(Ich weiss ehrlich gesagt nicht mehr genau, was für einen Widerstand ich benutzt habe, muss irgend etwas zwischen 200Ω und 1kΩ gewesen sein.)
Meine Zähler liefern tatsächlich alle paar Sekunden (lastabhängig) ein kurzes Klartext-Datentelegramm mit 9600 Baud, 7E1 (7 Datenbits, gerade Parität, ein Stoppbit). Das Infrarotsignal ist nicht mit 38kHz moduliert. Das war auch der Grund, warum der IR-Tower von Lego Mindstorms nur Datenmüll lieferte: Dort wird ein TSOP1138 benutzt, der erstens 38kHz Modulation erwartet und zweitens für 9600 Baud nicht schnell genug ist.
/HAG5eHZ010C_RWE1ZA20
1-0:0.0.0*255(123456-1234567)
1-0:1.8.1*255(004944.6745)
1-0:2.8.1*255(002093.5653)
1-0:96.5.5*255(82)
0-0:96.1.255*255(0000012345)
!
sowie
/EMH5----eHZ-E0028E
1-0:0.0.0*255(123456-1234567)
1-0:2.8.1*255(003523.4656)
1-0:96.5.5*255(00)
0-0:96.1.255*255(0001234567)
!
Da mein Rechner nur eine RS232-Schnittstelle hat (und vor allem weil serielle Ports immer seltener werden) habe ich mir für den zweiten Zähler einen USB-zu-Seriell-Konverter besorgt. Die Pegel sind dort etwas niedriger, ich brauchte den Widerstand aber nicht zu ändern.
Kurze und lange Datentelegramme
Unser aktueller Stromverbrauch ergibt sich aus der Summe der Solaranlagenproduktion und der Netzentnahme. Dabei kann die Netzentnahme natürlich auch nagativ werden, nämlich wenn die Solaranlage einspeist.
Beide Zähler liefern leider nicht den derzeitigen Wirkverbrauch. Laut Hager gibt es den Zähler als Ausführung mit kurzem und mit langem Datentelegramm (meine Zähler sind solche mit kurzem Datentelegramm) und lassen sich nicht über die rückseitige bidirektionale IR-Schnittstelle umkonfigurieren. Leider habe ich darauf bei der Installation letztes Jahr nicht geachtet.
Vielleicht lassen sich die Zähler noch kostenlos gegen die Benötigten umtauschen. Was sagt denn dazu mein Messstellenbetreiber?
Sehr geehrte Damen und Herren,ich betreibe seit Mitte letzten Jahres eine PV-Anlage nach EEG mit Messung des Eigenstromverbrauchs. Sie lieferten und betreiben die dazu notwendigen Zähler (ZÜ für Lieferung und Bezug, ZE für Erzeugung). Meine Kundennummer lautet X 123 4567 890.
Ich möchte nun meinen tatsächlichen Energieverbrauch ermitteln. Dazu benötige ich die jederzeit aktuell von ZÜ und ZE gemessenen Wirkleistungen. Diese sind aber bei den von Ihnen gelieferten Zählern nicht in dem Datentelegramm der vorderen optischen Schnittstelle (nach DIN EN 62056-21) enthalten.
Laut Firma Hager gibt es die Zähler in zwei Ausführungen, entweder mit kurzem oder mit langem Datentelegramm. Nur das lange Datentelegramm enthält die aktuellen Wirkleistungen. Die von Ihnen gelieferte Ausführung mit kurzem Datentelegramm entspricht sogar womöglich nicht § 21b Abs. 3a EnWG.
Bitte unterbreiten Sie mir ein Angebot, meine beiden Zähler gegen solche mit langem Datentelegramm aufzurüsten, die zur Ermittlung meines tatsächlichen Energieverbrauchs geeignet sind und die die aktuellen Wirkleistungen übermitteln.
Die Antwort der RWE Rhein-Ruhr Verteilnetz GmbH ist so simpel wie nur mündlich: Ein Zähleraustausch sei möglich, koste aber 90€ pro Zähler.
Es ist zum Haareraufen. Da verabschieden EU (2006/32/EG) und Bundesregierung (EnWG) lauter Gesetze und Verordnungen, und das RWE verbreitet dennoch lustig Zähler mit extra kurzem Datentelegramm, um sich dann die Umrüstung auf das lange Datentelegramm noch bezahlen zu lassen. Argh.
Die metrologische LED
Wenn sekündlich nur der aktuelle Zählerstand in kWh mit vier Nachkommastellen, also auf 1/10 Wh genau, übermittelt wird, lässt sich daraus der aktuelle Stromverbrauch nur in Schritten von 360 Watt (!) berechnen. Für eine genauere Anzeige muss man also über mehrere Sekunden mitteln. Man möchte aber andererseits bei Einschalten eines Verbrauchers möglichst innerhalb weniger Sekunden den Effekt auf den Stromverbrauch sehen können.
Einen sehr genauen Wert des derzeitigen Stromverbrauch liefert dagegen die metrologische optische LED, die einmal pro 1/10 Wh blinkt. Wenn zum Beispiel gerade 3600W durch den Zähler fließen, also pro Sekunde 1Wh verbraucht wird, so blinkt die LED alle 100ms. Steigt der Stromverbrauch auf 3610W an, so sinkt das Blinkintervall auf 99.773ms, ein Unterschied von 277μs.
Andererseits kann man mit der metrologischen LED beim Zweiwegezähler nicht die Richtung des Stroms ermitteln. Zumindest habe ich keinen Trick gefunden.
Arduino
Ich benötige also ein Messgerät, dass wenig Strom verbraucht, zwei serielle Schnittstellen auslesen, Messungen im Mikrosekundenbereich vornehmen, Summen bilden und daraus einen künstlichen S0-Impuls generieren kann. So etwas kann ein PC nicht mehr: Ich brauche einen Mikrocontroller!
Schnell fällt die Wahl auf einen Arduino: Open Source Hardware, gefällige Programmierumgebung, gute Erweiterbarkeit. Ich entscheide mich für den Mega 2560, weil der Arduino Uno nur eine serielle Schnittstelle in Hardware unterstützt und ich Bedenken habe, dass die Bedienung der seriellen Schnittstelle in Software mit der genauen Messung der metrologischen LED kollidiert. Ich kaufe zudem einen Trafo, ein Gehäuse sowie ein RTC-Modul und einen Ethernet-Shield für zukünftige Erweiterungen.
Schaltungsaufbau
Erste Tests mit dem TEKT5400S und einer IR-Fernsteuerung an einem analogen Port sind erfolgreich. Für die Überwachung der metrologischen LED fällt die Wahl auf den LPT80A (weil er im lokalen Elektronikladen am Lager ist). Zur Generierung des S0-Impulses benutze ich einen Optokoppler vom Typ HCPL-817-00DE. Es entsteht folgender Schaltungsaufbau:

Man beachte, dass sich in meinem Fall kein Widerstand im S0-Strompfad befindet: Durch Leitungslänge (15m, zwei Mal jeweils vier Adern eines Ethernet-Kabels), Schutzdiode und Optokoppler ergibt sich bei mir ein maximaler Stromfluss von 7,5mA, also 150mW bei höchstens 20V, die der Optokoppler (gerade) noch schalten kann.
Solarlog S0-Eingang
Nach einigen Irrungen und Wirrungen läuft nun seit dem 27. Mai eine Version meiner Software im Dauerbetrieb. Dazu musste der S0-Eingang des Solarlog 500 als Eigenverbrauchszähler definiert werden. Ich hatte dabei zunächst auf den Upgrade der Firmware verzichtet. Das Resultat war eine "Datenbereinigung", durch die der Grossteil der historischen Ertragsdaten zerstört wurde. Na toll, dachte ich, gut dass ein regelmäßiger Backup konfiguriert war. Nur leider war der backup-Ordner leer, ein backup hatte nie funktioniert. Glücklicherweise sind wenigstens die minyymmdd.js-Tagesdateien alle noch vorhanden, so dass bei Bedarf die historischen Ertragsdaten zu rekonstruieren sein sollten. Nach dieser Erfahrung bin ich mit den Solarlog-Daten vollständig zu meinem persönlichen Webhoster (der Domainfactory) umgezogen.
Am Solarlog ist der Impulsfaktor auf 1000 Impulse pro kWh eingestellt. Die Software erzeugt also für je 10 1/10 kWh Impulse bzw. Verbrauchsdaten der Zähler einen Impuls am S0-Eingang des Solarlog. Laut Spezifikation der S0-Schnittstelle sollte dieser Impuls eine Mindestlänge von 30ms haben und ebenso mindestens 30ms zwischen zwei Impulsen liegen. Unser Haus hat 3 x 25A Panzersicherungen, macht also max. 10kW pro Phase, also maximal 30kW Verbrauch. 30kW entsprechen 8,33Wh pro Sekunde, also 8,33 S0-Impulsen, also 120ms pro Impuls. Eine Impulslänge von 50ms ist also unkritisch und führt bei Maximalverbrauch zu 70ms Pause. Passt.
Andersherum soll der Solarlog angeblich bei weniger als einem Impuls pro Minute den S0-Eingang abschalten. Ein Impuls pro Minute entspricht (bei 1000 Impulses pro kWh) 60W. Passt auch bei uns (unser Grundverbrauch liegt über 60W), könnte für andere aber etwas knapp sein.
Die Installation produziert dann folgendes Ergebnis am Solarlog 500:

Ich benötige auch kein spezielles Netzteil für den Solarlog 500 wie in einigen Forenbeiträgen empfohlen. Ich stelle jedoch nach wie vor unerklärliche Fehlermeldungen im Diagnoselog des Solarlog fest:
Ereignis von - bis Status
13.06.11 03:03:08 - 0 - Power
13.06.11 03:02:30 - 03:03:07 255 - Offline
12.06.11 03:03:03 - 13.06.11 03:02:29 0 - Power
12.06.11 03:02:30 - 03:03:02 255 - Offline
11.06.11 03:03:09 - 12.06.11 03:02:29 0 - Power
11.06.11 03:02:30 - 03:03:08 255 - Offline
10.06.11 03:03:08 - 11.06.11 03:02:29 0 - Power
10.06.11 03:02:30 - 03:03:07 255 - Offline
09.06.11 03:03:07 - 10.06.11 03:02:29 0 - Power
09.06.11 03:02:30 - 03:03:06 255 - Offline
08.06.11 03:03:30 - 09.06.11 03:02:29 0 - Power
08.06.11 03:03:15 - 03:03:29 255 - Offline
08.06.11 03:03:07 - 03:03:14 0 - Power
08.06.11 03:02:30 - 03:03:06 255 - Offline
07.06.11 03:03:07 - 08.06.11 03:02:29 0 - Power
07.06.11 03:02:30 - 03:03:06 255 - Offline
06.06.11 03:03:08 - 07.06.11 03:02:29 0 - Power
06.06.11 03:02:30 - 03:03:07 255 - Offline
05.06.11 10:35:15 - 06.06.11 03:02:29 0 - Power
05.06.11 10:35:00 - 10:35:14 255 - Offline
05.06.11 10:34:45 - 10:34:59 0 - Power
05.06.11 10:34:30 - 10:34:44 255 - Offline
05.06.11 10:14:15 - 10:34:29 0 - Power
05.06.11 10:13:45 - 10:14:14 255 - Offline
05.06.11 03:03:06 - 10:13:44 0 - Power
05.06.11 03:02:30 - 03:03:05 255 - Offline
...
Was treibt das Teil morgens um 3 Uhr? Dafür habe ich bis dato keine Erklärung.
Software
Im folgenden möchte ich den Kern der Software beschreiben und einige Erfahrungen anmerken.
Der Aufbau der Software ist wie folgt: Eine Klasse Wattlight ist für die Überwachung der metrologischen LED's zuständig. Dabei triggert jede steigende Flanke des Lichtimpulses einen Interrupt. Im Interrupthandler wird der Zeitpunkt des letzten Impulses sowie die Anzahl der Impulse seit dem letzten Datenabruf vermerkt.
In der Klasse PowerSerial werden die seriellen Infrarotdaten der beiden Zähler empfangen und ausgewertet und die aktuellen Verbrauchswerte vorgehalten. Zu Beginn jeden Datenpakets (beim Zeichen /) wird zudem die zugehörige metrologische LED via Wattlight ausgelesen und dadurch der Impulszähler zurückgesetzt.
Die Klasse S0Class schliesslich berechnet ca. alle fünf Sekunden den angefallenen Verbrauch als Summe der Solarproduktion plus der Netzentnahme minus der Netzeinspeisung, auf der Basis der letzten erhaltenen Infrarotdaten von PowerSerial und zudem der seitdem angefallenen Impulse von Wattlight, und generiert dann die entsprechend nötigen S0-Impulse.
Wattlight
Als erstes die Klasse zur Messung der metrologischen LED, Wattlight.
wattlight.h
#include <WProgram.h>
class Wattlight {
volatile unsigned int count;
volatile unsigned long us, oldus;
volatile boolean haveold;
public:
unsigned int oldcount;
unsigned long avgus;
Wattlight ();
inline __attribute__((always_inline)) void interrupt () {
us = micros(); // Granularity only 4 us, this can be improved.
if (haveold) {
count++;
} else {
oldus = us;
haveold = true;
}
}
unsigned int pulses ();
void readout ();
};
wattlight.cpp
#include "wattlight.h"
Wattlight::Wattlight () {
count = 0;
haveold = false;
avgus = 0;
}
unsigned int Wattlight::pulses () {
unsigned int result;
noInterrupts();
result = count;
interrupts();
return result;
}
void Wattlight::readout () {
noInterrupts();
if (count) {
avgus = (us-oldus)/count;
oldus = us;
oldcount = count;
count = 0;
} else {
if (avgus && haveold) {
unsigned long newavg = micros()-oldus;
if (newavg>avgus) avgus = newavg;
}
oldcount = 0;
}
interrupts();
}
PowerSerial
Nun die darauf aufbauende Klasse zum Empfang und Auswertung der seriellen Daten, PowerSerial.
powerserial.h
#include <WProgram.h>
#include "wattlight.h"
class PowerSerial {
static const char* PATTERN;
const char* name;
HardwareSerial* serial;
const char* pp;
unsigned long kwhtemp[2];
char n;
unsigned long ms;
unsigned long maxage;
public:
Wattlight light;
unsigned long kwh[2], count;
void begin (const char* _name, HardwareSerial& _serial, unsigned long _maxage,
volatile uint8_t & ucsrc, uint8_t ucsz0, uint8_t upm1);
void parseMe ();
static PowerSerial power, solar;
static void setup();
static void parse();
};
#define FROMNET PowerSerial::power.kwh[0]
#define INTONET PowerSerial::power.kwh[1]
#define SOLAR PowerSerial::solar.kwh[1]
powerserial.cpp
#include "powerserial.h"
PowerSerial PowerSerial::power;
PowerSerial PowerSerial::solar;
const char* PowerSerial::PATTERN = "1-0:n.8.1*255(";
void PowerSerial::begin (const char* _name, HardwareSerial& _serial, unsigned long _maxage,
volatile uint8_t & ucsrc, uint8_t ucsz0, uint8_t upm1) {
name = _name;
serial = &_serial;
maxage = _maxage;
serial->begin(9600);
ucsrc = ucsrc & ~_BV(ucsz0) | _BV(upm1);
pp = PATTERN;
count = 0;
kwh[0] = kwh[1] = 0;
}
void PowerSerial::parseMe () {
unsigned long newms = millis();
if (maxage && (kwh[0] || kwh[1]) && newms>ms+maxage) {
kwh[0] = kwh[1] = 0;
}
int c;
if ((c = serial->read())>0) {
if (c=='/') {
light.readout();
kwhtemp[0] = kwhtemp[1] = 0;
} else if (c=='!') {
kwh[0] = kwhtemp[0];
kwh[1] = kwhtemp[1];
ms = newms;
count++;
} else if (*pp=='\0') {
if (c==')') {
pp = PATTERN;
} else if (c>='0' && c<='9') {
kwhtemp[n] = kwhtemp[n]*10+(c-'0');
} else if (c=='.') {
} else {
kwhtemp[n] = 0;
pp = PATTERN;
}
} else if (*pp=='n' && c>='1' && c<='2') {
n = c-'1';
pp++;
} else if (c==*pp) {
pp++;
} else {
pp = PATTERN;
}
}
}
void interrupt0() {
PowerSerial::power.light.interrupt();
}
void interrupt1() {
PowerSerial::solar.light.interrupt();
}
void PowerSerial::setup () {
power.begin("Power",Serial1,4500,UCSR1C,UCSZ10,UPM11);
solar.begin("Solar",Serial2,4500,UCSR2C,UCSZ20,UPM21);
attachInterrupt(0,interrupt0,RISING);
attachInterrupt(1,interrupt1,RISING);
}
void PowerSerial::parse () {
power.parseMe();
solar.parseMe();
}
S0Class
Und schliesslich die Klasse S0Class zur Erzeugung der S0-Impulse.
s0.h
#ifndef _s0_h
#define _s0_h
#include "powerserial.h"
class S0Class {
static const unsigned int RESYNC = 5200;
static const unsigned int PULSEMS = 50;
static const int PULSEFACTOR = 10;
unsigned long count;
enum State {INIT, START, SYNC} state;
unsigned long ms, kwh, fromnet, intonet, pulsems;
int pulses;
unsigned int msdelta;
boolean high;
uint8_t pin;
public:
void begin (uint8_t _pin);
void tick ();
};
extern S0Class S0;
#endif // _s0_h
s0.cpp
#include "s0.h"
S0Class S0;
void S0Class::begin (uint8_t _pin) {
pin = _pin;
pinMode(pin,OUTPUT);
digitalWrite(pin,LOW);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
count = 0;
state = INIT;
}
void S0Class::tick () {
unsigned long newms = millis();
if (state==INIT) {
if (FROMNET && SOLAR && INTONET) {
count++;
ms = newms;
fromnet = FROMNET;
intonet = INTONET;
kwh = fromnet+SOLAR-intonet;
pulses = 0;
high = false;
state = START;
}
} else if (newms>ms+RESYNC) {
count++;
if (FROMNET && SOLAR && INTONET) {
unsigned long newkwh;
ms = newms;
int powerpulses = PowerSerial::power.light.pulses();
int solarpulses = PowerSerial::solar.light.pulses();
if (FROMNET==fromnet && INTONET>intonet) {
// We feed the network. Power pulses are negative. House consumes solely solar.
powerpulses = -powerpulses;
} else if (FROMNET>fromnet && INTONET==intonet) {
// We consume from network in addition to solar (if any).
} else {
// We can't decide the flow direction of the power pulses. Disregard them.
powerpulses = 0;
}
fromnet = FROMNET;
intonet = INTONET;
newkwh = fromnet+SOLAR-intonet+powerpulses+solarpulses;
pulses += newkwh-kwh;
kwh = newkwh;
msdelta = pulses>0? RESYNC/pulses: 0;
if (state==START) {
pulsems = ms;
state = SYNC;
}
} else {
state = INIT;
}
}
if (pulses>=PULSEFACTOR && newms>=pulsems) {
high = !high;
digitalWrite(pin,high?HIGH:LOW);
digitalWrite(13,high?HIGH:LOW);
long pulsedelta = high? PULSEMS: msdelta*PULSEFACTOR-PULSEMS;
// pulsems += high?PULSEMS:msdelta*PULSEFACTOR-PULSEMS;
pulsems = newms + pulsedelta;
if (!high) pulses-=PULSEFACTOR;
}
}
Hauptprogramm
Zum Schluss das Hauptprogramm.
Power12.pde
#include "s0.h"
void setup() {
S0.begin(12);
PowerSerial::setup();
}
void loop() {
PowerSerial::parse();
S0.tick();
}
Auszug aus den Logdateien
In einer erweiterten Version der Software werden Logdaten über syslog (Udp Port 514) ins Heimnetz gebroadcasted (schönes deutsches Verb). So kann man die Software in Aktion erleben:
...
<13>2011/06/15 20:41:00.454416: Solar,76781: 0kWh, 51640042kWh; 4202958808us (0W, 0*)
<13>2011/06/15 20:41:00.540016: Power,39958: 55302603kWh, 33124486kWh; 1359820us (264W, 1*); 1929796us (373W, 0W)
<13>2011/06/15 20:41:01.228668: S0,16980: 73818155->73818160 (55302603+51640042-33124486+1+0), 2->7
<13>2011/06/15 20:41:01.454412: Solar,76782: 0kWh, 51640042kWh; 4203958844us (0W, 0*)
<13>2011/06/15 20:41:03.454352: Solar,76784: 0kWh, 51640042kWh; 4205958744us (0W, 0*)
<13>2011/06/15 20:41:04.454404: Solar,76785: 0kWh, 51640042kWh; 4206958844us (0W, 0*)
<13>2011/06/15 20:41:04.617260: Power,39960: 55302606kWh, 33124486kWh; 1326608us (271W, 1*); 4077244us (265W, 0W)
<13>2011/06/15 20:41:05.454412: Solar,76786: 0kWh, 51640042kWh; 4207958800us (0W, 0*)
<13>2011/06/15 20:41:06.429584: S0,16981: 73818160->73818164 (55302606+51640042-33124486+2+0), 7->11
<13>2011/06/15 20:41:06.436876: S0 pin goes HIGH for 50ms
<13>2011/06/15 20:41:06.454372: Solar,76787: 0kWh, 51640042kWh; 4208958768us (0W, 0*)
<13>2011/06/15 20:41:06.479728: S0 pin goes LOW for 4670ms
<13>2011/06/15 20:41:06.665908: Power,39961: 55302607kWh, 33124486kWh; 1352098us (266W, 2*); 2048648us (176W, 0W)
<13>2011/06/15 20:41:07.454408: Solar,76788: 0kWh, 51640042kWh; 4209958796us (0W, 0*)
<13>2011/06/15 20:41:08.454368: Solar,76789: 0kWh, 51640042kWh; 4210958756us (0W, 0*)
<13>2011/06/15 20:41:09.454376: Solar,76790: 0kWh, 51640042kWh; 4211958796us (0W, 0*)
<13>2011/06/15 20:41:09.604912: Power,39962: 55302609kWh, 33124486kWh; 1366258us (263W, 2*); 2939004us (245W, 0W)
<13>2011/06/15 20:41:11.454352: Solar,76792: 0kWh, 51640042kWh; 4213958760us (0W, 0*)
<13>2011/06/15 20:41:11.630476: S0,16982: 73818164->73818167 (55302611+51640042-33124486+0+0), 1->4
<13>2011/06/15 20:41:12.454372: Solar,76793: 0kWh, 51640042kWh; 4214958760us (0W, 0*)
<13>2011/06/15 20:41:13.454284: Solar,76794: 0kWh, 51640042kWh; 4215958704us (0W, 0*)
<13>2011/06/15 20:41:13.629220: Power,39964: 55302612kWh, 33124486kWh; 1340660us (268W, 1*); 4024308us (268W, 0W)
<13>2011/06/15 20:41:14.454336: Solar,76795: 0kWh, 51640042kWh; 4216958760us (0W, 0*)
<13>2011/06/15 20:41:15.454308: Solar,76796: 0kWh, 51640042kWh; 4217958732us (0W, 0*)
<13>2011/06/15 20:41:15.618532: Power,39965: 55302614kWh, 33124486kWh; 1361920us (264W, 2*); 1989312us (362W, 0W)
<13>2011/06/15 20:41:16.831340: S0,16983: 73818167->73818171 (55302614+51640042-33124486+1+0), 4->8
<13>2011/06/15 20:41:17.454296: Solar,76798: 0kWh, 51640042kWh; 4219958708us (0W, 0*)
<13>2011/06/15 20:41:17.595308: Power,39966: 55302615kWh, 33124486kWh; 1366516us (263W, 1*); 1976776us (182W, 0W)
<13>2011/06/15 20:41:19.454228: Solar,76800: 0kWh, 51640042kWh; 4221958616us (0W, 0*)
<13>2011/06/15 20:41:19.633460: Power,39967: 55302617kWh, 33124486kWh; 1364780us (263W, 1*); 2038152us (353W, 0W)
<13>2011/06/15 20:41:20.454276: Solar,76801: 0kWh, 51640042kWh; 4222958692us (0W, 0*)
<13>2011/06/15 20:41:21.454204: Solar,76802: 0kWh, 51640042kWh; 4223958640us (0W, 0*)
<13>2011/06/15 20:41:21.620140: Power,39968: 55302618kWh, 33124486kWh; 1364666us (263W, 2*); 1986680us (181W, 0W)
<13>2011/06/15 20:41:22.032268: S0,16984: 73818171->73818174 (55302618+51640042-33124486+0+0), 8->11
<13>2011/06/15 20:41:22.039448: S0 pin goes HIGH for 50ms
<13>2011/06/15 20:41:22.082444: S0 pin goes LOW for 4670ms
<13>2011/06/15 20:41:22.454212: Solar,76803: 0kWh, 51640042kWh; 4224958604us (0W, 0*)
<13>2011/06/15 20:41:23.454268: Solar,76804: 0kWh, 51640042kWh; 4225958652us (0W, 0*)
<13>2011/06/15 20:41:23.600772: Power,39969: 55302620kWh, 33124486kWh; 1364188us (263W, 1*); 1980632us (364W, 0W)
...
Power bezieht sich hier auf den Übergabezähler ZÜ, Solar auf den Erzeugungszähler ZE. Die Mikrosekunden und Wattangaben hinter dem ersten Semikolon ergeben sich aus den Blinkimpulsen der metrologischen LED's. Die Wattangaben hinter dem zweiten Semikolon bei Power sind nachträglich errechnet aus der Differenz der Zeit und der Zählerstände zum vorherigen Datentelegramm: Man erkennt die Fluktuation durch die zeitgesteuerte Übertragung und die daraus resultierende Ungenauigkeit gegeüber der metrologischen LED durch die Rundung der Zählerstände.

Hallo Sebastian,
schöne Projektdokumentation. Die Blink-LED-Auswertemaschine haben schon viele gebaut, ist ja auch eine einfache Lösung. Hat allerdings - wie Du schon sagst - den Schönheitsfehler, dass am Zweirichtungszähler die Einspeisung und der Bezug nicht zu trennen sind.
Wenn ich die Ausgaben Deines Hagers allerdings richtig lese, dann brauchst Du das gar nicht:
1-0:1.8.1*255(004944.6745)
1-0:2.8.1*255(002093.5653)
Da sind doch die aktuellen Zählerstände für Bezug und Einspeisung in kWh mit 4 Nachkommastellen kodiert, sprich: Der Zähler gibt Dir den Zählerstand in Wattstunden aus. Wenn Du nun diese Werte nimmst und jeweils die Zeit zwischen zwei Datagrammen misst, kannst Du aus den unterschiedlichen Zählerständen doch den Momentanwert in Watt errechnen. Das ist quasi das, was auch ein Flukso im mySmartGrid-Projekt macht.
Dominik Keller hat schon einen Mikrocontroller-Code, um die OBIS-Datagramme auszuwerten. Wenn Du Lust hast, kann ich Dir sagen wo der liegt - die Änderungen daran wären wahrscheinlich recht überschaubar.
Gruß,
-Mathias
Hallo Mathias, vielen Dank für Deinen Kommentar. Ich habe Deinen Bericht mit Interesse gelesen.
Die Auswertung der Klartext-OBIS-Datagramme geschieht in meiner Methode PowerSerial::parseMe(), siehe oben. Die seriellen Daten werden jedoch laut Datenblatt zeitgesteuert, also wohl zur vollen Sekunde abgeschickt. Dabei werden die Zählerstände auf 1/10 Wh gerundet. Damit lässt sich, wie gesagt, sekündlich der Verbrauch nur in Schritten von 360W ermitteln. Ich habe die Logdateien noch einmal dahingehend ausgewertet (sie bestätigen meine Annahme) und den Artikel entsprechend erweitert.
Aber ja, das würde für den Solarlog 500 reichen. Dort werden ja sogar nur 1 Wh-Impulse verwendet, also sekündlich nur auf 3600W genau. Da aber der Solarlog den Verbrauch schlussendlich nur alle 5 Minuten aufzeichnet, ergibt sich dadurch eine ausreichende Genauigkeit von 12W.
Die Auswertung der metrologischen LED ist dagegen eher für eine zukünftige Echtzeit-Anzeige gedacht. Die Schwierigkeit darin ist einzig, durch eine Interrupt-Steuerung die nötige Genauigkeit zu erreichen und dabei den nebenläufigen Zugriff auf die ermittelten Daten zu synchronisieren -- sprich, die Variablen als volatile zu deklarieren und beim Zugriff kurzzeitig die Interrupts abzuschalten. Dies wird nicht unbedingt in allem Quellcode berücksichtigt, der so durch das Internet kreucht und fleucht.
Hallo Sebastian,
habe mal ne Frage zu deinem Projekt. Und zwar habe ich einen EHZ001 Auslesekopf und suche nun nach einer Möglichkeit diesen Kopf an den Solarlog500 anzuschliesen. So wie ich das hier sehe klappt das bei dir. Kannst du mir bitte kurz Info geben wie das mit der Software geht?
Gruß
Ralf
Hallo Ralf,
im Prinzip sollte der Arduino das können, nur ist dafür noch etwas Bastelei nötig. Kannst Du die Zählerdaten mit hterm am PC empfangen (Einstellungen siehe http://www.mikrocontroller.net/topic/190517)? Manche neueren Zähler übertragen zudem die Daten im SML-Format, wodurch noch ein wenig Programmiererei gefordert ist.
Gruss, Sebastian
Hallo Sebastian,
mom. hängt es noch am Einbau da die EHZ001 nur für den rückwärtigen Einbau am Zähler gedacht ist. Und da müsste ich die Blombe am Zähler entfernen...
Also stehe ich noch ganz am Anfang...und hab 30€ für die Katz ausgegeben...
Gruß
Ralf
Hallo Sebastian,
sorry, für die verspätete Antwort. Habe mich der Sache noch einmal angenommen und habe was entdeckt was mir evtl. helfen könnte: http://store.arduino.cc/eu/index.php?main_page=product_info&cPath=11_12&products_id=142
Das Ethernetboard mit PoE. Da wären dann die Stromprobleme gelöst, da bei mir nicht weit weg vom Solarlog ein PoE Switch hängt.
Jetzt würde ich hergehen die Infrarot Schaltung von dir nachbauen und an den Arduino hängen da die EHZ001 Schnittstelle noch nicht eingebaut ist und vermutlich auch nicht passt da die Zählerhalterung eine Ältere ist.
Zu meinen Fragen:
- was meinst du geht das mit dem Strom?
- kann man über das Netz dann auch Daten empfangen?
- geht das Bord um 1 EHZ auszulesen?
- was muss ich alles programmieren?
Hoffe du kannst mir weiter helfen.
Gruß
Ralf
http://sebastians-blog.wangnick.de//comment.php?type=trackback&entry_id=2
Ma tutto in krucco ... uffi ...
There is a draft article in English at http://arduino.cc/playground/Main/Ehz2s0?action=diff.
Moreover, the source code is completely in English, so not really tutto in krucco :)
Hallo Sebastian,
vielen Dank für diesen sehr informativen Blog.
Ich habe einen zusätzlichen privaten S0-Zähler zur Messung des Strombezugs installiert und diesen an die S0-Schnittstelle meines Solarlog 200 angeschlossen. Ich habe das ebenfalls das Problem, dass das Solarlog in 90% der Zeit die S0-Schnittstelle offline schaltet:
http://energiethemen.blogspot.com/2011/12/solarlog-s0-schnittstelle-geht.html
Hast Du inzwischen die Ursache und evtl. sogar eine Lösung gefunden?
Bei mir ist im Januar der Austausch des Solarlog und des S0-Zählers geplant mit der Hoffnung, dass das Problem dann verschwindet.
Hallo Sebastian,
ich vermute, daß dein Solarlog nachts nur Offline meldet, weil der DSL-Router sich um diese Zeit meist vom Internet trennt, um neu zu verbinden.
Vielleicht erklärt das die Ausgabe.
Sehr interessante Seite ansonsten, bin selbst gerade dabei meine zwei Zähler (Eigenverbrauch 11kw PV-Anlage) optisch auszulesen, habe leider auch das kurze Protokoll.
Ich versuche das ganze mit einem Atmega-Board ins Netzwerk zu bringen.
Gruß,
Sascha
Hi,
klasse Bericht :-) sehr interessant. Ich wollte dir nur eine Info nachschieben, falls du diese noch nicht kanntest.
Jeder SolarLog rebootet einmal nacht um 3 Uhr, damit seine Datenbank bei diesem Reboot konsolidiert, bzw. bereinigt wird, falls irgendwelche Daten quer liegen ;-)
Ich hoffe geholfen zu haben und vielen Dank für deinen Bericht.
Gruß
Habib
Hallo Sascha,
habe heute die ersten Versuche unternommen unserem Hager eHZ-IW8 Zweirichtungszähler die ersten Daten zu entlocken - leider ohne Erfolg.
Der serielle Anschluss über Widerstand und Fototransistor war auch schnell gemacht, als Testsoftware für den PC habe ich libehz genommen und mittels
int iFlags;
// turn on DTR
iFlags = TIOCM_DTR;
ioctl(tty_fd, TIOCMBIS, &iFlags);
auch DTR auf Spannung geschaltet. Eine kleine LED in Reihe zum Fototransistor zeigt auch schön den Datenempfang im Sekundentakt -> doch auf Empfangsseite der RS-232 ist absolute Funkstille. Habe schließlich den TTL Wandler von Pollin dazwischengeschaltet und den Fototransistor mit 5V angesteuert, leider auch hier, der PC zeigt nichts, auch mittels HTERM nicht.
Hattest du solche Erfahrungen auch zwischenzeitlich? Den Widerstand hatte ich vorübergehend auf 50, 330, 1k Ohm variiert, keine Änderung. Ist der fließende Collector Emitter Strom einfach zu gering? Hast du evtl. ein anderes, einfaches Konsolenprogramm zum testen verwendet?
Grüße Mark
Vielleicht mal ohne die LED in Reihe probieren, um den Spannungsabfall zu vermeiden?
Hallo Mark,
ich lese die Daten mittels Seriell->USB-Adapter mit der Software "Putty" aus. damit lässt sich der Empfang auch gleich auf ein Netzlaufwerk loggen.
Letztendlich möchte ich allerdings den Laptop durch eine kleinere Hardware wie z.b. das AVR-NetIO ersetzen.
Mir fehlt derzeit lediglich die Zeit, mich an die Umsetzung zu machen...
Gruß