Zum Inhalt springen

LED-NIXIE als Anzeige für die Produktionsdaten einer Photovoltaikanlage

Seit ein paar Monaten bin ich stolzer Besitzer einer 18 kWp Photovoltaikanlage. Um zu visualisieren, wieviel diese produziert und wie hoch mein aktueller Stromverbrauch ist, wollte ich eine repräsentative Anzeige im Haus haben. Damit war die Idee geboren, mir dafür eine LED-Nixie umzubauen. Wie diese Anzeige in Aktion aussieht, zeigt folgendes Video:

Demonstationsvideo zur Anzeige der Werte auf der LED-Nixie

Falls jemand solch eine Anzeige nachbauen möchte, findet er hier meine Vorgehensweise. Aber zuvor eine kleine Warnung: Hierbei handelt es sich um kein einfaches Schritt-für-Schritt Tutorial mit Erfolgsgarantie. Ohne allgemeine Linux-Kenntnisse und ein paar rudimentären Programmierkenntnissen ist dieses Projekt nicht zum Nachbau geeignet.

benötigte Bauteile

  1. Ein Raspberry Pi 2 oder neuer
  2. Eine LED-Nixie passender Größe von z.B. https://www.led-genial.de/LED-Nixie . Ich habe mir dort die solderfree (ohne Lötarbeiten) LED-Nixie-M mit dem einfachsten Controller (dieser wird später durch den Raspberry Pi ersetzt) gekauft. Diese LED-Nixie hat 6 Stellen. Da alle Ausgaben in Watt erfolgen und meine Anlage niemals 6 stellig werden kann, hätte eigentlich auch eine fünfstellige LED-Nixie gereicht. Leider war so eine aber nicht im Angebot. Technisch gesehen ist so eine LED-Nixie eine hübsche Verpackung für einen WS281X-kompatiblen LED-Streifen.
  3. Drei Verbindungskabel um die GPIO-Leiste des Raspberry Pi mit den Kabeln der LED-Nixie zu verbinden.

benötigte Software

Um verschiedene Wechselrichter auszulesen, gibt es von Ulrich Kunz das Projekt solaranzeige.de . Dieser unterstützt auch meinen Wechselrichter von SolarEdge. Auf seiner Homepage bietet er fertige Images seiner Software für den Raspberry Pi an.

allgemeine Vorgehen

1. LED-Nixie montieren

Montiere die LED-Nixie gemäß der Anleitung und probiert diese mit dem mitgelieferten Controller aus.

2. Solaranzeige einrichten

Installiere die Solaranzeige auf dem Raspberry Pi und binde dort den eigenen Wechselrichter ein. Alle dazu benötigten Informationen befinden sich auf den Webseiten der Solaranzeige.

3. Raspberry Pi mit LED-Nixie verbinden

Jetzt ist es Zeit die LED-Nixie an den Raspberry Pi anzuschließen. Das erfordert ein bisschen Bastelei, ist aber nicht weiter kompliziert. Ich habe mich hier an dem Tutorial von StaticFloat orientiert. Dazu habe ich das Anschlusskabel der LED-Nixie einfach abgeklemmt und neu angeschlossen. Auf ein separates Netzteil zur Stromversorgung der LEDs habe ich verzichtet, da die LED-Nixie pro Zahl nur zwei LEDs ansteuert. Es leuchten also maximal 6 Zahlen mit jeweils 2 LEDs. Diese Energiemenge kann der Raspberry Pi locker selber zur Verfügung stellen. In seiner einfachsten Verkabelungsform sieht das Ganze dann so aus:

direkter Anschluss der LED-Nixie an einen Raspberry Pi

Anschließend bringe aus obigem Tutorial das Skript melodie.py zum laufen. Dieses wird verschiedene Farbmuster an die LED-Nixie schicken.

4. Werte von der Solaranzeige an die LED-Nixie übergeben

Ab hier sollte nun die LED-Nixie montiert und mit dem Raspberry Pi verbunden sein. Außerdem sollte das Skript melodie.py erfolgreich bunte Muster auf der LED-Nixie ausgegeben haben.

Als nächstes erstelle auf dem Raspberry die Datei solaranzeige2lednixie.py mit folgendem Inhalt:

#!/usr/bin/env python3
# NeoPixel library to connect a led-nixie to solaranzeige
# Author: Harald Popke (harald.popke@me.com)

import time
from rpi_ws281x import *
import argparse
 
# LED strip configuration:
LED_COUNT = 60 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
#LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 100 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53

