Led Matrix Display V4

Begonnen von hankyzoolander, 29 Juli 2019, 14:05:19

Vorheriges Thema - Nächstes Thema

hankyzoolander

Hallo,
nach langer Zeit bin ich endlich dazu gekommen die Led Matrix auf mqtt umzubauen.
Vorher lief ein webserver mit eingabefeld darauf, in welches ein notify alle Minute die Uhrzeit pushte.
Das geht noch besser!

Da es leider noch kein fhem Modul gibt welches die perfekte einbindung der max7219 Matrix Module erlaubt, musste somit eine"erträgliche" Lösung her.

In fhem wird ein mqtt2_device angelegt welches alle Funktionen in einer setList enthält, sowie alle Readings zum weiterverarbeiten.
Am Gehäuse befinden sich noch 2 Microtaster. Einer für scrolling an/off, der andere dim Stufen 0-10.
Auf der Rückseite des Gehäuses sind "normale" RGB Leds "Strip" aufgeklebt, welche über einen ULN Transistor am Wemos D1 mini angeschlossen sind.
Die Matrix besteht aus 2 max7219 4er Modulen. Also insgesamt 8 Anzeigen. Eine Auflösung 64x8 Pixel.

Funktionen:
LedMatrix/text  -  Text auf die Matrix senden.
RGBPower        -  RGB Leds aus schalten.
dim                   -  Dimmen über einen Slider der Stufen 0 bis 10
power              -  Matrix aus schalten"Display dunkel"
rgb                   -  Leds ein schalten mit den hinterlegten RGB Werten "FF0000,00FF00,0000FF,ffff00" (rot,grün,blau,gelb)
scrolling           -  schaltet das Display scrollen an oder aus
scrollspeed      -  Scroll Geschwindigkeit der Matrix mit einem Slider einstellbar. In 5er Schritten von 5-100
time                 -  Es wird der Unix Timestamp an den ESP gesendet,dieser rechnet ihn in Stunden:Minuten:Sekunden um und zeigt ihn auf der Matrix.Eine Ticker Funktion in Code zählt die Sekunden hoch,
                           so das die Uhrzeit quasi autark ohne fhem läuft.

Readings:
dim                -  wert 0 bis 10
rgb                -  (rgb wert) z.b. FF0000
scrolling        -  on
scrollspeed   -  z.b. 20
text               - z.b. fhem

Die Funktion time,power und RGBPower haben kein eigenes Reading.
Ist time gesetzt, steht im Reading text zeit.
Ist power off gesetzt, steht im Reading text OFF.
Ist RGBPower off gesetzt, steht im Reading rgb OFF.

Anbei noch einige Bilder.
Ich hoffe ich habe nichts vergessen zu erwähnen.
Würde mich freuen wenn es euch anregt das Projekt nachzubauen.(eine Led Matrix sollte jeder haben)  ;)

Zum kompilieren werden noch die Dateien Ticker.cpp und die Ticker.h benötigt

Wlan-SSID und Wlan Passwort ändern sowie die mqttServer IP.

Einbindung in fhem:
defmod matrix1 MQTT2_DEVICE
attr matrix1 IODev MQTT_Server

attr matrix1 alias Matrix Display klein

attr matrix1 icon led_matrix@green

attr matrix1 readingList LedMatrix/text:.* text
LedMatrix/RGB:.* rgb
LedMatrix/dim:.* dim
LedMatrix/scrolling:.* scrolling
LedMatrix/scrollspeed:.* scrollspeed

attr matrix1 room Wohnung

attr matrix1 setList LedMatrix/text $EVENT
dim:slider,0,1,10 LedMatrix/dim $EVTPART1
power:off LedMatrix/power $EVTPART1
scrolling:on,off LedMatrix/scrolling $EVTPART1
scrollspeed:slider,5,5,100 LedMatrix/scrollspeed $EVTPART1
rgb:FF0000,00FF00,0000FF,ffff00 LedMatrix/RGB $EVTPART1
RGBPower:off LedMatrix/RGBPower $EVTPART1
time:noArg {"LedMatrix/time ".time()}

attr matrix1 stateFormat text


Als libery dient die LEDMatrixDriver.hpp
Zur Wlanverbindung die ESP8266WiFi.h
Zur mqttverbindung PubSubClient.h


Hier der Code für den Wemos d1 mini
#include <LEDMatrixDriver.hpp>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ticker.h>


