Repowering-Upgrade für den digitalen Garten

Hier lagern Sie also, die aus der Einspeisevergütung gelaufenen PV-Anlagen (älter 20 Jahre):

Lager beim Solarteur

Einige Panele werden nun ihr Zweitleben im digitalen Garten fristen und ihren Beitrag zur autarken Energieversorgung leisten.

  1. Ausladen:

Alt-Panele im E-Mokka

  1. Reinschleppen
  1. Die PV-Versorgung des Klohäuschens mit den neuen, alten Panels optimieren.

Fortsetzung...

What powers my digital garden? ...and making solar Chili

Die "Pandemie" bringt meine Kollegen und mich im wöchentlichen Wechsel ins "Home-Office".

Jeder weiß, dass die wenigsten Menschen ein "Home-Office" haben, sondern sich in irgendwelchen Ecken oder Kellerräumen einen Platz geschaffen haben, an dem Sie mehr schlecht als recht ihre Arbeiten am Rechner verrichten können. Die eingeschränkten öffentlichen Freiheiten müssen glücklicherweise nicht im privaten Raum gelten und so ist es jedem gestattet die Art des mobilen Arbeitens zu gestalten.

Ein nahe gelegenes Wiesengrundstück bietet dazu folgende Annehmlichkeiten:

  • PV-Stromerzeugung für Licht, elektrische Heizung und elektrisches Kochen
  • Anbindung an dieses Interweb mittels LTE
  • WLAN-Versorgung auf dem gesamten Grundstück mittels alter Fritzboxen als APs
  • Sichere Einwahl ins Firmen-Netzwerk mittels VPN
  • Telefonische Erreichbarkeit unter meiner Büro-Festnetznummer des Arbeitgebers
  • Telefonische Erreichbarkeit unter einer separaten "Home-Office"-Festnetznummer
  • Eine Kaffeemaschine
  • Eine Trenn-Toilette
  • Einen Holzofen, falls die "Pandemie" auch noch im Winter 2022/23 "wüted"
  • Das Wichtigste: Gelegenheit zur Weiterentwicklung

Ich berichte weiter aus meinem "Digitalen Garten".

Stromkosten live auf LED-Matrixdisplay anzeigen

In Anbetracht rasant steigender Strompreise sollte es idealerweise einen gewissen erzieherischen Effekt in der Familie haben, die tatsächlichen Bezugskosten des laufenden Tages tagtäglich am Esstisch unter die Nase gerieben zu bekommen. Die Erkenntnis soll sein, die Stromkosten durch das eigene Verhalten beeinflussen zu können, anstelle diese als unveränderbar hinzunehmen.

Die Live-Anzeige der Stromkosten ist die ideale Ergänzung zu meinem früheren Projekt "Grünes Licht für den Eigenverbrauch". Artikel muss noch geschrieben werden

Die Umsetzung der Verbrauchsanzeige geschah innerhalb von 3 Tagen mit folgenden Mitteln:

Hardware:

ArtikelPreisBezugsquelleFunktion
Wemos D1 Mini6,99 €AZ-DeliveryMikrocontroller
LED Matrix9,49 €AZ-DeliveryAnzeigemodul
USB-Ladegerät0,00 €SchubladeSpannungsversorgung

Software:

ArtikelPreisBezugsquelleFunktion
Arduino IDE0,00 €DownloadEntwicklungsumgebung
ioBroker0,00 €HomepageGebäudeautomatisierung

Jetzt geht der Spass im ioBroker los 😀

Das folgende Script berechnet im Sekundentakt, diesen Takt gibt das SMA-EnergyMeter vor, die unterhalb des Codes abgebildeten Datenpunkte. Die für die Anzeige interessanten Datenpunkte werden gleichzeitig in das entsprechende MQTT-Topic geschrieben.

// Sektion Bezug

// Bezugszählerstand jeweils um Mitternacht
// in Datenpunkt pregardcounter24h festhalten
schedule('{"time":{"exactTime":true,"start":"00:00"},"period":{"days":1}}', async function () {
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.pregardcounter24h"/*Datenpunkte.Berechnungen.sma-em.pregardcounter24h*/, getState("sma-em.0.1900235801.pregardcounter").val, true);
});

// Bezugskosten des aktuellen Tages jeweils um 23:59 Uhr
// im Datenpunkt BezugskostenGestern festhalten. DP wird
// bei Änderung in history.0 für 2 Jahre gespeichert.
schedule('{"time":{"exactTime":true,"start":"23:59"},"period":{"days":1}}', async function () {
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.BezugskostenGestern"/*Datenpunkte.Berechnungen.sma-em.BezugskostenGestern*/, getState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.BezugskostenSeit24Uhr").val, true);
});

