{"id":3584,"date":"2024-02-19T10:08:26","date_gmt":"2024-02-19T16:08:26","guid":{"rendered":"https:\/\/lab.rapternet.us\/?p=3584"},"modified":"2025-01-17T16:01:11","modified_gmt":"2025-01-17T22:01:11","slug":"max7219-display-in-esphome","status":"publish","type":"post","link":"https:\/\/lab.rapternet.us\/?p=3584","title":{"rendered":"Max7219 display in esphome"},"content":{"rendered":"\n<p>I saw a really cool blanking panel for a server rack recently that used a bunch of LED displays to show information powered by an ESP and home assistant. I thought the displays were pretty cool and decided to get some and try them out. I may also have some ulterior motives with a project I&#8217;ve started working on as well.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>The display is a max 7219 led matrix. It&#8217;s just a single color display, no fancy RGB here, but it&#8217;s very simple to wire up and use in EspHome (also inexpensive). The <a href=\"https:\/\/esphome.io\/components\/display\/max7219digit.html\" target=\"_blank\" rel=\"noreferrer noopener\">EspHome documentation<\/a> for it is pretty solid as well. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Components<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/amzn.to\/4h0Xy7K\" target=\"_blank\" rel=\"noreferrer noopener\">Max7219 display<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/amzn.to\/4gZ4fHg\">Esp8266<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Hardware<\/h2>\n\n\n\n<p>Wiring it up to an ESP is simple enough, it uses SPI for communication, and one extra pin. So hook up the CLK and CS pins to the ones configured for it, and wire up the DIN on the display to the configured MOSI pin.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248-1024x771.jpg\" alt=\"\" class=\"wp-image-3614\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0020135835065962653091082248.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>Below are my mappings from the display board pins to those configured in EspHome<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Max7219 DIN pin -&gt; MOSI Pin from EspHome SPI settings<\/li>\n\n\n\n<li>Max7219 CS pin -&gt; CS Pin from the EspHome display settings<\/li>\n\n\n\n<li>Max7219 CLK pin -&gt; CLK Pin from EspHome SPI settings<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">EspHome Configuration<\/h2>\n\n\n\n<p>Before we get into the EspHome configuration, we first want to get the font files in place. This font is a pixelated font that is great for these kinds of displays. It is the <a href=\"https:\/\/www.wfonts.com\/font\/pixelmix\" target=\"_blank\" rel=\"noreferrer noopener\">pixel mix font from wfonts<\/a>. With the file in hand, I uploaded it to the esphome\/font folder using VS Code (the same folder I used for my air gradient display fonts, if you don&#8217;t have the folder, you can create it in VS Code as well). <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"911\" height=\"580\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image.png\" alt=\"\" class=\"wp-image-3607\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image.png 911w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-300x191.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-768x489.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>For this example configuration, we&#8217;ll just be showing the current time on the display. This is a nice simple EspHome configuration for it to get our feet wet.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Example configuration entry<br>spi:<br>  clk_pin: 15<br>  mosi_pin: 13<br><br>font:<br>  - file: \"font\/pixelmix.ttf\"<br>    id: digit_font<br>    size: 8<br><br>time:<br>  - platform: homeassistant<br>    id: hass_time<br><br>display:<br>  - platform: max7219digit<br>    cs_pin: 3<br>    num_chips: 4<br>    intensity: 15<br>    lambda: |-<br>      it.strftime(0, 0, id(digit_font), \"%H:%M\", id(hass_time).now());<br><\/pre>\n\n\n\n<p>Now that we have everything wired up and EspHome configured, we can start up our clock!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427-1024x771.jpg\" alt=\"\" class=\"wp-image-3615\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240107_0014394555728225761546207427.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Everything Running with the Time<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Text Input Field from Home Assistant<\/h2>\n\n\n\n<p>Now that we have the basics down, let&#8217;s get the display to read text coming from a Home Assistant text sensor. This will give Home Assistant the ability to send any arbitrary message to the display, and let automations send data as well.<\/p>\n\n\n\n<p>To start out, we&#8217;ll add a text sensor helper to Home Assistant. This can be done at: Settings -&gt; Devices and Services -&gt; Helpers<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"470\" height=\"564\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-6.png\" alt=\"\" class=\"wp-image-3644\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-6.png 470w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-6-250x300.png 250w\" sizes=\"auto, (max-width: 470px) 100vw, 470px\" \/><figcaption class=\"wp-element-caption\">Adding a Text Helper<\/figcaption><\/figure>\n\n\n\n<p>Once you click to create a text helper, you&#8217;ll get a dialog with some inputs used to define it. I just left those on the defaults and gave it a unique name and clicked create.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"574\" height=\"672\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-7.png\" alt=\"\" class=\"wp-image-3645\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-7.png 574w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-7-256x300.png 256w\" sizes=\"auto, (max-width: 574px) 100vw, 574px\" \/><figcaption class=\"wp-element-caption\">Creating a Text Helper<\/figcaption><\/figure>\n\n\n\n<p>Once it&#8217;s been created, you can find it on the dashboard, type in some text and hit enter to send it in.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"335\" height=\"116\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-5.png\" alt=\"\" class=\"wp-image-3643\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-5.png 335w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/image-5-300x104.png 300w\" sizes=\"auto, (max-width: 335px) 100vw, 335px\" \/><figcaption class=\"wp-element-caption\">In the Home Assistant Dashboard<\/figcaption><\/figure>\n\n\n\n<p>Now that we have the Home Assistant side of things setup, let&#8217;s go over to the EspHome configuration and start getting that going. We&#8217;ll need the sensor name for our text sensor in home assistant. This way we can configure the screen to read from that sensor. Everything else is the same as the clock from above.<\/p>\n\n\n\n<p>The heart of our code is in the lambda, where we get the string data from the home assistant text field.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text_sensor:<br>  - platform: homeassistant<br>    name: \"Display Text\"<br>    entity_id: input_text.esphome_display_text<br>    id: input_text_field<br>font:<br>  - file: \"font\/pixelmix.ttf\"<br>    id: digit_font<br>    size: 8<br>display:<br>  - platform: max7219digit<br>    cs_pin: 3<br>    num_chips: 4<br>    intensity: 5<br>    id: cool_display<br>    lambda: |-<br>      it.printf(0, 0, id(digit_font), \"%s\", id(input_text_field).state.c_str());<\/pre>\n\n\n\n<p>Now that the code is done, we can upload the new firmware and have some fun tooling in messages in home assistant and seeing them show up on the display. This allows home assistant to send any arbitrary text to the display for notifications for information. The text does scroll if it&#8217;s longer than the display as well, so no worries about character limits (within reason).<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" data-id=\"3648\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911-1024x771.jpg\" alt=\"\" class=\"wp-image-3648\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152041104813636764360346911.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Text Sent from Home Assistant<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"1506\" data-id=\"3649\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391.jpg\" alt=\"\" class=\"wp-image-3649\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391.jpg 2000w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/01\/pxl_20240112_2152164628769566139117342391-1536x1157.jpg 1536w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">\ud83d\ude00<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>This was a fun little thing to try out in EspHome and I&#8217;ll eventually use it in one of my builds or projects. I may even try to make a rack mount blanking panel like my inspiration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Future Things to Try<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.adafruit.com\/product\/4594\">Diffusion Acrylic from Adafruit <\/a>or <a href=\"https:\/\/www.tapplastics.com\/product\/plastics\/cut_to_size_plastic\/black_led_sheet\/668\">elsewhere<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.wfonts.com\/font\/pixelmix\" target=\"_blank\" rel=\"noreferrer noopener\">Pixelmix font<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/esphome.io\/components\/display\/max7219digit.html\" target=\"_blank\" rel=\"noreferrer noopener\">EspHome max 7219 display documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.makerguides.com\/max7219-led-dot-matrix-display-arduino-tutorial\/\" target=\"_blank\" rel=\"noreferrer noopener\">Maker guide on the display<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/discord.com\/channels\/429907082951524364\/1095407120796635287\" target=\"_blank\" rel=\"noreferrer noopener\">Inspiration on discord<\/a><\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Some of the links in this post are affiliate links, which means I may earn a small commission if you make a purchase through them\u2014at no extra cost to you. This helps support the blog and allows me to continue creating content that you love. I will only recommend products and services that I trust and believe will be beneficial to my readers. Thank you for your support!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I saw a really cool blanking panel for a server rack recently that used a bunch of LED displays to show information powered by an ESP and home assistant. I thought the displays were pretty cool and decided to get some and try them out. I may also have some ulterior motives with a project &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/lab.rapternet.us\/?p=3584\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Max7219 display in esphome&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":3648,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[102,74,39,101,49],"class_list":["post-3584","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","tag-display","tag-esphome","tag-home-assistant","tag-max7219","tag-smart-home"],"_links":{"self":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/3584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3584"}],"version-history":[{"count":19,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/3584\/revisions"}],"predecessor-version":[{"id":4767,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/3584\/revisions\/4767"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/media\/3648"}],"wp:attachment":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}