const char* ssid = "SSID";
const char* password = "wlan-passwort";
const char* mqtt_server = "192.168.0.23";
// folgende zeilen und zeile ;WiFi.config(ip,gateway,subnet); auskommentieren für feste IP.
// IPAddress ip(192, 168, 0, 177);
// IPAddress gateway(192, 168, 0, 1);
// IPAddress subnet(255, 255, 255, 0);

WiFiClient espClient;
PubSubClient client(espClient);
time_t globaltime;
Ticker timeTicker;


const char* TOPIC_TEXT = "LedMatrix/text";
const char* TOPIC_MATRIXPOWER = "LedMatrix/power";
const char* TOPIC_SCROLLING = "LedMatrix/scrolling";
const char* TOPIC_BRIGHTNESS = "LedMatrix/dim";
const char* TOPIC_SCROLLSPEED = "LedMatrix/scrollspeed";
const char* TOPIC_RGB = "LedMatrix/RGB";
const char* TOPIC_RGBPOWER = "LedMatrix/RGBPower";
const char* TOPIC_TIME = "LedMatrix/time";

/*
   ESP8266 pins need wired are below:
   DIN (data in) on Matrix ---> D7 or MOSI on ESP8266
   Clock(CLK) on Matrix --> D5 or SCK on ESP8266
   CS pin on Matrix define below  --->( pick 15 on esp8266)
*/
const uint8_t LEDMATRIX_CS_PIN = 15;

// Define LED Matrix dimensions (0-n) - eg: 32x8 = 31x7
const int LEDMATRIX_WIDTH = 64;
const int LEDMATRIX_HEIGHT = 8;
const int LEDMATRIX_SEGMENTS = 8;
const int RED = D2;
const int GREEN = D3;
const int BLUE = D4;

// The LEDMatrixDriver class instance
LEDMatrixDriver lmd(LEDMATRIX_SEGMENTS, LEDMATRIX_CS_PIN);