// Bezugskosten pro Tag seit Mitternacht in Euro in
// Datenpunkt BezugskostenSeit24Uhr schreiben / Aktueller
// Preis pro kWh 32,12 Cent (Maingau Januar 2022)
//
// binde: Wert automatisch in MQTT-Topic "MatrixDisplay1.text"
// kopieren (Anzeige in ESP8266-Matrix-Display im Wohnzimmer)
on({id: 'sma-em.0.1900235801.pregardcounter', change: "ne"}, async function (obj) {
  var value = obj.state.val;
  var oldValue = obj.oldState.val;
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.BezugskostenSeit24Uhr"/*Datenpunkte.Berechnungen.sma-em.BezugskostenSeit24Uhr*/, Math.round((parseFloat((parseFloat(getState("sma-em.0.1900235801.pregardcounter").val) - getState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.pregardcounter24h").val)) * 0.3212)*100)/100, true);
});
on({id: '0_userdata.0.Datenpunkte.Berechnungen.sma-em.BezugskostenSeit24Uhr', change: "ne"}, function (obj) {
  setState('mqtt.0.MatrixDisplay1.text', obj.state.val);
});


// Sektion Erzeugung

// Einspeisezählerstand jeweils um Mitternacht
// in Datenpunkt psurpluscounter24h festhalten
schedule('{"time":{"exactTime":true,"start":"00:00"},"period":{"days":1}}', async function () {
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.psurpluscounter24h"/*Datenpunkte.Berechnungen.sma-em.psurpluscounter24h*/, getState("sma-em.0.1900235801.psurpluscounter").val, true);
});

// Einspeiseverguetung des aktuellen Tages jeweils um 23:59
// Uhr im Datenpunkt EinspeiseverguetungGestern festhalten.
// DP wird bei Änderung in history.0 für 2 Jahre gespeichert.
schedule('{"time":{"exactTime":true,"start":"23:59"},"period":{"days":1}}', async function () {
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungGestern"/*Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungGestern*/, getState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungSeit24Uhr").val, true);
});

// Einspeiseverguetung pro Tag seit Mitternacht in Euro
// in Datenpunkt EinspeiseverguetungSeit24Uhr schreiben /
// Einspeisevergütung pro kWh 12,00 Cent (Inbetriebnahme 2016)
//
// binde: Wert automatisch in MQTT-Topic "MatrixDisplay1.text2"
// kopieren (Anzeige in ESP8266-Matrix-Display im Wohnzimmer)
on({id: 'sma-em.0.1900235801.psurpluscounter', change: "any"}, async function (obj) {
  var value = obj.state.val;
  var oldValue = obj.oldState.val;
  setState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungSeit24Uhr"/*Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungSeit24Uhr*/, Math.round((parseFloat((parseFloat(getState("sma-em.0.1900235801.psurpluscounter").val) - getState("0_userdata.0.Datenpunkte.Berechnungen.sma-em.psurpluscounter24h").val)) * 0.12)*100)/100, true);
});
on({id: '0_userdata.0.Datenpunkte.Berechnungen.sma-em.EinspeiseverguetungSeit24Uhr', change: "ne"}, function (obj) {
  setState('mqtt.0.MatrixDisplay1.text2', obj.state.val);
});

Ergebnis des obigen Salates sind die folgenden Datenpunkte:

Berechnete Datenpunkte im ioBroker

Sowie die zugehörigen MQTT-Topics:

Aus Datenpunkten befüllte MQTT-Topics

Nun geht die Sause in der Arduino-IDE weiter 😃

Die folgende Programmierung verleitet den ESP8266-Mikrocontroller auf der angeschlossenen LED-Matrix zur Darstellung der ganz unten im Video zu sehenden Teufelei:

#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <time.h>
#include <PubSubClient.h>

WiFiClient espClient; 
PubSubClient client(espClient); 

bool starte = false;
char tmp[50];
String Text = ""; // Variable Text wird angelegt.
char ssid[] = "Hier die SSID des heimischen WLANs eintragen";  //  SSID (name)
char pass[] = "Hier den Key des heimischen WLANs eintragen";       // password
const char* mqtt_server = "Hier die IP-Adresse des heimischen ioBrokers eintragen"; //Broker IP Address
const char* mqttUser = "Optional: MQTT-Benutzer"; // Broker Name
const char* mqttPassword = "Optional: MQTT-Passwort"; // Broker Passwort

