lubeda / EsphoMaTrix

A simple DIY status display with an 8x32 RGB LED panel implemented with esphome.io and Home Assistant
MIT License
217 stars 23 forks source link
esphome homeassistant

Important news

Take a look at the new version of the improved EspHoMaTriXv2!!!

This version is read-only!!!!

EspHoMaTriX (ehmtx)

Breaking changes in esphome 2023.7.0

Since the update ehmtx only compiles if you add some code to your yaml. See here: https://github.com/lubeda/EspHoMaTriXv2/issues/62#issuecomment-1643052894

Important information

If you like my work, please donate me a star on GitHub and consider sponsoring me!!

Introduction

A simple DIY status display, built with a flexible 8x32 RGB LED panel implemented with esphome.io sample image

There are some “RGB-matrix” status displays/clocks out there, the commercial one from LaMetric and some excellent DIY-alternatives.

ehmtx in the media

See this German tutorial video with information on setting up your display RGB-LED Status Display für Home Assistant mit ESPHome | ESPHoMaTrix. Another german tutorial video focused at the Ulanzi Smarte Pixel Clock über Home Assistant steuern - Entitäten / Icons und mehr in der Ulanzi See this nice article about EsphoMaTrix on an Ulanzi TC001 from blakadder. Short video on Instagram @blak_adder https://www.instagram.com/reel/CpYVByRIaSI See these English discussions: Share your projects ESPHOME Or in German: Showroom

State

It is a working solution with core functionality coded. Advanced features, like automatic brightness control, can be done with esphome actions and automations. The possibilities are endless.

Features

Based on a 8x32 RGB flexible matrix, it displays a clock, the date and up to 24 other 'screens' provided by Home Assistant. Each screen (value/text) can be associated with a 8x8 bit RGB icon or GIF animation (see installation). The values/text can be updated or deleted from the display queue. Each screen has a lifetime, if not refreshed in its lifetime, it will disappear. When a screen is active, it is displayed so that the text can scroll twice (scroll_count) or even longer for screen_time seconds. You can use the fullfeature.yaml as a sample for an ESP8266. As mentioned, you have to edit to your needs. So check font, icons, board and the GPIO pins for your display. The file ulanziTC001.yaml uses the functions ehmtx provides, optimized for the Ulanzi Hardware. See it in action on YouTube (no sound but subtitles).

Installation

EsphoMaTrix custom component

EsphoMaTrix is a custom component, you have to include it in your YAML configuration. To always use the newest features, you should use the repo, to use a stable version you copy a working version to your esphome installation.

local use

If you download the components-folder from the repo and install it in your esphome you have a stable installation. But if there are new features, you won't see them. If needed, customize the YAML to your folder structure.

external_components:
   - source:
       type: local
       path: components # e.g. /config/esphome/components

use from repo

Use the GitHub repo as a component. Esphome refreshes the external components “only” once a day, perhaps you have to refresh it manually. In this mode, there may be breaking changes, so read the changelog and check the logs while installing the firmware.

external_components:
  - source:
      type: git
      url: https://github.com/lubeda/EsphoMaTrix
      ref: main # optional select a special branch or tag

Addressable_light component

The EsphoMaTrix component requires a 8x32 pixel addressable_light, it is referenced by the ID matrix_component. See the default options There are some different matrices-types on the market, to adapt them to EspHoMaTriX you have to find the proper pixel mapper. If there is garbage on your display, try the other pixel_mapper. Here are the most common types for flexible 8x32 matrices:

Type 1

under the display tag, specify this pixel mapper:

display:
  - platform: addressable_light
    .....
    pixel_mapper: |-
      if (x % 2 == 0) {
        return (x * 8) + y;
      }
      return (x * 8) + (7 - y);
    .....

Type 2 (e.g., Ulanzi TC001)

Under the display tag, specify this pixel mapper:

display:
  - platform: addressable_light
    .....
    pixel_mapper: |-
      if (y % 2 == 0) {
        return (y * 32) + x;
      }
      return (y * 32) + (31 - x);
    .....

You have to configure this lambda under the display: section to use the EsphoMaTrix component

display:
  - platform: addressable_light
    id: ehmtx_display
    .....
    auto_clear_enabled: true
    lambda: |-
      id(rgb8x32)->tick();
      id(rgb8x32)->draw();

Light component

The light component is used by the addressable_light component and referenced by ID under addressable_light_id:. To use the light component directly from home assistant, add the sample lambdason_turn_on and on_turn_off to the light component.

Sample

light:
  - platform: neopixelbus
    id: ehmtx_light
    ....
    on_turn_on:
      lambda: |-
         id(rgb8x32)->set_enabled(false);
    on_turn_off:
       lambda: |-
         id(rgb8x32)->set_enabled(true);

To hide the light component from home assistant use: internal: true


light:
  - platform: neopixelbus
    id: ehmtx_light
    internal: true
    ...

Time component

Since it is a clock, you need a time component, e.g., homeassistant. It is referenced by its ID under time_component: The display shows !t! until the time source is synchronized and valid.

Font

Download a small “pixel” TTF-font, I use "monobit.ttf". You can modify this font with FontForge and add on base of a E and so on. Due to copyright, I can't provide my modified version :-(. Not all fonts are suitable for this minimalistic display. There are public domain fonts which work well on the display, e.g., DMDSmall, details on alternative fonts are here. DarkPoet78 is providing special fonts for 8x32 matrices in his repo

font:
  - file: monobit.ttf
    id: EHMTX_font
    size: 16
    glyphs:  |
      !"%()+*=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz€@

Icons and Animations

Download and install all needed icons (.jpg/.png) and animations (.gif) under the ehmtx: key. All icons have to be 8x8 or 8x32 pixels in size. If necessary, scale them with gimp, check “as animation” for GIFs. You can also specify a URL to directly download the image file. The URLs will only be downloaded once at compile time, so there is no additional traffic on the hosting website. There are maximum 90 icons possible.

Sample

emhtx:
  icons:
    - id: boot
      file: icons/rocket.gif
      duration: 75    
    - id: temp
      file: temperature.png
    - id: yoga
      file: icons/yoga-bridge.gif
      pingpong: true
    - id: garage
      file: garage.gif
      duration: 100
    - id: homeassistant
      url: https://github.com/home-assistant/assets/raw/master/logo/logo-small.png     

The ID of the icons is used later to configure the screens to display. So, you should name them wisely. If you like to group icons, you should prefix them e.g., with "weather_" (see Service del_screen) The first defined icon will be used as a fallback icon, in case of an error, e.g., if you use a non-existing icon ID. GIFs are limited to 110 frames to limit the used amount of flash space. All other solutions provide ready-made icons, especially Lametric has a big database of icons. Please check the copyright of the icons you use. The maximum number of icons is limited to 90 in the code and also by the flash space and the RAM of your board. See also icon parameter

Configuration

ehmtx component

This component is highly customizable. Example

ehmtx:
  id: rgb8x32
  time_component: ehmtx_time
  matrix_component: ehmtx_display
  clock_time: 5    # seconds
  screen_time: 8   # seconds
  font_id: ehmtx_font
  show_dow: true   # day of week
  show_date: true  # also show the date
  icons2html: false # generate html with con overview
  brightness: 80 # percent
  time_format: "%H:%M"
  date_format: "%d.%m."
  week_start_monday: true # false equals sunday
  xoffset: 1
  yoffset: 2
  scroll_count: 2 # scroll long text at least two times
  scroll_interval: 80 # milliseconds
  frame_interval: 192 # milliseconds

Parameters

id (required, ID): Manually specify the ID used for code generation and in service definitions. clock_interval (optional, seconds): show the clock at least each x seconds, (default=60) clock_time (optional, seconds): duration to display the clock after this time, the date is displayed until next "show_screen". If show_date is false and clock_time > 0 the clock will be display as long as a normal screen! Setting clock_time to 0 will not show the clock or date. If there are no screens ind the queue, the display will be blank until the next screen is sent. timing screen_time (optional, seconds): default duration to display a screen or a clock/date sequence, a long text will be scrolled at least scroll_count times (default: 10 seconds). This may be overwritten by the add_screen service. hold_time (optional, seconds): extends the display time of the current screen in seconds (default=20). Used in services or automations, see hold_screen date_format (optional, string): formats the date display with strftime syntax, defaults "%d.%m." (use "%m.%d." for the US) show_seconds (optional, boolean): toggle an indicator for seconds while the clock is displayed (default: false)) time_format (optional, string): formats the date display with strftime syntax, defaults "%H:%M" (use "%I:%M%p" for the US) yoffset (optional, pixel): yoffset the text is aligned BASELINE_LEFT, the baseline defaults to 6 xoffset (optional, pixel): xoffset the text is aligned BASELINE_LEFT, the left defaults to 1 matrix_component (required, ID): ID of the addressable display show_dow (optional, bool): draw the day of week indicator on the bottom of the clock screen. Disable, e.g., if you want larger fonts, defaults to true. show_date (optional, bool): if true, show the date for screen_time - clock_time seconds, otherwise only shows the clock for screen_time seconds, defaults to true. time_component (required, ID): ID of the time component. The display shows !t! until the time source is valid. font (required, ID): ID of the font component week_start_monday (optional, bool): default Monday is first day of week, false => Sunday scroll_interval (optional, ms): the interval in ms to scroll the text (default=80), should be a multiple of the update_interval of the display frame_interval (optional, ms): the interval in ms to display the next animation/icon frame (default = 192), should be a multiple of the update_interval of the display. It can be overwritten per icon/gif, see icons parameter frame_duration icons2html (optional, boolean): If true, generate the HTML (filename.html) file to show all included icons.  (default = false) Example output: icon preview

icons

Parameters See icon details

Compile errors animation.h is missing

Error:
In file included from src/esphome.h:25,
                 from src/esphome/components/ehmtx/EHMTX.cpp:1:
src/esphome/components/ehmtx/EHMTX.h:6:10: fatal error: esphome/components/animation/animation.h: No such file or directory
 #include "esphome/components/animation/animation.h"
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
... 

Solution

Add in your given YAML this Code at the end:

animation:
  - id: animation_black
    file: "black.gif"

image:
  - id: image_black
    file: "black.gif"

and copy furthermore the black.gif Picture to your esphome Folder (most under /config/esphome/) You will find this picture in the image Folder in this git.


Control your display

Plenty of the features are accessible with actions, you can use in your YAML

Local actions/lambdas

Show all icons on your matrix

This code shows all icons once on boot up, depending on the amount of your icons it can take a while to see them all.

esphome:
  ....
  on_boot:
    priority: -100
    # ...
    then:
      - lambda: !lambda |-
          id(rgb8x32)->show_all_icons();

Add screen to your display queue

You can add screens locally and display data directly from any local sensor. See this sample:

Lambda

Take care that the char text[30]; has enough space to store the formatted text.

sensor:
  - platform: bh1750
    id: sensorlx
    ...
    on_value:
      then:
        lambda: |-
          char text[30];
          sprintf(text,"Light: %2.1f lx", id(sensorlx).state);
          // 5 Minutes,each time at least 11 seconds,no alarm
           id(rgb8x32)->add_screen("sun", text, 5,11, false);
Action
sensor:
  - platform: bh1750
    id: sensorlx
    ...
    on_value:
      then:
        - ehtmx.add.screen
          id: rgb8x32
          icon_name: "sun"
          text: "new data from lux sensor"
          lifetime: 5 # minutes optional
          screen_time: 35 # seconds optional
          alarm: true # optional

Parameters


Set (alarm/clock/gauge/text/today/weekday) color action

Sets the color of the selected element

Lambda set text color
  lamda:
    id(rgb8x32)->set_text_color(200,45,12);
Action for set text color

You have to use the ID of your ehmtx component, e.g., rgb8x32

     - ehmtx.***.color:
        id: rgb8x32
        red: !lambda return r;
        green: !lambda return g;
        blue: !lambda return b;

valid elements:

Buzzer, sound, buttons, and automatic brightness

  Awtrix and PixelIt have hard-coded functionality. EHMTX is also capable of building something like that by lambdas. But this is all your freedom.   Example: automatic brightness control with a bh1570 sensor  

sensor:
  - platform: bh1570
    # ...
    on_value:
      then:
         lambda: |- 
            if (x > 200)
            {
               id(rgb8x32)->set_brightness(50);
            } else {
               id(rgb8x32)->set_brightness(250);
            }

Notifier Custom Component

There is an optional notifier custom component you can install with HACS. It is comparable to the _screen service, but more streamlined.

Breaking changes

Usage

The integration works with the Home Assistant API so, after boot of the device, it takes a few seconds until the service calls start working.

Disclaimer

THE SOFTWARE IS PROVIDED "AS IS", use at your own risk!

Thanks

Special thanks to all sponsors