def digit_1(number, color):
    for i in range(0,10):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(5,color)
    elif number == 1:
        strip.setPixelColor(0,color)
    elif number == 2:
        strip.setPixelColor(6,color)
    elif number == 3:
        strip.setPixelColor(1,color)
    elif number == 4:
        strip.setPixelColor(7,color)
    elif number == 5:
        strip.setPixelColor(2,color)
    elif number == 6:
        strip.setPixelColor(8,color)
    elif number == 7:
        strip.setPixelColor(3,color)
    elif number == 8:
        strip.setPixelColor(9,color)
    elif number == 9:
        strip.setPixelColor(4,color)
            
    strip.show()

def digit_2(number, color):
    for i in range(10,20):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(15,color)
    elif number == 1:
        strip.setPixelColor(10,color)
    elif number == 2:
        strip.setPixelColor(16,color)
    elif number == 3:
        strip.setPixelColor(11,color)
    elif number == 4:
        strip.setPixelColor(17,color)
    elif number == 5:
        strip.setPixelColor(12,color)
    elif number == 6:
        strip.setPixelColor(18,color)
    elif number == 7:
        strip.setPixelColor(13,color)
    elif number == 8:
        strip.setPixelColor(19,color)
    elif number == 9:
        strip.setPixelColor(14,color)
            
    strip.show()

def digit_3(number, color):
    for i in range(20,30):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(25,color)
    elif number == 1:
        strip.setPixelColor(20,color)
    elif number == 2:
        strip.setPixelColor(26,color)
    elif number == 3:
        strip.setPixelColor(21,color)
    elif number == 4:
        strip.setPixelColor(27,color)
    elif number == 5:
        strip.setPixelColor(22,color)
    elif number == 6:
        strip.setPixelColor(28,color)
    elif number == 7:
        strip.setPixelColor(23,color)
    elif number == 8:
        strip.setPixelColor(29,color)
    elif number == 9:
        strip.setPixelColor(24,color)
            
    strip.show()

def digit_4(number, color):
    for i in range(30,40):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(35,color)
    elif number == 1:
        strip.setPixelColor(30,color)
    elif number == 2:
        strip.setPixelColor(36,color)
    elif number == 3:
        strip.setPixelColor(31,color)
    elif number == 4:
        strip.setPixelColor(37,color)
    elif number == 5:
        strip.setPixelColor(32,color)
    elif number == 6:
        strip.setPixelColor(38,color)
    elif number == 7:
        strip.setPixelColor(33,color)
    elif number == 8:
        strip.setPixelColor(39,color)
    elif number == 9:
        strip.setPixelColor(34,color)
            
    strip.show()

def digit_5(number, color):
    for i in range(40,50):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(45,color)
    elif number == 1:
        strip.setPixelColor(40,color)
    elif number == 2:
        strip.setPixelColor(46,color)
    elif number == 3:
        strip.setPixelColor(41,color)
    elif number == 4:
        strip.setPixelColor(47,color)
    elif number == 5:
        strip.setPixelColor(42,color)
    elif number == 6:
        strip.setPixelColor(48,color)
    elif number == 7:
        strip.setPixelColor(43,color)
    elif number == 8:
        strip.setPixelColor(49,color)
    elif number == 9:
        strip.setPixelColor(44,color)
            
    strip.show()

def digit_6(number, color):
    for i in range(50,60):
        strip.setPixelColor(i, Color(0,0,0))
    if number == 0:
         strip.setPixelColor(55,color)
    elif number == 1:
        strip.setPixelColor(50,color)
    elif number == 2:
        strip.setPixelColor(56,color)
    elif number == 3:
        strip.setPixelColor(51,color)
    elif number == 4:
        strip.setPixelColor(57,color)
    elif number == 5:
        strip.setPixelColor(52,color)
    elif number == 6:
        strip.setPixelColor(58,color)
    elif number == 7:
        strip.setPixelColor(53,color)
    elif number == 8:
        strip.setPixelColor(59,color)
    elif number == 9:
        strip.setPixelColor(54,color)
            
    strip.show()

def parse_number(number, color, old_number=""):
    for i in range(0,LED_COUNT):
        strip.setPixelColor(i, Color(0,0,0))

    if len(number) > 6:
        return false
    position = 6 - len(number)
    i = 0
#    print(number)
#    print(old_number)
    while i < 6:
        if position == 0:
            digit_1(int(number[i]),color)
        elif position == 1:
            digit_2(int(number[i]),color)
        elif position == 2:
            digit_3(int(number[i]),color)
        elif position == 3:
            digit_4(int(number[i]),color)
        elif position == 4:
            digit_5(int(number[i]),color)
        elif position == 5:
            digit_6(int(number[i]),color)            

        position += 1
        i += 1
   
