A simple DIY status display with an 8x32 RGB LED

EspHoMaTriX: A simple DIY status display with an 8x32 RGB LED panel implemented with esphome.io

I like status DIY-displays!

But all available solutions didn’t fit exactly my needs so i started to develop my own version based on esphome and the hardware used by Awtrix or PixelIt.
My solutions is now comparable with the mentioned gadgets and it is working well with homeassistant.
There is a youtube video showing the some aspects on how to use it. The video does not reflect the actual functionality since i am constantly improving the software.

Here is my github repo with documentation and some examples on how to use it.

It’s a spare time project, hope you like it. If you like it star me on github :slight_smile:

You can send messages to the display also with this custom component EHMTX notify component

ToDo:

  • cleanup code. A lot of this is done by jd1
    - cleanup documentation
    - adapt esphome guidelines on code-formating
  • implement RGB565 to safe flash space see my new branch
13 Likes

You made be buy one :money_with_wings:
Will be back when it arrived :package:, is wired :electric_plug: and ready to rock :rocket:

Nice, but the published code will change a lot. I am diving more and more into the componet development. The next version on github will have much cleaner and better code.

But i am still at the beginning.

2 Likes

That was quick. My led matrix arrived already.

Nice, but the published code will change a lot.

I see you are quite active over @ github. Is it worth to give it a shot now or would you suggested to wait a bit still you have a more solid/refactored/futureproof base?

I couldn’t wait :stuck_out_tongue: and just tried your code. I “solved” all dependecies (fonts, icons…) but now stuck at compiling with the following error:

Failed config

ehmtx: [source ehmtx.yaml:97]
  
  Couldn't find any component that can be used for '<module 'esphome.components.time' from '/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/components/time/__init__.py'>'. Are you missing a hub declaration?.
  id: rgb328
  showclock: 6
  showscreen: 8
  display8x32: ehmtxdisplay
  duration: 7
  font_id: ehmtxfont
  icons: 
    - file: ../00-icons/star-three-points_12x12.png
      id: boot
      type: RGB24
    - file: ../00-icons/thermometer-lines_12x12.png
      id: temp
      type: RGB24
    - file: ../00-icons/power_12x12.png
      id: power
      type: RGB24
  yoffset: -5
  scrollintervall: 64
  animintervall: 160

I took your yaml from the github, relevant part:

ehmtx:
  id: rgb328
  showclock: 6
  showscreen: 8
  display8x32: ehmtxdisplay
  time: 
  duration: 7
  font_id: ehmtxfont
  icons: 
    - file: ../00-icons/star-three-points_12x12.png
      id: boot 
      ...

time doesn’t contain a value. What is it for - it’s mandatory but doesn’t allow numbers :thinking: ?

okay, it’s just the id of the time component actually which belongs there.

Next problem is a more advaced compiling error :grimacing:

Traceback (most recent call last):
  File "/home/esphomeboy/.local/bin/esphome", line 8, in <module>
    sys.exit(main())
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 823, in main
    return run_esphome(sys.argv)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 810, in run_esphome
    rc = POST_CONFIG_ACTIONS[args.command](args, config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 364, in command_run
    exit_code = write_cpp(config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 157, in write_cpp
    generate_cpp_contents(config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 169, in generate_cpp_contents
    CORE.flush_tasks()
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/core/__init__.py", line 613, in flush_tasks
    self.event_loop.flush_tasks()
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/coroutine.py", line 245, in flush_tasks
    next(task.iterator)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 149, in wrapped
    await coro(conf)
  File "/home/esphomeboy/lab/components/ehmtx/__init__.py", line 89, in to_code
    frames = min (image.n_frames,MAXFRAMES)
AttributeError: 'PngImageFile' object has no attribute 'n_frames'

Something related to the images?

Cross checked with a jpeg (8x8), same same but different:

Traceback (most recent call last):
  File "/home/esphomeboy/.local/bin/esphome", line 8, in <module>
    sys.exit(main())
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 823, in main
    return run_esphome(sys.argv)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 810, in run_esphome
    rc = POST_CONFIG_ACTIONS[args.command](args, config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 364, in command_run
    exit_code = write_cpp(config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 157, in write_cpp
    generate_cpp_contents(config)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 169, in generate_cpp_contents
    CORE.flush_tasks()
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/core/__init__.py", line 613, in flush_tasks
    self.event_loop.flush_tasks()
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/coroutine.py", line 245, in flush_tasks
    next(task.iterator)
  File "/home/esphomeboy/.local/lib/python3.8/site-packages/esphome/__main__.py", line 149, in wrapped
    await coro(conf)
  File "/home/esphomeboy/lab/components/ehmtx/__init__.py", line 89, in to_code
    frames = min (image.n_frames,MAXFRAMES)
AttributeError: 'JpegImageFile' object has no attribute 'n_frames'

for the “time” - problem: you need a esphome time-component in the yaml like this:

time:
  - platform: homeassistant
    id: ehmtx_clock

and use it in the config:

ehmtx:
  id: rgb328
  time: ehmtx_clock

the new yaml in the repo has this fixed. In this case the matrix will display the time it gets from home-assistant. I take ~ a minute but after that they are sychronised.

=====

For the “n_frames” problem… i thing this depends on your pillow library which depends on your os :-(. It works for my hass-os. Which is the only os i tried. :-(.

For further testing please use gifs. I will try to fix this error.

There are still some other bugs in my code but it works (for me) somehow. But i will improve

1 Like

Thank’s for your feedback! Compiling goes further with gif files indeed but still fails:

Compiling .pioenvs/ehmtx/lib1da/FS/FS.cpp.o
ehmtx.yaml: In lambda function:
ehmtx.yaml:55:30: error: no matching function for call to 'esphome::EHMTX::get_status(int32_t&)'
In file included from src/esphome.h:21:0,
                 from src/main.cpp:3:
src/esphome/components/ehmtx/EHMTX.h:61:10: note: candidate: void esphome::EHMTX::get_status()
     void get_status();
          ^
src/esphome/components/ehmtx/EHMTX.h:61:10: note:   candidate expects 0 arguments, 1 provided
Compiling .pioenvs/ehmtx/lib1da/FS/vfs_api.cpp.o
Compiling .pioenvs/ehmtx/libb17/Update/HttpsOTAUpdate.cpp.o
Compiling .pioenvs/ehmtx/libb17/Update/Updater.cpp.o
Compiling .pioenvs/ehmtx/lib9b0/ESPAsyncWebServer-esphome/AsyncEventSource.cpp.o
Compiling .pioenvs/ehmtx/lib9b0/ESPAsyncWebServer-esphome/AsyncWebSocket.cpp.o
Archiving .pioenvs/ehmtx/libc85/libWiFi.a
Indexing .pioenvs/ehmtx/libc85/libWiFi.a
Compiling .pioenvs/ehmtx/lib9b0/ESPAsyncWebServer-esphome/WebAuthentication.cpp.o
Compiling .pioenvs/ehmtx/lib9b0/ESPAsyncWebServer-esphome/WebHandlers.cpp.o
Compiling .pioenvs/ehmtx/lib9b0/ESPAsyncWebServer-esphome/WebRequest.cpp.o
*** [.pioenvs/ehmtx/src/main.cpp.o] Error 1

This :point_up_2: wasn’t the most recent code. I now got myself your new yaml and component as a base but the validating now fails:

Failed config

api:
  services:  [source ehmtx.yaml:36]
    - service: alarm
      variables: 
        icon: int
        text: string
      then: 
        lambda: id(rgb328)->add_alarm(icon,text);
    - service: screen
      variables: 
        icon: int
        text: string
      then: 
        lambda: id(rgb328)->add_screen(icon,text);
    - [source ehmtx.yaml:50]
      service: status
      
      expected a dictionary.
      variables:  [source ehmtx.yaml:51]
      then: 
        lambda: id(rgb328)->get_status();
    - service: del_screen
      variables: 
        icon: int
      then: 
        lambda: id(rgb328)->del_screen(icon);

:thinking:

OK, i hope the pushed version is working (it does for me).

There is also a new yaml. Please adapt all changes to your yaml.

JPG and PNG are working (hopefully).

Next weekend i will continue with some features, cleanups and perhaps with the anounced video to see what is possible.

1 Like

Hint!

If the upload is working, it take some seconds until the esp knows the time, so “01:00” is displayed. After it gets the the real time the clock-display is working. All service calls will fail until the clock is working! So after boot you have to wait around 30 seconds! If the api conection is working everything is fine.

It works :rocket:

Compiled, flashed and the thing is rolling start:bulb:

That’s awesome! A short video showing how things tick would be indeed very useful :+1:

1 Like

There is a usable version now on github. it is still beta but it really works. There is still a lot to improve. I hope a better developer will maintain the source and the documentation to make it more usable for everybody.

To see it in action Youtube The quality of the live video is very bad in reality it looks much better. activate subtitles!!

2 Likes

What do you think of a support for rtttl/buzzer? So beside a icon a “sound” can be choosen. Might be very useful to get some ones attention for he messages/alarm.
Maybe for the sound it might be good to have option to play it only once (the first time the message/alarm is shown) or repeatingly every time.

Why not, but you can do it on your own! You need a rtttl: component and modify the lambdas of your service call. So can define a service call *alarm and add something like this

- rtttl.play: 'MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d'

to the lambda.

I think this is an advantage to all the other solutions, you can add buttons, sensors and anything you like to make it your device.

E.G. for your sensors you can use templates to convert the sensor state to an string and display it on the ehmtx with this comand

id(rgb8x32)->add_screen(5,text);
1 Like

Nice project!

What kind of power supply unit is needed to drive the 8*32 led-panel?

That depends on your maximal brightness. For my “production” display i use a 5V 2.5A power supply. The maximum current is 256*0.06A around 15 Amps. In the awtrix documentation it says

Power Supply (>3A)

Another important part is to power the led matrix on the middle connection and connect the ESP on the “D-IN” side. You will destroy the esp by pushing >1 A through the board!

3 Likes
  services:
    - service: alarm
      variables:
        icon: int
        text: string
      then:
        lambda: |-
          id(ehmtx_sound).play("mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6");
          id(rgb8x32)->add_alarm(icon,text);

Like this but my esp-clone can’t handle scrolling text and play the sound, perhaps it works with an esp32.

1 Like

Thanks for your answer and the warning!

I just tried to compile it for a esp32 but get the following error :point_down:

Indexing .pioenvs/ehmtx/libFrameworkArduino.a
Linking .pioenvs/ehmtx/firmware.elf
home/esphomeboy/.platformio/packages/[email protected]/bin/../lib/gcc/xtensa-esp32-elf/5.2.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/ehmtx/firmware.elf section `.flash.rodata' will not fit in region `drom0_0_seg'
home/esphomeboy/.platformio/packages/[email protected]/bin/../lib/gcc/xtensa-esp32-elf/5.2.0/../../../../xtensa-esp32-elf/bin/ld: section .dram0.data loaded at [000000003ffbdb60,000000003ffc169b] overlaps section .flash.rodata loaded at [000000003f400020,000000004153984f]
home/esphomeboy/.platformio/packages/[email protected]/bin/../lib/gcc/xtensa-esp32-elf/5.2.0/../../../../xtensa-esp32-elf/bin/ld: region `drom0_0_seg' overflowed by 30644304 bytes
collect2: error: ld returned 1 exit status
*** [.pioenvs/ehmtx/firmware.elf] Error 1

:thinking:

I think this depends on your icon or sound amount, it looks like there is no more space in flash.

This is nothing i can control. Minimize your icons, check your boards setting and so on.