ESPhome LED matrix clock with nodemcuv2

I had a working LED matrix display clock (8 high, 32 wide) running nodeMCUv2 in the old situation. I was not able to update the device because fasted was not supported anymore. Because there were sides like chatgpt o thought, I give it a try. But after trying for a day I don’t have it working anymore and I don’t know how to solve this.

Beneath the original old but working config I had. It has also some includes because the matrix has some sort of zigzag setup but I don’t know how to integrate that in my new setup.

led_matrix.yaml

substitutions:
  devicename: led_matrix

esphome:
  name: $devicename
  platform: ESP8266
  board: nodemcuv2

  includes:
    - my_matrixled_display.h

wifi:
  ssid: "xxx"
  password: "xxx"

logger:
  level: info

debug:

web_server:
  port: 80

api:
  encryption:
    key:xxx

ota:
  - platform: esphome
    password: "xxx"

font:
  - id: tinyfont
    file: "DejaVuSans-Bold.ttf"
    size: 9
    glyphs: '♡Ωäöüß!"%()+,-_.:*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'

time:
  - platform: sntp
    id: rtc

light:
  - platform: fastled_clockless
    chipset: WS2812B
    rgb_order: GRB
    pin: GPIO12
    num_leds: 256
    name: "$devicename Light"
    id: mylight
    color_correct: [40%, 40%, 40%]

    effects:
      - random:
      - random:
          name: Random Effect With Custom Values
          transition_length: 5s
          update_interval: 7s

      - flicker:
      - flicker:
          name: Flicker Effect With Custom Values
          alpha: 95%
          intensity: 1.5%

      - addressable_rainbow:
      - addressable_rainbow:
          name: Rainbow Effect With Custom Values
          speed: 10
          width: 50

      - addressable_lambda:
              name: "My Simple Counter"
              update_interval: 3000ms
              lambda: |-
                static int run = 0;
                static auto matrixled = new MatrixLedDisplay();
                matrixled->set_addr_light((light::AddressableLight *) &it);
                matrixled->set_width(8);
                matrixled->set_height(32);
                matrixled->set_rotation(display::DISPLAY_ROTATION_90_DEGREES); 
                matrixled->clear();
                matrixled->printf(matrixled->get_width()/2, matrixled->get_height()/2,
                                    id(tinyfont), COLOR_ON, TextAlign::CENTER,
                                    "%i", run % 10);            
                run++;
 
      - addressable_lambda:
          name: "Clock"
          update_interval: 500ms
          lambda: |-
            static char text[16] = "??:??";    
            static uint16_t run = 0; 
            static int width;
            static float charwidth = 10;
            static int x_offset;
            static int baseline;
            static int height;
            static auto matrixled = new MatrixLedDisplay();
            matrixled->set_addr_light((light::AddressableLight *) &it);
            matrixled->set_width(8);
            matrixled->set_height(32);
            matrixled->set_rotation(display::DISPLAY_ROTATION_90_DEGREES); 
          
            matrixled->set_fg_color(current_color);  
            matrixled->clear();
            
                id(rtc).now().strftime(text, sizeof(text), "%H:%M");
                id(tinyfont)->measure(text, &width, &x_offset, &baseline, &height); 	            charwidth = float(width) / strlen(text);
                ESP_LOGD("main", "Displaying \"%s\"", text);
     
             matrixled->printf(matrixled->get_width()/2, matrixled->get_height()/2, id(tinyfont), COLOR_ON, TextAlign::CENTER, text); 

            run++;

display:

my_matrixled_display.h

#include "esphome.h"
using namespace esphome;

