Skip to content

Commit

Permalink
Merge pull request #41 from lubeda/develop
Browse files Browse the repository at this point in the history
Develop => 2023.6.4
  • Loading branch information
lubeda authored Jun 10, 2023
2 parents 1699686 + e824eda commit 7e9ac97
Show file tree
Hide file tree
Showing 17 changed files with 229 additions and 74 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ ltr3.png
8x32 iMAGE.xcf

.vscode/c_cpp_properties.json
.vs/
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 2023.6.4

- introduced `scroll_small_text`
- introduced `allow_empty_screen`

## 2023.6.3

- introduced `default_clock_font: true`
Expand Down
43 changes: 23 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

## Important information

If you like my work, please donate me a star on GitHub and consider [sponsoring](https://www.paypal.com/donate/?hosted_button_id=FZDKSLQ46HJTU) me!!
If you like this project, please donate a star on GitHub and consider [sponsoring](https://www.paypal.com/donate/?hosted_button_id=FZDKSLQ46HJTU) me!

## Introduction

A simple but very flexible DIY status display, built with a flexible 8x32 RGB LED panel, e.g., the ULANZI TC001 implemented with [esphome.io](https://esphome.io)
An easy to setup and extensible DIY LED Matrix status display built with a 8x32 RGB LED panel, (Example: ULANZI TC001) all implemented with [esphome.io](https://esphome.io)

![sample image](./images/sample.png)

If you like to tinker, you can use the custom component even as a satellite voice control microphone for home assistant. [Youtube](https://www.youtube.com/watch?v=CsOir14DCbM)
If you like to cuztomize and tinker you can use this custom component as a satellite voice control microphone for home assistant. [Youtube](https://www.youtube.com/watch?v=CsOir14DCbM)

Special use cases or tips and tricks can be found in the [WIKI](https://github.com/lubeda/EspHoMaTriXv2/wiki)
For additioanl tips and tricks be sure to check out the [WIKI](https://github.com/lubeda/EspHoMaTriXv2/wiki)

## Background

Expand All @@ -24,27 +24,26 @@ There are some “RGB-matrices” status displays/clocks out there, the commerci
- [Pixel It](https://pixelit-project.github.io/) (project is under active development)
- [AWTRIX-Light](https://github.com/Blueforcer/awtrix-light) From the developer of AWTRIX, optimized for the Ulanzi TC001 hardware

The solutions have their pros and cons. I tried some and used AWTRIX for a long time. But the cons are so big (in my opinion) that I started an esphome.io variant. Targeted to an optimized Home Assistant integration, without paid blueprints and the need of MQTT or uploading files to the ESP.

But it had to be extensible, e.g., for the use as a pool thermometer or as a media player. All done by the magical power of [esphome.io](https://esphome.io).
All of the various solutions have their pros and cons. I tried some and used AWTRIX for a long time, but I found it lacking in a lot of ways (in my opinion,) so I started work on an esphome.io variant. Targeted for an optimized and extensible Home Assistant integration without paid blueprints, MQTT broker requirement, or the need to upload files to the ESP board.

### Features

Based on a 8x32 RGB 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](#installation-of-esphomatrixv2-custom-component). 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. Even 8x32 GIF animations are possible. You can control nearly everything of the component.
Based on a 8x32 RGB 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](#installation-of-esphomatrixv2-custom-component)). 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. Even 8x32 GIF animations are possible. You can control nearly everything of the component.

### State

After the [old](https://github.com/lubeda/EsphoMaTrix) component became favorite, there were some feature requests, which indicated that my old code was a mess. I reworked the whole code and restructured it, so it is now hopefully more extensible. **This software is still heavily in progress, before updating check the [breaking changes](#breaking-changes)**
After the [v1](https://github.com/lubeda/EsphoMaTrix) component became popular and receieved additonal feature requests it became clear that yhe v1 [v1](https://github.com/lubeda/EsphoMaTrix)code was a bit of a mess. I reworked all of the code and restructured it to hopefully be much more extensible.
**This software is still heavily in development, before updating please check the [Breaking Changes](#breaking-changes)**

### Advice

If you have the choice to use an **ESP32 device**, there are conditions where the RAM size is too limited in a ESO8266 device, so I stripped out some features and these boards, e.g., the bitmap_screen.
It is highly recomended to use an **ESP32 device**. There are conditions where the RAM size is too limited in a **ESO8266 device** so some of the features had to be removed for these boards (Example: bitmap_screen).

## How to use

### The easy way

There is a little hype around the Ulanzi TC001 pixel clock. The easy way works with the Ulanzi TC001 hardware. For more customization and other hardware, look [here](#the-funny-but-more-elaborate-way).
There is a little hype around the Ulanzi TC001 pixel clock. The easy way works with the Ulanzi TC001 hardware. For more customization and other hardware, look [here](#the-advanced-way).

In easy mode you'll have a clock with auto brightness control and after step 3 you can send states to the display and toggle on or off additional screen elements.

Expand Down Expand Up @@ -79,7 +78,7 @@ and after a while (~30 seconds) it should display the correct time.

If not, check the esphome logs for further investigations.

### The funny but more elaborate way
### The advanced way

This is for the more advanced users. If you understand the concept of esphome, you can display nearly everything with this component. You can also create your own customized esphome based display with multiple sensors, or even use it as a microphone for the new [voice assist](https://esphome.io/components/voice_assistant.html) feature from home assistant.

Expand Down Expand Up @@ -526,6 +525,10 @@ ehmtxv2:

**special_font_xoffset** (optional, pixel): xoffset the text is aligned BASELINE_LEFT, the left defaults to `1`

**scroll_small_text** (optional, bool): normally small text is centered on the display if possible, with this set to `true` even small text is scrolled in `text_screen` and `rainbow_text_screen` (default: false)

**allow_empty_screen** (optional, bool): When the queue for messages to be displayed is empty and the time screen has been removed, the time screen is normally reactivated. This option can be used to disable this behavior by setting `allow_empty_screen` to `true`. (default: false)

**rtl** (optional, boolean): if `true` write text (but only the scroll direction, the words and numbers aren't changed!) from right to left (Arabic, Hebrew etc.). Default is `false`

**matrix_component** (required, ID): ID of the addressable display
Expand Down Expand Up @@ -577,7 +580,7 @@ See [icon details](#icons-and-animations)

## Control your display

Numerous features are accessible with services from home assistant and lambdas you can use in your YAML.
Numerous features are accessible with services from home assistant and lambdas that you can use in your YAML.

### Public functions/services
 
Expand All @@ -594,8 +597,8 @@ Numerous features are accessible with services from home assistant and lambdas y
|`show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper-right corner|
|`show_rindicator`|"r", "g", "b", "size"|shows the color with the given size in the lower-right corner|
|`set_clock_color`|"r", "g", "b"|set the default color for the clock/date display|
|`set_today_color"`|"r", "g", "b"|set the special color for today in the day of week line|
|`set_weekday_color"`|"r", "g", "b"|set the default color in the day of week line|
|`set_today_color`|"r", "g", "b"|set the special color for today in the day of week line|
|`set_weekday_color`|"r", "g", "b"|set the default color in the day of week line|
|`del_screen`|"icon_name", “mode”|deletes the specified icon screen from the queue, the [mode](#modes) is a filter|
|`force_screen`|"icon_name", “mode”|displays the selected the specified icon screen from the queue, the [mode](#modes) is a filter|
|`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified 8x32 icon as full screen|
Expand Down Expand Up @@ -927,7 +930,7 @@ max: 10

## Tips

### Display precision after home assistant 2023.3.0
### Display sensor precision after home assistant 2023.3.0

See [templating](https://www.home-assistant.io/docs/configuration/templating/#states) for possibilities to optimize the output
e.g.
Expand Down Expand Up @@ -1004,9 +1007,9 @@ action:
      ...
```

### Integrate in Home Assistant UI
### Integrate into Home Assistant UI

Add entities to the Home Assistant UI for interactive control of your display
Add entities to the Home Assistant UI for interactive control of the display

#### Brightness

Expand Down Expand Up @@ -1044,7 +1047,7 @@ switch:

### 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. See the Ulanzi simple YAML as a guide.
Awtrix and PixelIt have hard-coded functionality. EHMTX is also capable of building something like that with lambdas. Feel free to expierement as you see fit. See the Ulanzi simple YAML as a guide.

Example: automatic brightness control with a bh1570 sensor

Expand Down Expand Up @@ -1113,7 +1116,7 @@ THE SOFTWARE IS PROVIDED “AS IS”, use at your own risk!
- **[pplucky](https://user-images.githubusercontent.com/16407309/224850723-634c9b2d-55d9-44f2-9f93-765c0485b090.GIF)** for his 8x32 GIF animation
- **[dennisse](https://github.com/dennisse)** Auto brightness for the Ulanzi
- **[hco](https://github.com/hco)** fixing documentation
- **[geekofweek](https://github.com/geekofweek)** fixed sample YAML
- **[geekofweek](https://github.com/geekofweek)** fixed sample YAML, cleanup documentation
- **Everybody** who found bugs/issues and reported them!

## Special thanks to all sponsors
13 changes: 8 additions & 5 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

## function

- [ ] screen_time on ms sec base
- [ ] scroll left to right
- [ ] screen_time on ms sec base (preparing ticks base next_action)
- [ ] uint8_t ticks_per_second = ceil( 1000 / this->config_->display.get_update_interval());
- [ ] fade in/out on screen change
- [x] scroll left to right
- [ ] seconds point moveable
- [ ] dynamic bitmap as JSON (works partially)
- [x] dynamic bitmap as JSON (works partially)
- [ ] fix find_free_icon to work for bitmap screen
- [x] alarm on all screens but full screen
- [x] rindicator on all screens but full screen and clock
- [x] refreshing an icon screen should extend the display time
- [x] size of rindicator and alarm
- [x] center text
- [x] scroll text even if small
- [x] alarm independent of screen
- [x] del_screen with * and filter by type, do delete all clocks etc.
- [x] force_screen with * and filter by type, do delete all clocks etc.
Expand All @@ -24,7 +27,7 @@

## user experience

- [ ] blueprints
- [x] blueprints
- [ ] external HTML with more blueprint helpers (icons and modes)
- [ ] ~~all modes in one blueprint~~
- [x] Color in blueprints
Expand All @@ -45,7 +48,7 @@
- [ ] simple mode sample
- [ ] enhanced mode sample
- [ ] remake documentation
- [ ] more explanation for fonts
- [x] more explanation for fonts => wiki
- [ ] reference to https://www.pentacom.jp/pentacom/bitfontmaker2/gallery/?id=13768
- [ ] sample YAML with voice

Expand Down
11 changes: 7 additions & 4 deletions components/ehmtxv2/EHMTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,10 +538,13 @@ namespace esphome
}
else
{
ESP_LOGW(TAG, "tick: nothing to do. Restarting clock display!");
this->clock_screen(24 * 60, this->clock_time, false, C_RED, C_GREEN, C_BLUE);
this->date_screen(24 * 60, (int)this->clock_time / 2, false, C_RED, C_GREEN, C_BLUE);
this->next_action_time = ts + this->clock_time;
if(!EHMTXv2_ALLOW_EMPTY_SCREEN)
{
ESP_LOGW(TAG, "tick: nothing to do. Restarting clock display!");
this->clock_screen(24 * 60, this->clock_time, false, C_RED, C_GREEN, C_BLUE);
this->date_screen(24 * 60, (int)this->clock_time / 2, false, C_RED, C_GREEN, C_BLUE);
this->next_action_time = ts + this->clock_time;
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions components/ehmtxv2/EHMTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const uint8_t TEXTSCROLLSTART = 8;
const uint8_t TEXTSTARTOFFSET = (32 - 8);

const uint16_t POLLINGINTERVAL = 250;
static const char *const EHMTX_VERSION = "2023.6.3";
static const char *const EHMTX_VERSION = "2023.6.4";
static const char *const TAG = "EHMTXv2";
#ifndef USE_ESP8266
static const char *const EHMTX_LOGO = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63519,63519,63519,63519,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63519,0,0,0,0,2016,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,0,0,63488,0,63488,0,0,0,63519,0,0,0,0,2016,2016,0,0,0,65514,0,65514,0,0,0,31,0,0,0,64512,0,0,64512,0,63488,63488,0,63488,63488,0,0,63519,63519,63519,0,0,2016,0,2016,0,65514,0,65514,0,65514,0,31,31,31,0,0,0,64512,64512,0,0,63488,63488,63488,63488,63488,0,0,63519,0,0,0,0,2016,0,2016,0,65514,0,65514,0,65514,0,0,31,0,0,0,0,64512,64512,0,0,0,63488,63488,63488,0,0,0,63519,63519,63519,63519,0,2016,0,2016,0,65514,0,65514,0,65514,0,0,0,31,31,0,64512,0,0,64512,0,0,0,63488,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]";
Expand Down Expand Up @@ -94,6 +94,7 @@ namespace esphome
int display_rindicator;
int display_lindicator;
int display_alarm;
uint8_t ticks_per_second=62;
bool display_gauge;
bool is_running = false;
bool show_date;
Expand All @@ -113,6 +114,8 @@ namespace esphome
unsigned long last_rainbow_time;
unsigned long last_anim_time;
time_t next_action_time = 0; // when is the next screen change
uint32_t tick_next_action = 0; // when is the next screen change
uint32_t ticks_ = 0; // when is the next screen change

void remove_expired_queue_element();
uint8_t find_oldest_queue_element();
Expand Down Expand Up @@ -190,7 +193,6 @@ namespace esphome
EHMTX *config_;

public:
uint8_t centerx_;
uint16_t pixels_;
uint16_t screen_time_;
bool default_font;
Expand Down
72 changes: 39 additions & 33 deletions components/ehmtxv2/EHMTX_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace esphome
this->config_ = config;
this->endtime = 0;
this->last_time = 0;
this->centerx_ = 0;
this->screen_time_ = 0;
this->mode = MODE_EMPTY;
this->icon_name = "";
Expand Down Expand Up @@ -95,26 +94,30 @@ namespace esphome
}
width -= startx;

#ifdef EHMTXv2_USE_RTL
if (this->pixels_ < width)
{
result = 32 - ceil((width - this->pixels_) / 2);
}
else
{
#ifdef EHMTXv2_USE_RTL
if (this->pixels_ < width)
{
result = 32 - ceil((width - this->pixels_) / 2);
}
else
{

result = startx + this->config_->scroll_step;
}
#else
result = startx + this->config_->scroll_step;
}
#else
#ifdef EHMTXv2_SCROLL_SMALL_TEXT
result = startx - this->config_->scroll_step + width;
#else
if (this->pixels_ < width)
{
result = startx + ceil((width - this->pixels_) / 2);
}
else
{
result = startx - this->config_->scroll_step + width;
}
#endif
{
result = startx + ceil((width - this->pixels_) / 2);
}
else
{
result = startx - this->config_->scroll_step + width;
}
#endif
#endif
return result;
}

Expand Down Expand Up @@ -171,13 +174,13 @@ namespace esphome
extraoffset = TEXTSTARTOFFSET;
}
color_ = this->text_color;
#ifdef EHMTXv2_USE_RTL
#ifdef EHMTXv2_USE_RTL
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_RIGHT,
this->text.c_str());
#else
#else
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_LEFT,
this->text.c_str());
#endif
#endif
if (this->config_->display_gauge)
{
this->config_->display->line(10, 0, 10, 7, esphome::display::COLOR_OFF);
Expand Down Expand Up @@ -255,13 +258,13 @@ namespace esphome
}

color_ = (this->mode == MODE_RAINBOW_ICON) ? this->config_->rainbow_color : this->text_color;
#ifdef EHMTXv2_USE_RTL
#ifdef EHMTXv2_USE_RTL
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_RIGHT,
this->text.c_str());
#else
#else
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_LEFT,
this->text.c_str());
#endif
#endif
if (this->config_->display_gauge)
{
this->config_->display->image(2, 0, this->config_->icons[this->icon]);
Expand All @@ -286,13 +289,13 @@ namespace esphome
extraoffset += 2;
}
color_ = (this->mode == MODE_RAINBOW_TEXT) ? this->config_->rainbow_color : this->text_color;
#ifdef EHMTXv2_USE_RTL
#ifdef EHMTXv2_USE_RTL
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_RIGHT,
this->text.c_str());
#else
#else
this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_LEFT,
this->text.c_str());
#endif
#endif
break;
default:
break;
Expand Down Expand Up @@ -326,25 +329,29 @@ namespace esphome
{
this->config_->display->get_text_bounds(0, 0, text.c_str(), this->config_->special_font, display::TextAlign::LEFT, &x, &y, &w, &h);
}

this->pixels_ = w;
this->centerx_ = 0;


switch (this->mode)
{
case MODE_RAINBOW_TEXT:
case MODE_TEXT_SCREEN:
#ifdef EHMTXv2_SCROLL_SMALL_TEXT
max_steps = (EHMTXv2_SCROLL_COUNT + 1) * (width - startx) + EHMTXv2_SCROLL_COUNT * this->pixels_;
display_duration = ceil((max_steps * EHMTXv2_SCROLL_INTERVALL) / 1000);
this->screen_time_ = (display_duration > screen_time) ? display_duration : screen_time;
#else
if (this->pixels_ < 32)
{
this->screen_time_ = screen_time;
this->centerx_ = ceil((32 - this->pixels_) / 2);
}
else
{
max_steps = (EHMTXv2_SCROLL_COUNT + 1) * (width - startx) + EHMTXv2_SCROLL_COUNT * this->pixels_;
display_duration = ceil((max_steps * EHMTXv2_SCROLL_INTERVALL) / 1000);
this->screen_time_ = (display_duration > screen_time) ? display_duration : screen_time;
}
#endif
break;
case MODE_RAINBOW_ICON:
case MODE_BITMAP_SMALL:
Expand All @@ -353,7 +360,6 @@ namespace esphome
if (this->pixels_ < 23)
{
this->screen_time_ = screen_time;
this->centerx_ = ceil((23 - this->pixels_) / 2);
}
else
{
Expand Down
Loading

0 comments on commit 7e9ac97

Please sign in to comment.