void connect_to_MQTT() {
 client.setServer(mqtt_server, 1883);//MQTT Server, - Port
 client.setCallback(callback); // aktiviert das zuhören 
 // Solltet Ihr kein Benutzer/Passwort haben so müssen folgende Zeilen entfernt werden: 
 // (client.connect("MatrixDisplay1" , mqttUser, mqttPassword))
 // und mit folgender getauscht werden: 
 // if (client.connect("MatrixDisplay1");
  if (client.connect("MatrixDisplay1")) {
  Serial.println("Verbinde zum MQTT Server");
  } else {
  Serial.println("zu MQTT Server nicht verbunden ");
  if (!client.connect("MatrixDisplay1")) {
      Serial.print("Fehlgeschlagen, state=");
      Serial.print(client.state());
      Serial.println(" Versuch in 5 Sekunden nochmal");
      delay(5000);
    }
  }
  client.subscribe("MatrixDisplay1.text");
  client.subscribe("MatrixDisplay1.text2");
  client.subscribe("MatrixDisplay1.kWhLadenAktuell");
  // Es könne weitere Topics hinzugefügt werden! 
  // Alternativ steht folgende Alternative zur Verfügung: 
  //client.subscribe("topic/#"); --> es werden dann alle topics abonniert ( Beispiel: MatrixDisplay1/# ) Es werden alle Nachrichten aus Wohnzimmer empfangen! 
  
  //client.subscribe("MatrixDisplay1/woche");
  //client.subscribe("MatrixDisplay1/verbraucht");
  //client.subscribe("MatrixDisplay1/internet");
  //client.subscribe("MatrixDisplay1/zimmertemperatur");
}
    
int pinCS = D8; // CS PIN
int numberOfHorizontalDisplays = 4; //Display Anzahl
int numberOfVerticalDisplays   = 1; // Diplay höhen Anzahl
char time_value[20];
// LED Matrix Pin -> ESP8266 Pin
// Vcc            -> 3v / 5v
// Gnd            -> Gnd 
// DIN            -> D7 
// CS             -> D8  
// CLK            -> D5
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
int wait = 95; // In millis -> Scrollgeschwindigkeit! 
int spacer = 1;
int width  = 5 + spacer; // Die Panels haben 5 Pixel + Leerzeichen

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  
  connect_to_MQTT(); 
  
  configTime(1 * 3600, 0, "192.168.10.1", "pool.ntp.org"); // Zeitserver aus dem LAN und ein alternativer Zeitserver im Internet mit Festlegung der Zeitzone
  setenv("TZ", "CET-1CEST,M3.5.0/01,M10.5.0/02",1);
  matrix.setIntensity(5); // Lichtstärke einstellen! Bis 8 kann man sicherlich über den Wemos D1 mini ansteuern, alles darüber sollte das Netzteil aufgeteilt werden und direkt mit Strom versorgt werden!! 
  matrix.setRotation(0, 1);    
  matrix.setRotation(1, 1);    
  matrix.setRotation(2, 1);    
  matrix.setRotation(3, 1);    
}

void loop() {

  matrix.fillScreen(LOW);
  time_t now = time(nullptr);
  String time = String(ctime(&now));
  time.trim();
  Serial.println(time);
  time.substring(11,19).toCharArray(time_value, 10); 
  matrix.drawChar(2,0, time_value[0], HIGH,LOW,1); // H
  matrix.drawChar(8,0, time_value[1], HIGH,LOW,1); // HH
  matrix.drawChar(14,0,time_value[2], HIGH,LOW,1); // HH:
  matrix.drawChar(20,0,time_value[3], HIGH,LOW,1); // HH:M
  matrix.drawChar(26,0,time_value[4], HIGH,LOW,1); // HH:MM
  matrix.write(); // Bitmap an das Display senden.
  
  delay(2000);
  if (!client.connected()) {
  Serial.println("Keine Verbindung zum MQTT Server");
  connect_to_MQTT();
  }
  client.loop();
}
void display_message(String message){
   for ( int i = 0 ; i < width * message.length() + matrix.width() - spacer; i++ ) {
  //matrix.fillScreen(LOW);
  int letter = i / width;
  int x = (matrix.width() - 1) - i % width;
  int y = (matrix.height() - 8) / 2; // Zentriert die Ausgabe.
  while ( x + width - spacer >= 0 && letter >= 0 ) {
    if ( letter < message.length() ) {
    matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // HIGH LOW 
    }
    letter--;
    x -= width;
  }
  matrix.write(); // Bitmap an das Display senden.
  delay(wait/2);
  }
}
void callback(char* topic, byte* payload, unsigned int length) {
 // Zähler
 int i = 0;
 // Hilfsvariablen für die Convertierung der Nachricht in ein String
 char message_buff[100];
 
 Serial.println("Message arrived: topic: " + String(topic));
 Serial.println("Length: " + String(length,DEC));
 
 // Kopieren der Nachricht und erstellen eines Bytes mit abschließender \0
 for(i=0; i<length; i++) {
 message_buff[i] = payload[i];
 }
 message_buff[i] = '\0';
 
 // Konvertierung der Nachricht in ein String
 String msgString = String(message_buff);
 Serial.println("Payload: " + msgString);
 if (strcmp(topic,"MatrixDisplay1.text")==0){
  Text = "Stromkosten heute: " + msgString + " EUR";
  display_message(Text);
  }

  if (strcmp(topic,"MatrixDisplay1.text")==0){
  Text = "-" + msgString + " EUR";
  display_message(Text);
  }

 if (strcmp(topic,"MatrixDisplay1.text2")==0){
  Text = "Stromerzeugung heute: " + msgString + " EUR";
  display_message(Text);
  }

  if (strcmp(topic,"MatrixDisplay1.text2")==0){
  Text = "+" + msgString + " EUR";
  display_message(Text);
  }
  
  if (strcmp(topic,"MatrixDisplay1.kWhLadenAktuell")==0){
  Text = "E-Ladevorgang: " + msgString + " kWh";
  display_message(Text);
  }

  /*
  Für die Zukunft:
  Zum freimachen, das "/*" und am ende "* /" entfernen!
  
  ################################################ 
  ## Topic filtern und etwas bestimmtes machen! ##
  ################################################
  
  if (strcmp(topic,"display1.woche")==0){
  Text = "Woche Gesamt: " + msgString + "Std.";
  display_message(Text);
  display_message(Text);
  }
  if (strcmp(topic,"display1.zimmertemperatur")==0){
  Text = msgString + " Grad";
  display_message(Text);
  display_message(Text);
  long rssi = WiFi.RSSI();
  itoa(rssi,tmp,10);
  client.publish("display1/rssi",tmp);
  //display_message(Text);
  }
   
*/
 

Nun geht der Spass mit der Hardware und dem Anschliessen weiter :😍

Der Wemos D1 Mini, oder jeder andere ESP8266-Controller, wird nun anhand der im Arduino-Code festgelegten Pin-Belegung mit der LED-Matrix verbunden und per USB-Netzteil mit Spannung versorgt.

Ich bitte nun wirklich jede und jeden inständig, den im Bild zu sehenden Aufbau unter !!!KEINEN UMSTÄNDEN!!! nachzumachen. Es dient lediglich der Illustration wie man es !!!auf gar keinen Fall!!! machen darf! Danke!

Niemals nie nachmachen!

Zusammen mit dem alten Voltmeter aus dem Physikunterricht ergibt das eine zumindest interessante Kombination.

Nicht schön aber selten

Sozusagen als Abfallprodukt wird die Uhrzeit sowie die, bei aktivem Ladevorgang, an der Wallbox ins E-Auto geladene Energiemenge in kWh angezeigt.

Das Ergbnis des gesamten Reigens ist nun dies Video 😀

PS: Wenn die Anzeige im Winter auch schmerzt, so freue ich mich auf den Frühling und Sommer, wenn die Bezugskosten nahe 0 € bleiben dürften und die Familie live sieht, warum die PV-Anlage unbedingt sein musste.

Update: KfW 440 oder warum eine zweite Wallbox?

Nachdem seit Teil 1 drei Monate vergangen sind, kann ich berichten, dass die zweite Wallbox nun installiert und in Betrieb ist.

Das Ergebnis sieht folgendermaßen aus:

Vorher: Vorher Nachher: Nachher

Der Solarteur meines Vertrauens hat mal wieder sehr gute Dienste bei den Anschlußarbeiten geleistet und ca. 7 Stunden gebraucht. Diese Zeit bzw.zu entlohnende Arbeitsstunden sollte man, je nach örtlichen Gegebenheiten, also in die Kalkulation aufnehmen, wenn man eine private Wallbox haben möchte.

Zusätzliche Zeit und materiellen Aufwand hat mein Wunsch erfordert, eine zusätzliche Schuko-Doppeldose haben zu wollen. Irgendwann wird sich diese sicherlich noch als nützlich erweisen.

Wetter- und Vandalismus-Schutz: Wetter- und Vandalismus-Schutz

Rückansicht der Unterverteilung Wallbox und Schuko-Dose mit separater 220V-Absicherung: Unterverteilung Rückwand

Laut dem Installateur ist es für die Inanspruchnahme der KfW-Förderung notwendig, eine drahtgebundene Netzwerkverbindung am Installationsort der Wallbox vorzubereiten. Wir haben also gleich ein Cat6-Kabel durch das Leerrohr in die Installationsbox gezogen. Der go-e Charger wird per W-Lan ins Netz gebracht, aber LAN kann an der Stelle sicherlich nicht schaden.

Die Nachweise habe ich im KfW-Portal hochgeladen und warte nun auf Auszahlung des Förderbetrages. Nach deren Eingang hat die zweite Wallbox, auch durch die Erbrachte Eingenleistung (siehe Teil 1), insgesamt "lediglich" 400,00 € gekostet.

Das Förderprogramm "KfW 440" wurde am 27.10.2021 aufgrund erschöpfter Fördermittel beendet. Bis dahin gestellte Anträge werden nach Umsetzung ausgezahlt.

Windows 10: Kein Ton / No Sound

Wer wie ich, seit einem bestimmten Windows-Update unter Windows 10 (bei mir Enterprise) plötzlich keine Sound-Ausgabe mehr hat, findet hier möglicherweise die Lösung.

Ich war jedenfalls mehr als 2 Monate am Dienst-Notebook ohne Ton und Mikro unterwegs, was derzeit bei der stark gestiegenen Anzahl von Videokonferenzen und Webinaren natürlich ganz besonders hilfreich ist...

Symptomatisch war, dass zwar der Geräte-Manager keinerlei Auffälligkeiten zeigte, das Lautsprechersymbol in der Taskleiste jedoch ein rotes Kreuz mit dem Hinweis "Kein Audioausgabegerät installiert" und "Lautsprechereinrichtung (UNKNOWN)" zierte. Die dabei angebotene Windows-Problembehandlung glänzte erneut durch Wirkungslosigkeit.

Das folgende strukturierte Vorgehen zur Fehlerbehebung hat bei mir rein gar nichts gebracht, könnte in Deinem Fall aber vielleicht trotzdem helfen:

  • Treiber löschen und von der Herstellerseite frisch heruntergeladene Soundtreiber installieren
  • Sicherheitshalber nachschauen, ob der Onboard-Sound durch irgendeinen Zufall im BIOS deaktiviert wurde
  • Wenn vorhanden, die für Dein Gerät aktuelle BIOS-Version installieren (in der Verzweiflung versucht man alles)
  • Den Status der Windows-Dienste "Windows-Audio" und "Windows-Audio-Endpunkterstellung" auf "Wird ausgeführt" prüfen
  • Schauen, ob Dein Hersteller ein Tool bereitstellt, dass Treiber für Dein Gerät automatisch passend herunterlädt und installiert (z.B. Fujitsu DeskUpdate)
  • Alle zuletzt installierten Windows-Updates deinstallieren, auf einen früheren Wiederherstellungspunkt oder ein selbstverständlich vorhandenes Backup zurücksetzen
  • Ebenfalls zur Sicherheit, dass nicht irgendwas an der Hardware faul ist, ein beliebiges Live-Linux von USB-Stick starten und sicherstellen, dass Audio funktioniert

Nachdem ich kurz davor war beim Chef ein neues Notebook zu erbetteln bzw. sogar bereit gewesen wäre Windows 11 zu installieren, in der Hoffnung der Fehler würde dadurch verschwinden, unternahm ich noch einen letzten Anlauf. Diese Hartnäckigkeit sollte belohnt werden!

Die Lösung in meinem Fall:

  1. Öffnen einer Kommandozeile mit Admin-Rechten (Rechtsklick "Als Administrator ausführen")
  2. Eingabe von net localgroup Administratoren /add networkservice (bei deutschem Windows, ansonsten den Gruppennamen der Sprache anpassen) -> Enter
  3. Eingabe von net localgroup Administratoren /add localservice ("") -> Enter
  4. exit
  5. Reboot des Rechners

Ich kann nicht erklären, was da zu irgendeinem Zeitpunkt beim Update schief läuft, gehört aber in die Kategorie "zum Kübeln".

Ich hoffe, dass Du nun auch wieder Audio unter Windows hast :) Soll ja manchmal ganz nützlich sein...