Hallo,
vor einiger Zeit habe ich im Forum mein Matrix Display vorgestellt https://forum.fhem.de/index.php/topic,77316.msg692541.html#msg692541 (https://forum.fhem.de/index.php/topic,77316.msg692541.html#msg692541)
Diese version wurde jetzt überarbeitet und möchte ich euch nicht vorenthalten und den ein oder anderen zum bauen anregen.
Zuerst mal ein großes DANKESCHÖN an Markus und Marc für ihre guten Nerven und Zeit mit diesem Projekt.
Hardware:
Wemos D1 mini (clone)
8x 4er Matrix Display mit Max7219 Chip
5V RGB LED Stripe 1m lang
2 kleine Taster
3x STP16NF06L (Transistoren für RGB LED Stripe)
5V Netzteil
RGB LED Stripe hinten am Gehäuse und leuchtet gegen Wand und/oder Decke(stimmungsvolle indirekte Beleuchtung)
Software:
folgender Code wird verwendet.
#include <LEDMatrixDriver.hpp>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
const char* ssid = "wlan-ssid";
const char* password = "wlan-passwort";
// TCP server at port 80 will respond to HTTP requests
WiFiServer server(80);
const char* TEXT_KEY = "MatrixText";
const char* SCROLLING_KEY = "MatrixScrollen";
const char* BRIGHTNESS_KEY = "MatrixHelligkeit";
const char* RGB_KEY = "rgb";
const char* RGBPOWER_KEY = "rgbPower";
const char* SCROLLSPEED_KEY = "MatrixScrollSpeed";
const char* MATRIXPOWER_KEY = "MatrixPower";
/*
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 = D3;
// Define LED Matrix dimensions (0-n) - eg: 32x8 = 31x7
const int LEDMATRIX_WIDTH = 256;
const int LEDMATRIX_HEIGHT = 8;
const int LEDMATRIX_SEGMENTS = 32;
const int RED = D0;
const int GREEN = D1;
const int BLUE = D2;
// 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 (~)
};
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 buttonD4 = 0;
int lastbuttonD4 = 0;
int buttonD6 = 0;
int lastbuttonD6 = 0;
int red = 0;
int green = 0;
int blue = 0;
int rgb = 0x000000;
void setup() {
pinMode(D4, OUTPUT); // Taster Helligkeit D4
digitalWrite(D4, LOW);
pinMode(D6, OUTPUT); // Taster Scrolling an/aus D6
digitalWrite(D6, 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.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
displayText(text);
delay(ANIM_DELAY);
}
// Start TCP (HTTP) server
server.begin();
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);
Serial.begin(57600);
}
void loop()
{
buttonD4 = digitalRead(D4); //D4
buttonD6 = digitalRead(D6); //D6
if (buttonD4 != lastbuttonD4) {
if (buttonD4 == HIGH) {
brightness++ ;
Serial.print("brightness: ");
Serial.println(brightness);
delay(20);
}
}
if (brightness > 10) brightness = 0;
lastbuttonD4 = buttonD4;
lmd.setIntensity(brightness);
if (buttonD6 != lastbuttonD6) {
if (buttonD6 == HIGH) {
if (scrollen == 1) scrollen = 0; else scrollen = 1;
Serial.print("Scrollen: ");
Serial.println(scrollen);
lmd.clear();
delay(20);
}
}
lastbuttonD6 = buttonD6;
displayText(text);
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait for data from client to become available
while (client.connected() && !client.available()) {
displayText(text);
delay(1);
}
// Read the first line of HTTP request
String req = client.readStringUntil('\r');
// First line of HTTP request looks like "GET /path HTTP/1.1"
// Retrieve the "/path" part by finding the spaces
int addr_start = req.indexOf(' ');
int addr_end = req.indexOf(' ', addr_start + 1);
if (addr_start == -1 || addr_end == -1) {
return;
}
req = req.substring(addr_start + 1, addr_end);
client.flush();
String s;
int pos = req.indexOf('?');
if (pos > 0) {
req = req.substring(pos + 1);
/* parse key value pairs */
parseRequest(req);
x = LEDMATRIX_WIDTH;
lmd.clear();
//Serial.println(req.substring(req.indexOf('=')+1));
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML><style> #header{ min-height: 20px; background-color: #666699; } #menu{ min-height: 20px; margin-top: 1%; background-color: #999999; } #body{ min-height: 200px; margin-top: 1%; } #footer{ min-height: 20px; margin-top: 1%; background-color: #666699; } #header, #menu, #body, #footer{ margin-left: 10%; margin-right: 10%; box-shadow: 3px 5px 7px #666666; border: 1px solid black; } @viewport{ zoom: 1.0; width: extend-to-zoom; } @-ms-viewport{ width: extend-to-zoom; zoom: 1.0; } </style> <html lang='en'> <head> <meta name='viewport' content='width=device-width, initial-scale=1'> <title>ESP8266 Web Server</title> </head> <body> <div id='header'><center><h1>Welcome to the ESP8266 Web Server</H1></center></div>";
s += " <div id='menu'><center><H2>Printing to the 4 - 8x8 Matrix</h2></center></div> ";
s += "<div id='body'><center><div><div><br/><H3>";
s += text;
s += "<p><a href='./'>Back</a></p>";
s += "</H3></div></div> </center> </div> <div id='footer'> </div> </body></html> ";
//s+=req.substring(req.indexOf('=')+1);
s + "</body></html>\r\n\r\n";
client.print(s);
return;
}
else
{
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
s += "<!doctype html> <style> \#header{ min-height: 20px; background-color: \#666699; } \#menu{ min-height: 20px; margin-top: 1%; background-color: \#999999; } \#body{ min-height: 200px; margin-top: 1%; } \#footer{ min-height: 20px; margin-top: 1%; background-color: \#666699; } \#header, \#menu, \#body, \#footer{ margin-left: 10%; margin-right: 10%; box-shadow: 3px 5px 7px \#666666; border: 1px solid black; } @viewport{ zoom: 1.0; width: extend-to-zoom; } @-ms-viewport{ width: extend-to-zoom; zoom: 1.0; } </style> <html lang='en'> <head> <meta name='viewport' content='width=device-width, initial-scale=1'> <title>ESP8266 Web Server</title> </head> <body> <div id='header'><center><h1>Welcome to the ESP8266 Web Server</H1></center></div> <div id='menu'><center><H2>Enter text which will be displayed on a 4 - 8x8 led matrix</h2></center></div> <div id='body'><center><div><div><br> <form action='esp8266'> <br>Enter Text to display on LED Matrix:<br><input type='text' maxlength='70' name='text' value=''><br><br> <input type='submit' value='Submit'></form> </div></div> </center> </div> <div id='footer'> </div> </body>";
s += "</html>\r\n\r\n";
client.print(s);
return;
}
}
/* 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);
}
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();
}
}
}
/**
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 );
}
}
/**
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;
}
}
void urlDecode(String& url) {
/* special space encdoing for using in FHEM */
url.replace('+', ' ');
//Conver HTML URL to Text:
//https://www.w3schools.com/tags/ref_urlencode.asp
url.replace("%20", " ");
url.replace("%21", "\!");
url.replace("%22", "\"");
url.replace("%23", "\#");
url.replace("%24", "\$");
url.replace("%25", "%");
url.replace("%26", "&");
url.replace("%27", "\'");
url.replace("%28", "\(");
url.replace("%29", "\)");
url.replace("%2B", "\+");
url.replace("%2C", "\,");
url.replace("%2D", "\-");
url.replace("%2E", "\.");
url.replace("%2F", "\/");
url.replace("%3A", "\:");
url.replace("%3B", "\;");
url.replace("%3C", "\<");
url.replace("%3D", "\=");
url.replace("%3E", "\>");
url.replace("%3F", "\?");
url.replace("%40", "\@");
url.replace("%5B", "\[");
url.replace("%5C", "\\");
url.replace("%5D", "\]");
url.replace("%5E", "\^");
url.replace("%7B", "\{");
url.replace("%7C", "\|");
url.replace("%7D", "\}");
}
void parseRequest(String request) {
while (request.length() > 0) {
/* check if we have a key value pair */
int valueStartPos = request.indexOf('=');
/* cancel if we have no key value pair */
if (valueStartPos == -1) return;
/* look for end of value */
int valueEndPos = request.indexOf('&');
if (valueEndPos == -1) valueEndPos = request.length();
/* extract value */
String value = request.substring(valueStartPos + 1, valueEndPos);
/* value is "url" encoded, decode it to plain text */
urlDecode(value);
/* look for valid keys ... */
/* KEY: text */
if (strncmp(TEXT_KEY, request.c_str(), valueStartPos) == 0) {
strcpy(text, value.c_str());
len = strlen(text);
}
/* KEY: MatrixPower */
if (strncmp(MATRIXPOWER_KEY, request.c_str(), valueStartPos) == 0) {
if (strcmp("off", value.c_str()) == 0) strcpy(text, " ");
else strcpy(text, "on");
}
/* KEY: scrolling */
if (strncmp(SCROLLING_KEY, request.c_str(), valueStartPos) == 0) {
if (strcmp("on", value.c_str()) == 0) scrollen = 1;
else scrollen = 0;
}
/* KEY: Scrollspeed */
if (strncmp(SCROLLSPEED_KEY, request.c_str(), valueStartPos) == 0) {
ANIM_DELAY = value.toInt();
}
/* KEY: rgbPower */
if (strncmp(RGBPOWER_KEY, request.c_str(), valueStartPos) == 0) {
if (strcmp("on", value.c_str()) == 0) rgb = 0xFFFFFF;
else rgb = 0x000000;
setColor(rgb);
}
/* KEY: brightness */
if (strncmp(BRIGHTNESS_KEY, request.c_str(), valueStartPos) == 0) {
brightness = value.toInt();
}
/* KEY: rgb */
if (strncmp(RGB_KEY, request.c_str(), valueStartPos) == 0) {
rgb = (int)strtol(value.c_str(), NULL, 0);
setColor(rgb);
}
/* move to next key value pair */
request = request.substring(valueEndPos + 1);
}
}
Die beiden kleinen Taster haben die Funktionen
Hardwareseitiges dimmen der LedMatrix und Hardwareseitiges scrollen ein/aus.
Länge und Höhe des Displays anpassen.
Nachdem wlan ssid und passwort angepasst ist, wird der code mit der Arduino Software geflasht.
Auf dem Display erscheint die IP welche der Wemos vom Router bekommen hat.
Betrieb in Fhem:
Der Wemos wird von Fhem mit wget gefüttert.
Folgende Funktionen stehen nun bereit in Fhem.
-MatrixHelligkeit <--> über Fhem Helligkeit des Matrix Displays in 10 Stufen mit Slider dimmen
-MatrixPower <--> über Fhem das Matrix Display ein oder aus schalten
-MatrixScrollSpeed <--> über Fhem die Scroll Geschindigkeit mit Slider einstellen von 10ms-100ms in 5er Schritten
-MatrixScrollen <--> über Fhem das Textscrollen ein oder aus schalten
-MatrixText <--> über Fhem einen text oder reading auf dem Display anzeigen lassen
-rgbPower <--> über Fhem den LED Stripe ein oder aus schalten
-rgb <--> über Fhem die LED Stripe Farbe über den colorpicker einstellen
Im Moment besteht noch ein kleines Problem, und zwar wird für jede Funktion der ganzen Kiste ein separates notify benötigt!
Also 7 Funktionen = 7 notify.
Jetzt wird der ein oder andere sagen das geht auch in einem.
Wir haben es, ganz ehrlich gesagt nicht hinbekommen.(wenn jemand ne Idee hat, bitte her damit) ;)
Zuerst wird ein DUMMY angelegt
define display dummy
attr display webCmd rgb
attr display widgetOverride rgb:colorpicker,RGB
attr display setList MatrixText rgb MatrixScrollen:on,off MatrixHelligkeit:slider,0,1,10 rgbPower:on,off MatrixScrollSpeed:slider,10,5,100 MatrixPower:on,off
Hier mal die notify`s
Das ganze Gerät heißt bei mir display
define display_matrix_dimm notify display:MatrixHelligkeit.* "wget -q -O - "http://192.168.0.146/esp8266?MatrixHelligkeit=$EVTPART1""
define display_matrix_power notify display:MatrixPower.* "wget -q -O - "http://192.168.0.146/esp8266?MatrixPower=$EVTPART1""
define display_matrix_scroll notify display:MatrixScrollen.* "wget -q -O - "http://192.168.0.146/esp8266?MatrixScrollen=$EVTPART1""
define display_matrix_text notify display:MatrixText.* "wget -q -O - "http://192.168.0.146/esp8266?MatrixText=$EVTPART1""
define display_scroll_speed notify display:MatrixScrollSpeed.* "wget -q -O - "http://192.168.0.146/esp8266?MatrixScrollSpeed=$EVTPART1""
define display_rgb notify display:rgb.* "wget -q -O - "http://192.168.0.146/esp8266?rgb=0x$EVTPART1""
define display_rgb_power notify display:rgbPower.* "wget -q -O - "http://192.168.0.146/esp8266?rgbPower=$EVTPART1""
Versuchsaufbau mit einem 4er Modul
Hallo hankyzoolander,
wie kann ich mehrere readings auf das Display übertragen?
Mit
Aussen_Sensor:temperature:.* "wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+$EVTPART1+C""
Übertrage ich die Temperatur, schön wäre es jetzt wenn auch noch Luftdruck und Luftfeuchtigkeit mit übertragen werden.
Gruß Holgi
Hallo,
für alle die möglicherweise wie ich am flashen eines LoLin NodeMcu v3 verzweifeln http://www.instructables.com/id/Getting-Started-With-ESP8266LiLon-NodeMCU-V3Flashi/ (http://www.instructables.com/id/Getting-Started-With-ESP8266LiLon-NodeMCU-V3Flashi/)
Die Arduino IDE 1.8.5 setzt bei mir unter Linux die Speichergröße und Frequenz beim Aufruf des esptool nicht richtig. Wichtig sind die zusätzlichen Parameter -bz 4M -bf 80
esptool -vv -cd nodemcu -cb 9600 -cp /dev/ttyUSB0 -ca 0x00000 -bz 4M -bf 80 -cf /tmp/arduino_build_523731/esp8266_LED_Matrix2_2018-02-09.ino.bin
Ha das ja lustig ;D
Habe fast das gleiche gebaut allerdings über MQTT .
Zitat von: Shojo am 15 Februar 2018, 15:55:22
Ha das ja lustig ;D
Habe fast das gleiche gebaut allerdings über MQTT .
Hallo,
hast Lust mehr darüber zu erzählen?
Habe nämlich bis jetzt keinen Weg gefunden mehrere readings als Laufschrift auf dem Dot Matrix Display
anzuzeigen.
Gruß Holgi
Zitat von: The-Holgi am 15 Februar 2018, 20:51:45
Habe nämlich bis jetzt keinen Weg gefunden mehrere readings als Laufschrift auf dem Dot Matrix Display anzuzeigen.
Mein Display hat auch keine Queue, ich mach das einfach über ein DOIF.
([+00:00:18] and ([?$SELF:cmd] eq '0' or [?$SELF:cmd] eq '7'))
(
set BU.Anzeige.LEDMatrix Text WZ.Temp: [WZ.Sensor.Room:Temperature] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '1')
(
set BU.Anzeige.LEDMatrix Text KZ.Temp: [KZ.Heizung_Clima:measured-temp] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '2')
(
set BU.Anzeige.LEDMatrix Text GB.Temp: [GB.Heizung_Clima:measured-temp] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '3')
(
set BU.Anzeige.LEDMatrix Text BZ.Temp: [BZ.Heizung_Clima:measured-temp] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '4')
(
set BU.Anzeige.LEDMatrix Text SZ.Temp: [SZ.Heizung_Clima:measured-temp] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '5')
(
set BU.Anzeige.LEDMatrix Text BU.Temp: [BU.Heizung_Clima:measured-temp] C
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '6')
(
set BU.Anzeige.LEDMatrix Text TR.Temp: [TR.Sensor.Weather:Temperature] C
)
Hm, wenn ich das doif richtig verstanden habe wechselt die Anzeige alle 18 Sekunden und läuft in einer Schleife?
Mal sehen ob ich das mit meinem code:
Aussen_Sensor:temperature:.* "wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+$EVTPART1+C""
auch hin bekomme.
Zitat von: The-Holgi am 15 Februar 2018, 23:36:50
Hm, wenn ich das doif richtig verstanden habe wechselt die Anzeige alle 18 Sekunden und läuft in einer Schleife?
Ja genau.
Zitat von: The-Holgi am 15 Februar 2018, 23:36:50
Mal sehen ob ich das mit meinem code:
Aussen_Sensor:temperature:.* "wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+$EVTPART1+C""
auch hin bekomme.
Versuche mal dieses:
(Ohne das jetzt getestet zu haben, da ich nicht zu hause bin)
([+00:00:18] and ([?$SELF:cmd] eq '0' or [?$SELF:cmd] eq '2'))
(
{wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+ReadingsVal("Aussen_Sensor","temperature","0")+C";}
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '1')
(
{wget --quiet - "http://192.168.178.65/esp8266?max=Aussenhum.+ReadingsVal("Aussen_Sensor","humidity","0")+%";}
)
Hallo Shojo,
erstmal Danke für deine Hilfe.
Habe es mal so versucht:
define THPL_Display DOIF ([+00:00:18] and ([?$SELF:cmd] eq '0' or [?$SELF:cmd] eq '2'))
(
{wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+ReadingsVal("Aussen_Sensor","temperature","0")+C";}
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '1')
(
{wget --quiet - "http://192.168.178.65/esp8266?max=Aussenhum.+ReadingsVal("Aussen_Sensor","humidity","0")+%";}
)
darauf die Ausgabe:
THPL_Display DOIF: no right bracket: ( {wget --quiet - "http://192.168.178.65/esp8266?max=Aussentemp.+ReadingsVal("Aussen_Sensor","temperature","0")+C"
Unknown command }, try help.
Unknown command }, try help.
Error: >THPL_Display< has no TYPE, but following keys: >READINGS<
Ist vielleicht nur ein syntaxfehler?
Gruß Holgi
Zitat von: The-Holgi am 16 Februar 2018, 13:14:27
Ist vielleicht nur ein syntaxfehler?
Ja das kann gut sein... Bin kein Perl Crack und ich kann das hier jetzt nicht testen.
Vielleicht so?
([+00:00:18] and ([?$SELF:cmd] eq '0' or [?$SELF:cmd] eq '2'))
(
{
my $url = 'http://192.168.178.65/esp8266?max=Aussentemp' + ReadingsVal("Aussen_Sensor","temperature","0") + 'C';;
system("wget --quiet $url");;
}
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '1')
(
{
my $url = 'http://192.168.178.65/esp8266?max=Aussenhum' + ReadingsVal("Aussen_Sensor","humidity","0") + 'C';;
system("wget --quiet $url");;
}
)
So wurde zumindest das DOIF ohne Fehlermeldung erstellt.
Fhem hat sich jedoch komplett aufgehangen und das steht im log:
PERL WARNING: Argument "http://192.168.178.65/esp8266?max=Aussentemp" isn't numeric in addition (+) at (eval 228) line 1.
2018.02.16 13:54:14 3: eval: { my $url = 'http://192.168.178.65/esp8266?max=Aussentemp' + ReadingsVal("Aussen_Sensor","temperature","0") + 'C'; system("wget --quiet $url"); }
2018.02.16 13:54:14 1: PERL WARNING: Argument "C" isn't numeric in addition (+) at (eval 228) line 1.
2018.02.16 13:54:14 3: eval: { my $url = 'http://192.168.178.65/esp8266?max=Aussentemp' + ReadingsVal("Aussen_Sensor","temperature","0") + 'C'; system("wget --quiet $url"); }
2018.02.16 13:56:56 2: THPL_Display: { my $url = 'http://192.168.178.65/esp8266?max=Aussentemp' + ReadingsVal("Aussen_Sensor","temperature","0") + 'C'; system("wget --quiet $url"); }: -1
ah ok !
([+00:00:18] and ([?$SELF:cmd] eq '0' or [?$SELF:cmd] eq '2'))
(
{
my $url = 'http://192.168.178.65/esp8266?max=Aussentemp' . ReadingsVal("Aussen_Sensor","temperature","0") . 'C';;
system("wget --quiet $url");;
}
)
DOELSEIF ([+00:00:18] and [?$SELF:cmd] eq '1')
(
{
my $url = 'http://192.168.178.65/esp8266?max=Aussenhum' . ReadingsVal("Aussen_Sensor","humidity","0") . 'C';;
system("wget --quiet $url");;
}
)
SO ?! :D
Hallo,
soweit funktioniert es so.
Allerdings habe ich gerade gesehen das die readings auch in opt/fhem geschrieben werden.
esp8266?max=Aussenhum73%25.2
esp8266?max=Aussentemp+5.8C
fhem.cfg
esp8266?max=Aussenhum73%25.1
esp8266?max=Aussentemp5.8C.6
fhem.db-wal
fhem.db-shm
esp8266?max=Aussenhum73%25
esp8266?max=Aussentemp5.8C.5
esp8266?max=Aussenhum75%25
esp8266?max=Aussentemp5.8C.4
esp8266?max=Aussentemp5.8C.3
esp8266?max=Aussenhum75C.2
esp8266?max=Aussentemp5.8C.2
esp8266?max=Aussenhum75C.1
Das liegt natürlich nicht an deinem DOIF.
Überlege gerade mosqito zu installieren.
:D
Hallo Leute,
hat von euch jemand elegant das Problem gelöst, dass nur das 1. Wort übertragen wird?
Also hierbei meine ich:
set display MatrixText eins zwei
Verursacht durch $EVTPART1 im notify.
Gruß
kroman
So geht's:
defmod n_dotmatrix1_MatrixText notify d_dotmatrix1:MatrixText.*\
{\
my $i = 1;;\
my $a = "";;\
foreach (split / /,$EVENT)\
{\
if ($i > 1)\
{\
$a = $a.$_."%20";;\
}\
$i++;;\
}\
system ("wget -q -O - http://esp11/esp8266?MatrixText=$a")\
}
hallo zusammen,
Ich habe ein Problem bzw 2
1.wo muss CS nun angeschlossen werden? im code steht was von "pick 15 on ESP8266" und etwas drunter steht D3 also GPIO0
2. das Display wird angesteuert es Läuft die Ganze zeit die IP Adresse durch, die ich im Browser eingeben muss. Aber wenn ich dort ein wort oder Text eingebe wird dieser nicht angezeigt sondern nur die IP.
Woran kann das liegen??
p.s. deine Version 1 läuft ohne Probleme
Zitat
1.wo muss CS nun angeschlossen werden? im code steht was von "pick 15 on ESP8266" und etwas drunter steht D3 also GPIO0
Was du hier einstellst, dort musst du anstecken:
const uint8_t LEDMATRIX_CS_PIN = D8;
Ich habe D8 verwendet.
Zitat
2. das Display wird angesteuert es Läuft die Ganze zeit die IP Adresse durch, die ich im Browser eingeben muss. Aber wenn ich dort ein wort oder Text eingebe wird dieser nicht angezeigt sondern nur die IP.
Das ist bei mir auch so. Der sketch ist für FHEM ausgelegt.
So nachdem das soweit läuft,
"Wieso wird die letzte Reihe vom Display nicht mit benutzt??"
Okay wird genutzt für Buchstaben wie "p q y"
Und wenn ich z.b. WZ Temp 31,5 °C anzeigen lassen will muss ich dann WZ+Temp+31,5+°C als Text eingeben oder gibt es auch die möhlichkeit das ohne die + Zeichen zu machen?
Hallo Hankyzoolander,
es müsste doch auch möglich sein hiermit längere und auch breitere Displays zu betreiben?
Ich möchte eine Anzeigetafel draußen am Pool umbauen.
Z.Zeit läuft es auf diesem Modell seit 3 Jahren problemlos.
Nun will ich einfach nur länger und breiter, also mehr Dots die angesprochen werden müssen.
Grüße Wolfdieter