// returns the new bytepos
uint16_t get_next_char(const char *text, display::Font *font, uint16_t byte_pos,
                       char *buf, uint16_t buf_len) {
  assert(buf_len > 0);

  if (text[byte_pos] == '\0') // finished, start over!
    byte_pos = 0;

  int glyph_length;
  int glyph_n = font->match_next_glyph(text + byte_pos, &glyph_length);

  int i = 0;
  if (glyph_n >= 0) { // valid glyph, save it to buf
    while ((i < glyph_length) && (i < (buf_len - 1))) { // copy
      buf[i] = text[byte_pos + i];
      i++;
    }
    byte_pos += glyph_length;
  } else
    byte_pos += 1; // invalid glyph, advance one byte

  buf[i++] = 0; // terminate string

  return byte_pos;
}

class MatrixLedDisplay : public display::DisplayBuffer {
public:
  void set_addr_light(light::AddressableLight *lights) {
    this->lights = lights;
  }
  void set_fg_color(const light::ESPColor &fg_color) {
    this->fg_color = fg_color;
  }
  void set_bg_color(const light::ESPColor &bg_color) {
    this->bg_color = bg_color;
  }
  void set_width(const uint8_t width) { this->width = width; }
  void set_height(const uint8_t height) { this->height = height; }


  void dump_buffer() {
    ESP_LOGD("MatrixLedDisplay", "----- %4i x %4i -------",
             this->get_width_internal(), get_height_internal());

    for (int row = 0; row < this->get_height_internal(); row++) {
      char text[this->get_width_internal() * 9 + 1];
      for (int col = 0; col < this->get_width_internal(); col++) {
        int pos = col + row * this->get_width_internal();

        if ((pos < 0) || (pos > (this->width * this->height))) {
          ESP_LOGD("MatrixLedDisplay", "Error at pos=%i", pos);
          continue;
        }
        sprintf(&text[col*9], "%8x ", (*(this->lights))[pos].get().raw_32);
      }
      ESP_LOGD("MatrixLedDisplay", "%4i |%s|", row, text);
    };
  };

protected:
  void draw_absolute_pixel_internal(int x, int y, int color) override {
    if (x >= this->get_width_internal() || x < 0 ||
        y >= this->get_height_internal() || y < 0)
      return;

    if ((y & 0x01) == 0) 
        x = this->get_width_internal() - x - 1;  
    
    uint16_t pos = x + y * this->get_width_internal();
    if (pos >= (*(this->lights)).size()) {
      ESP_LOGD("MatrixLedDisplay",
               "Size mismatch of AddressableLight and Matrix, could not get "
               "light %i",
               pos);
      return;
    }

    if (color) {
      (*(this->lights))[pos] = this->fg_color;
    } else {
      (*(this->lights))[pos] = this->bg_color;
    }
  }

  int get_height_internal() override { return this->height; }

  int get_width_internal() override { return this->width; }

  uint8_t width{32};
  uint8_t height{8};
  light::AddressableLight *lights;
  light::ESPColor fg_color = light::ESPColor(0xff, 0xff, 0xff);
  light::ESPColor bg_color = light::ESPColor(0x00, 0x00, 0x00);
};

I hope someone can point me in the right direction getting this thing fixed once and for all e.g. deepseek and chatgpt were not able to get this fixed via my commands…!

Solved… Use http://install.wled.me this works a lot better… :wink:

Can you set number of leds per segment, number of segments etc…? I also have such led clock, i have 3 leds per segment and hours/minues/seconds shown. Currently i use some arduino code foud somewhere…

Yes you can!

1 Like

Do you have any link about how to set this thing ? I can change colors, effects… i did set number of leds, but that’s it, now i’m stuck. I can’t find any page explaining how to configure for clock… in my case i have bog clock with 6 digits (hours, minutes, seconds), each of 7-segment have 3 leds. I also have 2x two blinking leds (between minutes/seconds and between hours/minutes), so totally 130 leds.
Basically, i can’t even find how to start / show clock (if possible at all)…

Too complicated?

Followed this tut https://youtu.be/ZlYSjxx5IRc?si=Mtp71TOyMaBZAgLE

No, that’s not it… i have plain 7 segments… 3 leds per segment: