I had a few of the 8x32 LED matrices around, and wanted to work on making a few things with them. One for me and my home assistant install, and one for my daughter.
In all honesty, I got a 3D printer for Christmas and wanted to use it for the list of projects I have had on backlog.
So I worked with someone on Upwork.com to help with the 3D modeling and design based on a sketch. I am not a 3D modeling person, so didn’t want to waste time. He was great and would use him again. Maybe ultimately I would learn how to manage myself or modify something, but until then, outsourcing.
This is the sketch I started with.
No screws, power inlet, etc. You can see in the perfect diagram below.
From that, I received the following (only showing the grid). But I have the grid, the top and bottom caps, and the diffuser.
For assembly, the grid snaps into the bottom cap, then I install the LED inside, slide the diffuser around the grid, and close with the top cap. All are snap in pieces, no screws.
I am using a BambuLab X1C printer. The beauty of it is that I could print straight up with NO support. The printer was able to bridge from one column of the grid to the next without sagging. That was the biggest win.
The assembly fits great, the LED matrix is a little loose inside given the designer did not have the actual hardware (anyone venture to fix and tighten is more than welcome).
Grid and caps printed with black ABS filament.
Diffuser printed with transparent PETG filament.
Some pictures of the assembly:
The ESPHome program I have running for now is this simple one. It is the start of what I want to hang by my garage door and send message to it via MQTT.
I have not started on the firmware yet, so there is a lot of work there to do, but at least I could test it.
#Name the Project here to identify the specific node
substitutions:
project: Garage-LED-Sign-01
id: garage-led-sign-01
xscrollpadding: "4" # in pix
mqtt:
<<: !include common/mqtt_credentials.yaml
#Include the board used
<<: !include common/esphome/esp32.yaml
#include common Wifi-OTA-API, etc
<<: !include common/common.yaml
binary_sensor:
#Include the status
- !include common/binary_sensors/status.yaml
- platform: gpio
pin: GPIO34
name: "PIR Sensor"
device_class: motion
id: garage_pir_sensor
switch:
#Include restart button
- !include common/switches/restart.yaml
sensor:
#Include wifi signal sensor
- !include common/sensors/wifi_signal.yaml
- !include common/sensors/uptime.yaml
text_sensor:
- platform: mqtt_subscribe
id: garage_led_sign_text
internal: true
topic: garage/led_sign/text
on_value:
then:
- if:
condition:
lambda: return true;
then:
lambda: id(garage_led_text).publish_state(x);
- platform: template
id: garage_led_text
internal: true
font:
- file: "fonts/arial.ttf"
id: text_font_tiny
size: 10
- file: "fonts/materialdesignicons-webfont.ttf"
id: icon_font_10
size: 10
color:
- id: my_red
red: 100%
green: 0%
blue: 0%
- id: my_green
red: 0%
green: 100%
blue: 0%
- id: my_blue
red: 0%
green: 0%
blue: 100%
- id: my_yellow
red: 100%
green: 100%
blue: 0%
- id: my_black
red: 0%
green: 0%
blue: 0%
# Configure WS2815
light:
- platform: fastled_clockless
chipset: WS2812b
id: led_matrix_light
pin: GPIO5
num_leds: 256
rgb_order: GRB
name: "Garage Traffic Sign"
default_transition_length: 0s
color_correct: [50%, 50%, 50%]
restore_mode: ALWAYS_ON
effects:
- addressable_rainbow:
- addressable_color_wipe:
- flicker:
- strobe:
- random:
- addressable_scan:
- addressable_twinkle:
- addressable_random_twinkle:
- addressable_fireworks:
- addressable_flicker:
- addressable_rainbow:
name: Rainbow Effect With Custom Values
speed: 10
width: 50
display:
- platform: addressable_light
id: led_matrix_display
addressable_light_id: led_matrix_light
width: 32
height: 8
pixel_mapper: |-
if (x % 2 == 0) {
return (x * 8) + y;
}
return (x * 8) + (7 - y);
rotation: 180°
update_interval: 200ms
pages:
- id: page1
lambda: |-
if (id(mqtt_client)->is_connected()) {
// do something if MQTT is connected
static uint16_t xpos = 0;
int x_start, y_start;
int width, height;
it.get_text_bounds(0, 0, "MQTT Connected", id(text_font_tiny),
TextAlign::TOP_LEFT, &x_start, &y_start, &width, &height);
it.print(-(xpos % (width + $xscrollpadding)), -2,
id(text_font_tiny), Color(id(my_blue)),
TextAlign::TOP_LEFT, "MQTT Connected");
xpos++;
}
- id: page2
lambda: |-
it.print(0, 0, id(icon_font_10), Color(id(my_blue)), TextAlign::TOP_LEFT, "");
- id: page3
lambda: |-
// Draw the same rectangle, but this time filled.
//it.filled_rectangle(0, 0, it.get_width(), it.get_height());
it.fill(my_red);
- id: page4
lambda: |-
// Draw the same rectangle, but this time filled.
//it.filled_rectangle(0, 0, it.get_width(), it.get_height());
it.fill(my_black);
- id: page5
lambda: |-
static uint16_t xpos = 0;
const char * text = id(garage_led_sign_text).state.c_str();
int x_start, y_start;
int width, height;
it.get_text_bounds(0, 0, text, id(text_font_tiny),
TextAlign::TOP_LEFT, &x_start, &y_start, &width, &height);
it.print(-(xpos % (width + $xscrollpadding)), -2,
id(text_font_tiny), Color(id(my_green)),
TextAlign::TOP_LEFT, text);
xpos++;
interval:
- interval: 2s
then:
if:
condition:
lambda: |-
return id(garage_led_text).state == "STOP";
then:
- display.page.show: !lambda |-
static int pagenum = 0;
static display::DisplayPage* pages[] = {id(page2), id(page3)};
auto page = pages[pagenum++];
if (pagenum >= 2)
pagenum = 0;
return page;
- component.update: led_matrix_display
- interval: 2s
then:
if:
condition:
lambda: |-
return id(garage_led_text).state == "START";
then:
- display.page.show: !lambda |-
static int pagenum = 0;
static display::DisplayPage* pages[] = {id(page5), id(page3)};
auto page = pages[pagenum++];
if (pagenum >= 2)
pagenum = 0;
return page;
- component.update: led_matrix_display
The other one I am making is a lamp for my daughter, using WLED so she can interface with her phone, adding a mic to the it for sound effect.
Anyways, thought I’d share.
I will share the files for the 3D models on one of the 3D sites, but if anyone needs now just let me know.