// Block font 8x8
byte  font[][8] = {
  { 0, 0, 0, 0, 0, 0, 0, 0 }, //space
  { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00},   // U+0021 (!)
  { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0022 (")
  { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00},   // U+0023 (#)
  { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00},   // U+0024 ($)
  { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00},   // U+0025 (%)
  { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00},   // U+0026 (&)
  { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0027 (')
  { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00},   // U+0028 (()
  { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00},   // U+0029 ())
  { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00},   // U+002A (*)
  { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00},   // U+002B (+)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06},   // U+002C (,)
  { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},   // U+002D (-)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+002E (.)
  { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},   // U+002F (/)
  { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},   // U+0030 (0)
  { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},   // U+0031 (1)
  { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},   // U+0032 (2)
  { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},   // U+0033 (3)
  { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},   // U+0034 (4)
  { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},   // U+0035 (5)
  { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},   // U+0036 (6)
  { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},   // U+0037 (7)
  { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},   // U+0038 (8)
  { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},   // U+0039 (9)
  { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+003A (:)
  { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06},   // U+003B (//)
  { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00},   // U+003C (<)
  { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00},   // U+003D (=)
  { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00},   // U+003E (>)
  { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00},   // U+003F (?)
  { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00},   // U+0040 (@)
  { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},   // U+0041 (A)
  { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},   // U+0042 (B)
  { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},   // U+0043 (C)
  { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},   // U+0044 (D)
  { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},   // U+0045 (E)
  { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},   // U+0046 (F)
  { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},   // U+0047 (G)
  { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},   // U+0048 (H)
  { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0049 (I)
  { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},   // U+004A (J)
  { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},   // U+004B (K)
  { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},   // U+004C (L)
  { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},   // U+004D (M)
  { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},   // U+004E (N)
  { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},   // U+004F (O)
  { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},   // U+0050 (P)
  { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},   // U+0051 (Q)
  { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},   // U+0052 (R)
  { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},   // U+0053 (S)
  { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0054 (T)
  { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},   // U+0055 (U)
  { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0056 (V)
  { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},   // U+0057 (W)
  { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},   // U+0058 (X)
  { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},   // U+0059 (Y)
  { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},   // U+005A (Z)
  { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00},   // U+005B ([)
  { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00},   // U+005C (\)
  { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00},   // U+005D (])
  { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00},   // U+005E (^)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},   // U+005F (_)
  { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0060 (`)
  { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},   // U+0061 (a)
  { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},   // U+0062 (b)
  { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},   // U+0063 (c)
  { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},   // U+0064 (d)
  { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},   // U+0065 (e)
  { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},   // U+0066 (f)
  { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0067 (g)
  { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},   // U+0068 (h)
  { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0069 (i)
  { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},   // U+006A (j)
  { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},   // U+006B (k)
  { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+006C (l)
  { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},   // U+006D (m)
  { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},   // U+006E (n)
  { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},   // U+006F (o)
  { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},   // U+0070 (p)
  { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},   // U+0071 (q)
  { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},   // U+0072 (r)
  { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},   // U+0073 (s)
  { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},   // U+0074 (t)
  { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},   // U+0075 (u)
  { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0076 (v)
  { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},   // U+0077 (w)
  { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},   // U+0078 (x)
  { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0079 (y)
  { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},   // U+007A (z)
  { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00},   // U+007B ({)
  { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},   // U+007C (|)
  { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00},   // U+007D (})
  { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+007E (~) 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+007F (dummy)
  { 0x14, 0x3e, 0x55, 0x55, 0x55, 0x55, 0x41, 0x00},   // U+0080 (€)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0081 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0082 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0083 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0084 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0085 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0086 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0087 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0088 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0089 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008A (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008B (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008C (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008D (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008E (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+008F (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0090 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0091 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0092 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0093 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0094 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0095 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0096 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0097 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0098 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0099 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009A (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009B (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009C (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009D (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009E (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+009F (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A0 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A1 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A2 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A3 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A4 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A5 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A6 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A7 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A8 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00A9 (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AA (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AB (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AC (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AD (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AE (dummy)
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+00AF (dummy)
  { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00},   // U+00B0 (°)
};
int x = LEDMATRIX_WIDTH, y = 0; // start top left

// Marquee text
char text[75] = " Hello ";
int len = strlen(text);
// Marquee speed

// const int ANIM_DELAY = 60; TEST
int ANIM_DELAY = 60;
unsigned long myTime = millis();
unsigned long intro = millis();
IPAddress ip ;

int brightness = 0;
int scrollen = 1;
int buttonD0 = 0;
int lastbuttonD0 = 0;
int buttonD1 = 0;
int lastbuttonD1 = 0;
int red = 0;
int green = 0;
int blue = 0;
int rgb = 0x000000;

/* This function is called in loop but
    only does stuff when animimation delay
    is met.

    This will allow loop to do other thing instead
    of waiting for a delay to happen.

    Delay=bad programming.
*/

void setColor(int rgb) {
  analogWrite(RED, rgb >> 16);
  analogWrite(GREEN, rgb >> 8 & 0xFF);
  analogWrite(BLUE, rgb & 0xFF);
}

/**
   This draws a sprite to the given position using the width and height supplied (usually 8x8)
*/
void drawSprite( byte* sprite, int x, int y, int width, int height )
{
  // The mask is used to get the column bit from the sprite row
  byte mask = B10000000;

  for ( int iy = 0; iy < height; iy++ )
  {
    for ( int ix = 0; ix < width; ix++ )
    {
      //Yes my font is backwards so I swap it around.
      //lmd.setPixel(x + ix, y + iy, (bool)(sprite[iy] & mask ));
      lmd.setPixel(x + (width - ix), y + iy, (bool)(sprite[iy] & mask ));

      // shift the mask by one pixel to the right
      mask = mask >> 1;
    }

    // reset column mask
    mask = B10000000;
  }
}

/**
   This function draws a string of the given length to the given position.
*/
void drawString(char* text, int len, int x, int y )
{

  for ( int idx = 0; idx < len; idx ++ )
  {
    int c = text[idx] - 32;

    // stop if char is outside visible area
    if ( x + idx * 8  > LEDMATRIX_WIDTH )
      return;

    // only draw if char is visible
    if ( 8 + x + idx * 8 > 0 )
      drawSprite( font[c], x + idx * 8, y, 8, 8 );
  }
}

void displayText ( char * theText)
{
  if ( myTime + ANIM_DELAY < millis())
  {
    myTime = millis();
    // Draw the text to the current position
    if (scrollen == 1) drawString(theText, len, x, 0); else drawString(theText, len, 0, 0);
    // In case you wonder why we don't have to call lmd.clear() in every loop: The font has a opaque (black) background...
    // Toggle display of the new framebuffer
    lmd.display();
    // Advance to next coordinate
    if ( --x < len * -8 )
    {
      x = LEDMATRIX_WIDTH;
      lmd.clear();
    }
  }
}

void reconnect() { 
  while (!client.connected()) {               
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
           
      // subscription
      client.subscribe(TOPIC_TEXT);
      client.subscribe(TOPIC_BRIGHTNESS);
      client.subscribe(TOPIC_MATRIXPOWER);
      client.subscribe(TOPIC_SCROLLING);
      client.subscribe(TOPIC_SCROLLSPEED);
      client.subscribe(TOPIC_TIME);
      client.subscribe(TOPIC_RGB);
      client.subscribe(TOPIC_RGBPOWER);
    } else {     
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void timeToText(){
  struct tm* ptm = localtime(&globaltime);
  sprintf(text, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
  len = strlen(text);
}

void timer() {
      globaltime = globaltime + 1;
      timeToText();
   }


void callback(char* topic, byte* payload, unsigned int length) {   
    char* value = (char*) malloc(length + 1);   
    memcpy(value, payload, length);
    value[length] = 0;

   


    /* Topic: text */
    if (strcmp(topic, TOPIC_TEXT) == 0) {
      strcpy(text, value);
      len = length;
      timeTicker.detach();
      client.publish(TOPIC_TEXT, text);
    }

    /* Topic: MatrixPower */
    if (strcmp(topic, TOPIC_MATRIXPOWER) == 0) {
      if (strcmp("off", value) == 0) {
        timeTicker.detach();
        len = 0;
        client.publish(TOPIC_TEXT, "OFF");
      }
    }

    /* Topic: scrolling */
    if (strcmp(topic, TOPIC_SCROLLING) == 0) {
      if (strcmp("on", value) == 0) {
        scrollen = 1;
        client.publish(TOPIC_SCROLLING, "on");
      } else {
        scrollen = 0;
        client.publish(TOPIC_SCROLLING, "off");
      }
    }

    /* Topic: Scrollspeed */
    if (strcmp(topic, TOPIC_SCROLLSPEED) == 0) {
      ANIM_DELAY = atoi(value);
      client.publish(TOPIC_SCROLLSPEED, value);
    }   

    /* Topic: brightness */
    if (strcmp(topic, TOPIC_BRIGHTNESS) == 0) {
      brightness = atoi(value);
      client.publish(TOPIC_BRIGHTNESS, value);
    }

    /* Topic: RGB */
    if (strcmp(topic, TOPIC_RGB) == 0) {
      rgb = (int)strtol(value, NULL, 16);
      setColor(rgb);
      client.publish(TOPIC_RGB, value);
     
    }

    /* Topic: RGBPOWER */
    if (strcmp(topic, TOPIC_RGBPOWER) == 0) {
      if (strcmp("off", value) == 0) {
        setColor(0);
        client.publish(TOPIC_RGB, value);
      }
    }

    /* Topic: Time*/
    if (strcmp(topic, TOPIC_TIME) == 0) {
     globaltime = atoi(value);
     globaltime = globaltime + 2*  60*  60;
     timeToText();
     timeTicker.attach(1.0, timer);
     client.publish(TOPIC_TEXT, "zeit");
     scrollen = 0;

    }   

    free(value);
}




void setup() {

  pinMode(D0, OUTPUT); // Taster Helligkeit D0
  digitalWrite(D0, LOW);
  pinMode(D1, OUTPUT); // Taster Scrolling an/aus D1
  digitalWrite(D1, LOW);
  pinMode(RED, OUTPUT);
  digitalWrite(RED, LOW);
  pinMode(GREEN, OUTPUT);
  digitalWrite(GREEN, LOW);
  pinMode(BLUE, OUTPUT);
  digitalWrite(BLUE, LOW);



  //Initialize the display
  lmd.setEnabled(true);
  //lmd.setIntensity(brightness);   // 0 = low, 10 = high
  sprintf(text, "Connecting to %s", ssid);
  len = strlen(text);
  // Connect to WiFi network
  //WiFi.config(ip,gateway,subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    displayText(text);
    delay(ANIM_DELAY);
  }
 
 
  ip = WiFi.localIP();
  String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
  strcpy(text, ipStr.c_str());
  len = strlen(text);


  client.setServer(mqtt_server, 1884);
  client.setCallback(callback);

 
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  buttonD0 = digitalRead(D0); //D0
  buttonD1 = digitalRead(D1); //D1

   if (buttonD0 != lastbuttonD0) {
     if (buttonD0 == HIGH) {
       brightness++ ;
       delay(20);
     }
   }
   if (brightness > 10) brightness = 0;
   lastbuttonD0 = buttonD0;

  lmd.setIntensity(brightness);

   if (buttonD1 != lastbuttonD1) {
     if (buttonD1 == HIGH) {
       if (scrollen == 1) scrollen = 0; else scrollen = 1;
       lmd.clear();
       delay(20);
     }
   }
   lastbuttonD1 = buttonD1;



  displayText(text);
 
}













betateilchen  <--- my personal hero

pflock_y

Hallo hankyzoolander,
ich weiss dieser Beitrag ist schon etwas älter.  :o

Ich nutze deinen sketch seit ende 2019, läuft bestens.
Ich lassem mir über fhem Bewegungen/ Klingeln meiner Ring anzeigen, Sendernamen meiner VU, Temperatur und noch andere Sachen. Leider kommt es nach einem fhem update der MQTT pm´s zu komischen Funktionen der LED Matrix.
Ich habe versucht mich durch deinen sketch zu wühlen und den Fehler zu finden. Leider ohne jeglichen Erfolg.
Vielleicht weisst du eine Lösung.


vg
pflock_y

hankyzoolander

#2
Hallo, habe eine komplett überarbeitete Version davon erstellt.
Versuche euch den Code heute noch zur Verfügung zu stellen.
Habe mitlerweile auch die große matrix mit 32 Matrixmodulen(1,2m lang) fertig.
Code ist komplett neu, in und out effekte,dim,autarke uhr,schriftart,position,scrollingspeed,scrolling,rgb leds (neopixel) und und und ist jetzt alles möglich.
betateilchen  <--- my personal hero

hankyzoolander

Hallo, wie schon vorher geschrieben möchte ich euch die aktuelle Version der Matrix vorstellen und zum nachbau animieren.

Was jetzt möglich ist:
# dimmen per slider
# Text übergeben
# scrolling an/aus
#scrollgeschwindigkeit per slider
# rgb leds(neopixel)  (im moment nur feste farben,Lichtanimationen sind in Arbeit)
# rgb power (leds an/aus)
# effectIn (wie der text in die Anzeige reinkommt)
# effectOut (Wie der Text aus der Anzeige rausgeht)
# 2 verschiedene Schriftarten
# wiederholen an/aus
# pause
# position (Text links,mitte,rechts)
# power (Matrix an/aus)
# addText (quasi mehre zeilen Text oder werte an die Matrix senden)
# time (unix Timestamp wird an Matrix gesendet,Ticker zählt immer eine sekunde hoch)**

Es werden alle Funktionen mit readings zurückgegeben (somit ist ein weiteres einbinden kein problem).

An dieser Stelle kommt nun die sache mit den **
Habe es bis jetzt nicht hinbekommen die aktuelle Uhrzeit aus fhem zu bekommen.
Es wird immer nur der Unix Timestamp übergeben, was soweit auch nicht schlimm ist, da der timestamp im Code umgerechnet wird und die Uhrzeit dann auch angezeigt wird.
Aber wegen der blöden Zeitumstellung. Entweder geht die Uhr richtig oder halt ne Stunde vor oder nach(weiß gerade nicht mehr wie es im Code aktuell hinterlegt ist,da ich die Matrix bei der Umstellung immer neu geflasht hatte.
Aktuell habe ich es so gelöst, das ich mir ein topic auf time gesetzt habe und den umgerechneten timestamp per hand hinsende.
aber, ## es wird daran gearbeitet##
Klar könnte man die aktuelle Zeit auch online holen. Das ist aber nicht gewollt,fällt mal das Internet aus oder der Server ist nicht erreichbar, hätte man keine Uhrzeit.
Die Matrix soll alles nur im Heimnetz erledigen.

Weiterhin besteht die Auswahl DHCP oder feste IP Adresse.
nun mal zum eingemachten:

es werden folgende Libary´s gebraucht:
PubSubClient@2.7
MD_MAX72XX@3.1.0
MD_Parola@3.1.1
Adafruit NeoPixel@1.2.3

es werden 5 Dateien gebraucht:
config.h
effects.cpp
effects.h
fonts_data.h
main.cpp

Eure Config wie W-lan,ip,fhem ip,matrix größe,matrix pin,Neopixel pin,anzahl Neopixel leds werden in der config.h gemacht.

Anbei sind die 5 Dateien und noch ein paar screenshots.

Fhem:
In fhem wird ein MQTT2 DEVICE angelegt mit folgenden Inhalt

readingList
ESP8266Client:BigMatrix/status/dim:.* dim
ESP8266Client:BigMatrix/status/text:.* text
ESP8266Client:BigMatrix/status/scrolling:.* scrolling
ESP8266Client:BigMatrix/status/scrollspeed:.* scrollspeed
ESP8266Client:BigMatrix/status/RGB:.* RGB
ESP8266Client:BigMatrix/status/effect:.* effect
ESP8266Client:BigMatrix/status/position:.* position
ESP8266Client:BigMatrix/status/effectIn:.* effectIn
ESP8266Client:BigMatrix/status/effectOut:.* effectOut
ESP8266Client:BigMatrix/status/font:.* font
ESP8266Client:BigMatrix/status/repeat:.* repeat
ESP8266Client:BigMatrix/status/pause:.* pause
ESP8266Client:DotMatrix/status/scrolling:.* scrolling
ESP8266Client:DotMatrix/status/dim:.* dim
ESP8266Client:DotMatrix/status/text:.* text
ESP8266Client:DotMatrix/status/font:.* font
ESP8266Client:DotMatrix/status/RGB:.* RGB
ESP8266Client:DotMatrix/status/position:.* position


setList
BigMatrix/text $EVENT
dim:slider,0,1,15 BigMatrix/dim $EVTPART1
power:off BigMatrix/power $EVTPART1
scrolling:on,off BigMatrix/scrolling $EVTPART1
scrollspeed:slider,0,5,100 BigMatrix/scrollspeed $EVTPART1
rgb:FF0000,00FF00,0000FF BigMatrix/RGB $EVTPART1
RGBPower:off BigMatrix/RGBPower $EVTPART1
time:noArg {"BigMatrix/time ".time()}
position:links,mitte,rechts BigMatrix/position $EVTPART1
EffectIn:none,scrollLeft,scrollRight,scrollUp,scrollDown,scrollUpLeft,scrollUpRight,scrollDownLeft,scrollDownRight,slice,mesh,fade,dissolve,blinds,wipe,wipeCursor,scanHoriz,scanHorizx,scanVert,scanVertx,open,openCursor,close,closeCursor,growUp,growDown BigMatrix/effectIn $EVTPART1
EffectOut:none,scrollLeft,scrollRight,scrollUp,scrollDown,scrollUpLeft,scrollUpRight,scrollDownLeft,scrollDownRight,slice,mesh,fade,dissolve,blinds,wipe,wipeCursor,scanHoriz,scanHorizx,scanVert,scanVertx,open,openCursor,close,closeCursor,growUp,growDown BigMatrix/effectOut $EVTPART1
Schriftart:0,1 BigMatrix/font $EVTPART1
Wiederholen:on,off BigMatrix/repeat $EVTPART1
Pause:slider,0,500,10000 BigMatrix/pause $EVTPART1
BigMatrix/time $EVENT


Ich hoffe ich hab soweit alles. Falls ich etwas vergessen habe fragt einfach, ich versuche so schnell wie möglich zu antworten.






betateilchen  <--- my personal hero

roelleke

#4
Hallo,
ich habe versucht die Software für MQTT Display aus dem voherigen Beitag mit der Arduino IDE zu komplieren.
Leider erhalte ich immer folgende Fehlermeldung:

main:8:20: fatal error: ticker.h: No such file or directory

#include <ticker.h>

                    ^

compilation terminated.

exit status 1
ticker.h: No such file or directory


Woran kann das liegen?

Update: Problem gelöst. Es muss nicht <ticker.h> sondern <Ticker.h> verwendet werden.

kanenas

Hallo hankyzoolander,

wollte mich für dein Projekt hier bedanken. Funktioniert sehr gut!

LG
Jessie@Raspi(v3)+SSD, CUL-MAX, CUL-433, CUL-FS20, JeeLink-PCA301, JeeLink-JLLaCrosse, HM-MOD-UART, HUEBridge(v2), ESPEasy, Tasmota, Plenticore 7 mit BYD 11,5

hankyzoolander

betateilchen  <--- my personal hero

MaDu89

#7
Guten Abend, vor kurzem habe ich diese Dot-Matrix Anzeige 8-Segmente mit dem MAX 7219 in die Finger bekommen... einmal leuchten sehen und sofort für ein must-have befunden! 8)
Dann fande ich als begeisterter Fhem Nutzer diesen Beitrag und konnte die Matrix via MQTT einbinden... Echt MEGA Geil die Einbindung und die Möglichkeiten....Vielen Dank erstmal dafür!
Mittlerweile bin ich mehr als Happy aber wie bekomme ich z.B. bei einer Temperaturanzeige das °C ordentlich angezeigt bekomme.... Ich bekomme nur ein: A°C... (ohne das A wäre es schick ;))
Wo könnte ich mir auch eigene Zeichen "basteln" ?

Kann mir da vielleicht jemand kurz helfen... Danke!  ;)
RPi 3 B+mit FHEM, PiHole, PiVPN, Homatic, ESP8266, ESP32 Cam, Sonoff, Sonoff Pow, Shelly, 433MHz Funksteckdosen, ETA Pelletheizung, IPCam, RGB Controller LK35, MediaServer, Volumio, NAS/Backup, Homebot LG, FRITZ!Box 7560, Telegram, Dot-Matrix MAX 7219, SmartMirror, 3D-Drucker...seit 2017 stabil!

laberlaib

#8
Hallo hankyzoolander und andere,

ich räume zu Weihnachten mal auf und habe meine Matrix-LED gefunden und ein paar ESPs.
Ich würde gerne Deine neuste Version vom April 2020 ausprobieren, steh aber gerade komplett auf dem Schlauch:

Wie bekomme ich die den auf einen ESP?
Ich nutze nur die Arduino IDE und die kann nur *.INO-Dateien öffnen. Aber es sind ja nur CPPs und Hs angehängt..


Edit: Und wenn ich die Main.cpp mit einem anderen Editor öffne, dann wird doch weiterhin auf die Ticker.h verwiesen - sind das die Dateien vom ersten Beitrag?

Könntest Du so lieb sein und mich da erleuchten?

laberlaib
--
Proxmox, Homematic, G-Tags, Zigbee2MQTT, Rhasspy Sprachsteuerung im Aufbau (beta)

pflock_y

Moin laberlaib,

pack alle 5 Dateien in einen Ordner.
config.h
effects.cpp
effects.h
fonts_data.h
main.cpp

Ticker.h in das libary Verzeichnis der Arduino IDE

So sollte es dann klappen.

vg
pflock_y

bernd-j

Ich habe bis jetzt die V2 benutzt und wollte auf V4 updaten.
Das kompilieren zeigt keine Fehler auch das übertragen nicht.
Es wird jedoch keine IP geholt und die Displayanzeige kommt bis Conne und bleibt stehen.

pflock_y

Hallo bernd-j,
kommentier die Zeile mit "Conne..." mal aus.
Ich hab die gar nicht drin, bei mir läuft nur die IP Adresse durch, bis das erste MQTT kommt.


vg
pflock_y


parola.setTextAlignment(PA_CENTER);
  parola.printf("Connecting to %s", ssid);


bernd-j

Hallo pflock_y
Ich habe jetzt noch mal alles neu gemacht.
Wenn ich es richtig verstanden habe alle 5 Dateien in einen Ordner.
Ticker h in das libary Verzeichnis. Code für den Wemos d1 mini aus dem Post vom 29 Juli 2019 gleich oben nach der Einbindung in Fhem.
ticker.h in Ticker h geändert. Die WLAN SSID sowie das Passwort in die config.h eingetragen.
Im Display erscheint Connecting to SSID.
Es wird keine IP belegt.
Schon mal Danke.

pflock_y

Hallo bernd-j,

sorry für die späte Antwort. Habe deine erst jetzt gesehen.
Ich häng dir mal meine Version an. Ich hab aber ein bisschen rumgemacht in der *.ino. (TOPIC Namen usw.)
Deshalb auch die FHEM setList und readingList.

Ich selbst habe mittlerweile fünf im Einsatz, laufen alle absolut stabil!!!
Super Geiles Projekt!!!

@hankyzoolander, ich hoffe du hast kein Problem mit solchen Änderungen in deinem Quellcode.



vg
pflock_y

bernd-j

Hallo pflock_y
Besten Dank hat auf Anhieb funktioniert.