# Main program logic follows:
if __name__ == '__main__':
    # Process arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('verbrauch', help='Value 0-99999 which should be displayed on the LED-Nixie')
    parser.add_argument('leistung', help='Value 0-99999 which should be displayed on the LED-Nixie')
    args = parser.parse_args()
 
    strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
    strip.begin()
 
#    parse_number("220381")
einspeisung = int(args.leistung) - int(args.verbrauch) 
if int(args.leistung) > 0:
    # Orange für den aktuellen Verbrauch
    parse_number(args.verbrauch, Color(255,69,0))
    time.sleep(4)
    # FH-Aachen grün für die Produktion
    parse_number(args.leistung, Color(0,181,173))
    time.sleep(4)

# Lila wenn Einspeisung größer als 4000
if einspeisung > 4000:
    parse_number(str(einspeisung), Color(162,0,255))
# Blau wenn Einspeisung größer als 2000
elif einspeisung > 2000:
    parse_number(str(einspeisung), Color(8,0,255))
# Grün wenn Einspeisung größer als 0
elif einspeisung > 0:
    parse_number(str(einspeisung), Color(0,255,0))
#Rot wenn Zahl kleiner Null
elif einspeisung < 0:
    parse_number(str(einspeisung * -1), Color(255,0,0))

Angenommen der aktuelle Verbrauch beträgt 200W und die Leistung der Photovoltaikanlage liegt bei 500W würde der Aufruf des Skriptes so aussehen:
root@raspberrypi:/home/pi# python3 solaranzeige2lednixie.py 200 500

Es sollten dann drei Werte auf der LED-Nixie ausgegeben werden. Zunächst eine orange 200 für den aktuellen Verbrauch, dann eine grünliche 500 für die Produktion und zuletzt eine grüne 300 für den aktuellen Überschuss. Sollten euch die Farben nicht gefallen, könnt ihr dieser einfach im Skript ändern. Ebenso die Helligkeit oder die Anzeigedauer.

Jetzt müssen nur noch die anzuzeigenden Werte von der Solaranzeige an das Skript übergeben werden. Hierfür habe ich quick & dirty einfach den Programmcode der Solaranzeige um den Skriptaufruf ergänzt. Das war für meinen SolarEdge-Wechselrichter in der Datei /var/www/html/solaredge_serie.php an der Stelle mit unten stehendem Inhalt. Dort habe ich die grünen Funktionsaufrufe ergänzt.


 /****************************************************************************
  //  InfluxDB  Zugangsdaten ...stehen in der user.config.php
  //  falls nicht, sind das hier die default Werte.
  ****************************************************************************/
  $aktuelleDaten["InfluxAdresse"] = $InfluxAdresse;
  $aktuelleDaten["InfluxPort"] = $InfluxPort;
  $aktuelleDaten["InfluxUser"] =  $InfluxUser;
  $aktuelleDaten["InfluxPassword"] = $InfluxPassword;
  $aktuelleDaten["InfluxDBName"] = $InfluxDBName;
  $aktuelleDaten["InfluxDaylight"] = $InfluxDaylight;
  $aktuelleDaten["InfluxDBLokal"] = $InfluxDBLokal;
  $aktuelleDaten["InfluxSSL"] = $InfluxSSL;
  $aktuelleDaten["Demodaten"] = false;



  $funktionen->log_schreiben(print_r($aktuelleDaten,1),"*- ",9);
  $params = "{$aktuelleDaten["AC_Verbrauch"]} {$aktuelleDaten["AC_Leistung"]}";
  exec("/usr/bin/python3 /home/pi/melodie.py $params > /dev/null &");

Sofern ihr einen anderen Wechselrichter verwendet, müsst ihr diese Anpassung in einer anderen Datei vornehmen. Der Aufbau der Dateien für die Wechselrichter und die Namen der Variablen sind aber immer sehr ähnlich. Sucht einfach nach dem Funktionsaufruf $funktionen->log_schreiben(print_r($aktuelleDaten,1),"*- ",9) (oder so ähnlich) und schreibt direkt dahinter die grünen Funktionsaufrufe.

Abschluss

So, ich hoffe ihr konntet das soweit umsetzen. Falls jemand trotz intensiver Bemühungen an einer Stelle nicht weiterkommt, kann er sich gerne bei mir melden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert