Seit einiger Zeit haben wir eine Photovoltaikanlage auf unserem Dach. Nicht nur der produzierte Strom reduziert die monatlichen Kosten, sondern der fast schon sportliche Ehrgeiz, Waschmaschine und Geschirrspüler erst ab einer bestimmten Menge an produzierten Strom einzuschalten (hier gibt es noch viel Potenzial für die Haussteuerung).
In unserem Koch- Essbereich gibt es zwar ein Tablet an der Wand, das auch die gewünschten Daten anzeigt. Aus einer größeren Distanz waren sie aber nicht mehr zu erkennen. Die Lösung war eine Matrixanzeige, die sich beim Letzten Einkauf überraschend in meinen Einkaufskorb geschlichen hat :-).
Teile, die ich benutzt habe:
Lolin NodeMCU v3
2 Matrixdisplay 8 x 32 mit I2C Anschluss
/*
Pinbelegung
nodemcu matrix
3v > VCC
G > GND
D7 > DIN
D4 > CS
D5 > CLK
*/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <stdlib.h>
#include <stdio.h>
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "semar_home"
#define WLAN_PASS "86910695262591702804"
String netzname = "kuechendisplay"; //Name, der im IP-Verzeichnis des Routers aufscheint
int pinCS = D4;
int numberOfHorizontalDisplays = 8;
int numberOfVerticalDisplays = 1;
char time_value[20];
String message;
double doublezahl;
String aussentemp;
String solarleist;
int lang;
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "192.168.178.36"
#define AIO_SERVERPORT 1883 // use 8883 for SSL
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
int wait = 5000; // In milliseconds between scroll movements
int spacer = 1;
int width = 5 + spacer; // The font width is 5 pixels
String SITE_WIDTH = "1000";
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT); //, AIO_USERNAME, AIO_KEY);
/****************************** Feeds ***************************************/
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe aussentempera = Adafruit_MQTT_Subscribe(&mqtt, "meinTopic/aussentempera");
Adafruit_MQTT_Subscribe solarstrom = Adafruit_MQTT_Subscribe(&mqtt, "meinTopic/solarstrom");
void MQTT_connect();
void setup() {
Serial.begin(115200);
Serial.println ("Start");
delay(10);
matrix.setIntensity(0); // Use a value between 0 and 15 for brightness
matrix.setRotation(0, 1); // The first display is position upside down
matrix.setRotation(1, 1); // The first display is position upside down
matrix.setRotation(2, 1); // The first display is position upside down
matrix.setRotation(3, 1); // The first display is position upside down
matrix.setRotation(4, 1); // The first display is position upside down
matrix.setRotation(5, 1); // The first display is position upside down
matrix.setRotation(6, 1); // The first display is position upside down
matrix.setRotation(7, 1); // The first display is position upside down
wait = 25;
message = "Temperaturanzeige (C) Sebastian Binder 2020!";
display_message(message);
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.hostname(netzname);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: "); Serial.println(WiFi.localIP());
// Setup MQTT subscription
mqtt.subscribe(&aussentempera );
mqtt.subscribe(&solarstrom);
}
uint32_t x=0;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &aussentempera) {
doublezahl = atof((char *)aussentempera.lastread);
aussentemp = String(doublezahl,1);
Serial.print ("Aussentemperatur = ");
Serial.println (aussentemp);
lang=(aussentemp.length());
matrix.fillScreen(LOW);
matrix.setCursor(32-(lang*width),0);
matrix.print (aussentemp);
matrix.write();
}
if (subscription == &solarstrom) {
Serial.println ("Solarstrom");
Serial.println((char *)solarstrom.lastread);
solarleist = (char *)solarstrom.lastread;
Serial.print ("Solarleistung = ");
Serial.println (solarleist);
lang=(solarleist.length());
matrix.setCursor(64-(lang*width),0);
matrix.print (solarleist);
matrix.write();
}
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
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; // center the text vertically
while ( x + width - spacer >= 0 && letter >= 0 ) {
if ( letter < message.length() ) {
matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // HIGH LOW means foreground ON, background OFF, reverse these to invert the display!
}
letter--;
x -= width;
}
matrix.write(); // Send bitmap to display
delay(wait / 2);
}
}
Die Zeilen 104 und 105 dienen lediglich dazu, die zweite Dezimalstelle zu entfernen. Dies ist notwendig, da auf den jeweils vier Elelementen nur 5 Zeichen angezeigt werden können. Dazu zählen auch Vorzeichen und Komma.
In Openhab habe ich eine Rule, die alle zwei Minuten die aktuellen Werte an den MQTT-Broker sendet.
val actions = getActions("mqtt", "mqtt:broker:a4d200c9")
actions.publishMQTT("meinTopic/aussentempera", aussentemp.state.toString)
actions.publishMQTT("meinTopic/solarstrom", PV_Current.state.toString)