BitBastelei #308 - LED-Matrix mit MAX7219
(490 MB) 00:22:16
2018-11-11 11:00 🛈Wenn es darum geht viele LEDs anzusteuern gibt es viele Möglichkeiten: Serielle Systeme wie z.B. die „Neopixel“-Streifen oder Matrizen wie z.B. bei meiner 7-Segment-Anzeige sind die häufigsten Vertreter. Letztere hatte ich zuletzt händisch mit Schieberegistern und Dekadenzählern aufgebaut – mit dem MAX7219 gibt es jedoch einen fertigen Controller, welcher einen deutlich einfacheren Aufbau verspricht.
Hinweise und Ergänzungen:
- 02:32 Aktuell zwischen 0,80€ und 1,50€
- 06:35 https://github.com/squix78/MAX7219LedMatrix
- 07:20 https://learn.acrobotic.com/tutorials/post/esp8266-getting-started (Bild leider nicht mehr komplett verfügbar)
- 15:42 https://github.com/bartoszbielawski/LEDMatrixDriver
Code
#include <LEDMatrixDriver.hpp> extern "C" { #include "user_interface.h" } // This sketch draw marquee text on your LED matrix using the hardware SPI driver Library by Bartosz Bielawski. // https://github.com/bartoszbielawski/LEDMatrixDriver // Example written 16.06.2017 by Marko Oette, www.oette.info // Define the ChipSelect pin for the led matrix (Dont use the SS or MISO pin of your Arduino/ESP!) const uint8_t LEDMATRIX_CS_PIN = D1; // Define LED Matrix dimensions (0-n) - eg: 32x8 = 31x7 const int LEDMATRIX_WIDTH = 151; const int LEDMATRIX_HEIGHT = 7; const int LEDMATRIX_SEGMENTS = 19; // The LEDMatrixDriver class instance LEDMatrixDriver lmd(LEDMATRIX_SEGMENTS, LEDMATRIX_CS_PIN); signed int x=LEDMATRIX_WIDTH; // start top left // This is the font definition. You can use http://gurgleapps.com/tools/matrix to create your own font or sprites. // If you like the font feel free to use it. I created it myself and donate it to the public domain. // 2018-11-10 - Adlerweb: Added & byte font[95][8] = { {0,0,0,0,0,0,0,0}, // SPACE {0x10,0x18,0x18,0x18,0x18,0x00,0x18,0x18}, // EXCL ! {0x28,0x28,0x08,0x00,0x00,0x00,0x00,0x00}, // QUOT " {0x00,0x0a,0x7f,0x14,0x28,0xfe,0x50,0x00}, // # {0x10,0x38,0x54,0x70,0x1c,0x54,0x38,0x10}, // $ {0x00,0x60,0x66,0x08,0x10,0x66,0x06,0x00}, // % {0x00,0x30,0x48,0x48,0x48,0x34,0x48,0x34}, // & {0x00,0x10,0x18,0x18,0x08,0x00,0x00,0x00}, // ' {0x02,0x04,0x08,0x08,0x08,0x08,0x08,0x04}, // ( {0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20}, // ) {0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10}, // * {0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08}, // + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08}, // COMMA , {0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06}, // DOT . {0x00,0x04,0x04,0x08,0x10,0x20,0x40,0x40}, // / {0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x38}, // 0 {0x04,0x0c,0x14,0x24,0x04,0x04,0x04,0x04}, // 1 {0x00,0x30,0x48,0x04,0x04,0x38,0x40,0x7c}, // 2 {0x00,0x38,0x04,0x04,0x18,0x04,0x44,0x38}, // 3 {0x00,0x04,0x0c,0x14,0x24,0x7e,0x04,0x04}, // 4 {0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x38}, // 5 {0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38}, // 6 {0x00,0x7c,0x04,0x04,0x08,0x08,0x10,0x10}, // 7 {0x00,0x3c,0x44,0x44,0x38,0x44,0x44,0x78}, // 8 {0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x78}, // 9 {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08}, // ; {0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10}, // < {0x00,0x00,0x7e,0x00,0x00,0xfc,0x00,0x00}, // = {0x00,0x08,0x04,0x02,0x01,0x02,0x04,0x08}, // > {0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10}, // ? {0x00,0x30,0x48,0xba,0xba,0x84,0x78,0x00}, // @ {0x00,0x1c,0x22,0x42,0x42,0x7e,0x42,0x42}, // A {0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x7c}, // B {0x00,0x3c,0x44,0x40,0x40,0x40,0x44,0x7c}, // C {0x00,0x7c,0x42,0x42,0x42,0x42,0x44,0x78}, // D {0x00,0x78,0x40,0x40,0x70,0x40,0x40,0x7c}, // E {0x00,0x7c,0x40,0x40,0x78,0x40,0x40,0x40}, // F {0x00,0x3c,0x40,0x40,0x5c,0x44,0x44,0x78}, // G {0x00,0x42,0x42,0x42,0x7e,0x42,0x42,0x42}, // H {0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x7e}, // I {0x00,0x7e,0x02,0x02,0x02,0x02,0x04,0x38}, // J {0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44}, // K {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c}, // L {0x00,0x82,0xc6,0xaa,0x92,0x82,0x82,0x82}, // M {0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42}, // N {0x00,0x3c,0x42,0x42,0x42,0x42,0x44,0x38}, // O {0x00,0x78,0x44,0x44,0x48,0x70,0x40,0x40}, // P {0x00,0x3c,0x42,0x42,0x52,0x4a,0x44,0x3a}, // Q {0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44}, // R {0x00,0x38,0x40,0x40,0x38,0x04,0x04,0x78}, // S {0x00,0x7e,0x90,0x10,0x10,0x10,0x10,0x10}, // T {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e}, // U {0x00,0x42,0x42,0x42,0x42,0x44,0x28,0x10}, // V {0x80,0x82,0x82,0x92,0x92,0x92,0x94,0x78}, // W {0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42}, // X {0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10}, // Y {0x00,0x7c,0x04,0x08,0x7c,0x20,0x40,0xfe}, // Z // (the font does not contain any lower case letters. you can add your own.) }; // {}, // // Marquee text String text = "** ADLERWEB//BITBASTELEI ** WWW.ADLERWEB.INFO ** YOUTUBE.COM/USER/ADLERWEB **"; // Marquee speed signed int animDelay = 50; os_timer_t animTimer; bool animate = false; LOCAL void animateCallback(void *arg) { animate = true; } void setup() { // init the display lmd.setEnabled(true); lmd.setIntensity(0); // 0 = low, 10 = high Serial.begin(115200); Serial.println(F("\n\nLEDMatrix boot")); os_timer_setfn(&animTimer, (os_timer_func_t *)animateCallback, NULL); os_timer_arm(&animTimer, animDelay, true); animate = true; } void draw(void) { signed int len = text.length(); //We later use it for negative stuff char char_array[len+1]; strcpy(char_array, text.c_str()); drawString(char_array, len, x, 0); lmd.display(); x--; Serial.print("X: "); Serial.print(x); Serial.print("L: "); Serial.print(len); Serial.print("C: "); Serial.println((len * -8)); if( x < (len * -8) ) x = LEDMATRIX_WIDTH; } void comm(void) { //Serial Comm if(Serial.available()) { char in = Serial.read(); switch(in) { case 's': text = ""; do { in = Serial.read(); if(in != '\n') text += in; } while(in != '\n'); text.toUpperCase(); lmd.clear(); lmd.display(); x=LEDMATRIX_WIDTH; if(animDelay <= 0) x=0; draw(); Serial.print(F("\nText changed to: ")); Serial.println(text); break; case 'b': in = Serial.parseInt(); in = constrain(in, 0, 10); lmd.setIntensity(in); Serial.print(F("\nIntensity changed to: ")); Serial.println(in); break; case 'd': animDelay = Serial.parseInt(); Serial.print(F("\nAnimation delay changed to: ")); Serial.println(animDelay); os_timer_disarm(&animTimer); os_timer_arm(&animTimer, animDelay, true); break; case 'f': os_timer_disarm(&animTimer); if(animDelay > 0) animDelay *= -1; Serial.println(F("\nFreeze")); break; case 'm': if(animDelay < 0) animDelay *= -1; os_timer_disarm(&animTimer); os_timer_arm(&animTimer, animDelay, true); Serial.println(F("\nMove")); break; case 'h': case '?': Serial.println(F("\nb<1-10>: Brightness | d<0-128>: Scroll delay | s<text>: Change Text | f: freeze | m: move")); break; } } } void loop() { if(animate) { animate=false; Serial.print('.'); draw(); } comm(); } /** * 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++ ) { lmd.setPixel(x + ix, y + iy, (bool)(sprite[iy] & mask )); // shift the mask by one pixel to the right mask = mask >> 1; } // reset column mask mask = B10000000; } }