Skip to content
widaproPublic

About

Dot matrix panel management

Resources

Stars

122 stars

Watchers

14 watching

Forks

Latest commit

 

History

71 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wledPixel

img

MAX7219 LED dot matrix display driven by an ESP32 or ESP8266 MCU.

The latest firmware version can be found in Releases

The latest stable version is v4.1.1, fixing stale text in Manual/MQTT zones and clearing MQTT postfixes in profiles, and adding an original Robot sprite with automatic migration from MARIO. See the release notes for the changes. Back up your settings before updating.

Supported key features:

  1. Home Assistant client [display sensor values]
  2. OpenWeatherMap client [display: temperature (C/F), humidity, pressure, wind speed, weather icon]
  3. MQTT client [each display zone support own topic]
  4. Display controll through MQTT
  5. Wall NTP clock [NTP sync clock]
  6. Manual input
  7. Stock Ticker Mode: Display real-time stock prices on any zone. Supports multiple symbols, customizable display format, prefix/suffix, and price change arrows (↑↓)
  8. Countdown timer
  9. Progress Bar Overlay: 1-pixel bottom-row bar on any zone — supports HA sensors, MQTT topics, and time-based modes
    • Dynamic mode adds 16 animations and two HA/MQTT value rules, with complete progress-bar settings stored per profile and zone.
  10. Full controll through web UI
  • Display snapshot on Home shows lit and unlit pixels for the active zone layout. A snapshot loads once when opening the page; click Refresh for a new image. Display power and 180° rotation are reflected in the snapshot.
  1. Home Assistant MQTT discovery [When MQTT settings specified, device will be automatically send discovery message to HA]
  2. Control display as light in Home Assistant [MQTT setup required]
  3. Initial setup through wifi AP and web UI
  4. Support 4 independent display zones
  • Rotate display 180° in Service Settings → System settings rotates the entire display, including zones, animations and progress bars. Click Apply to save. This is one global setting shared by all profiles and retained after reboot.
  1. Support up to 12 display segments at the same time [configured in web UI]
  2. Multiple fonts, including PixelFonts 3D
  3. Plus symbols font
  4. Display profiles and scheduling: 4 profiles on ESP8266 or 8 on ESP32, including the default profile; scheduled overrides and Apply Now.

Display snapshot (v4.1)

Check what your display is showing directly on Home. The snapshot shows lit and unlit pixels for the configured module count, including clocks, text, icons and progress bars. It loads once when the page opens; click Refresh whenever you need a fresh image. The status line also shows the active profile number and name captured with that image.

Choose red, yellow-green, neon blue or white LEDs beside the preview. The 180° button rotates only the preview, independently of the hardware rotation setting, so a physically inverted display can be viewed upright. Both choices are saved in your browser for that device address. Changing the appearance redraws the existing snapshot without requesting another frame or changing device settings.

Display snapshot with LED colors, preview rotation and Refresh

NTP status (v4.1)

The NTP section in Service Settings shows the device's current date and time, UTC offset, sync status and last successful sync since restart. It uses the device's applied time zone, even if your browser uses a different one.

Click Sync now to request a sync and see its progress and result. If a sync fails, the previous successful sync time stays visible and you can retry. Apply changes to the NTP settings before using Sync now.

Profiles and scheduling (v4.0)

Open Profiles to configure a default baseline and additional profiles. Profiles can override power, brightness, zone layout, display modes, fonts, scrolling, countdown, stock ticker and progress bars. No change preserves the active value. Saving a profile stores it; Apply Now saves and activates it. Changing the zone layout can restart the device.

Enable scheduling and select hours, minutes, days of the week and days of the month. The scheduler uses the configured NTP time and time-zone offset and waits for a successful sync. To restore the baseline after another profile has run, apply or schedule the default profile explicitly.

The ON AIR badge follows the last applied profile across reboots, including when scheduling is disabled. Disabling scheduling leaves that profile active.

Progress bars support Regular numeric/time mode and Dynamic animation mode. Dynamic mode uses up to two HA/MQTT value rules with independent animations and speeds. Leaving both values unset runs Rule 1 continuously; configured rules hide the bar when neither value matches.

Ingredients:
  1. Dot matrix display MAX7219, something like this: https://aliexpress.com/item/32618155357.html
  2. ESP32 or WeMos D1 Mini (ESP8266), something like this: https://aliexpress.com/item/32651747570.html
  3. Optional: DS18B20 sensor for local temperature readings. The display works without it.

3D Printed Case

Fonts

PixelFonts 3D

Select PixelFonts 3D (Latin) in a zone's Font field under Profiles, then use Apply Now. This is pixelfont_3d_5x5_thin from mcer12/PixelFonts, converted for MD_MAX72XX. The outline and shadow fit the display's full 8-pixel height. ASCII letters, digits, punctuation and the euro sign use the original 3D glyphs; Cyrillic and accented letters are not included. Unsupported characters display ?. Temperature degrees and stock arrows retain their existing plain glyphs, and blinking clock separators preserve their width. Characters are wider than the compact fonts, so longer messages may scroll. On a 32-column zone, set character spacing to 0 to fit a 24-hour HH:MM clock.

PixelFonts 3D on an 8-row matrix

On a real display:

PixelFonts 3D on a wledPixel LED matrix display

The font is MIT-licensed; attribution is in lib/wledFont/PixelFonts-LICENSE.txt. The generated header links the exact upstream BDF revision. To regenerate it, download that BDF and run python3 tools/convert_pixelfont.py /path/to/font.bdf.

Compact + Symbols

This font allows you to display text alongside icons within a single message. Icons in Wled symbol font This font allows accessing special icons using the ~ prefix followed by a specific character.

Compact + Symbols Font Mapping

Mapped by ~ + Character.

Code Index Symbol Code Index Symbol
~! 129 Battery Empty ~G 167 Key
~" 130 Battery 25% ~H 168 Male
~# 131 Battery 50% ~I 169 Alarm
~$ 132 Battery 75% ~J 170 Clock
~% 133 Battery Full ~K 171 Garbage
~0 144 WLED Logo ~M 173 Moon
~1 145 X Symbol ~N 174 Message
~2 146 Stop ~O 175 Reminder
~3 147 Rain ~S 179 Sun
~4 148 IP Icon ~T 180 Thunderstorm
~8 152 Full Block ~c 195 Scattered Clouds
~A 161 Calendar ~f 198 Mist / Fog
~B 162 Windows Logo ~m 205 Few Clouds (Night)
~C 163 Broken Clouds ~r 210 Rain
~D 164 Door ~s 211 Few Clouds (Sun)
~E 165 Female ~P 224 P Icon
~F 166 Snow ~@ 230 @ Symbol

Wled font

Support Germany alphabet Icons in Wled symbol font

Cyrilic font

Support Cyrilic alphabet Icons in Wled symbol font

Icons in Wled symbol font:

Icons in Wled symbol font

Symbol Font Mapping

This font maps standard ASCII characters directly to icons.

Input Index Symbol Input Index Symbol
0 48 WLED Logo K 75 Garbage
1 49 X Symbol M 77 Moon
2 50 Stop N 78 Message
3 51 Rain O 79 Reminder
4 52 IP Icon P 80 P Icon
8 56 Full Block R 82 Shower Rain
A 65 Calendar S 83 Sun
B 66 Windows Logo T 84 Thunderstorm
C 67 Broken Clouds c 99 Scattered Clouds
D 68 Door f 102 Mist / Fog
E 69 Female m 109 Few Clouds (Night)
F 70 Snow r 114 Rain
G 71 Key s 115 Few Clouds (Sun)
H 72 Male DEL 127 Hollow Up Arrow
I 73 Alarm ° 176 Degree Symbol
J 74 Clock

Web UI - Settings

Settings UI with example network values

Hardware GPIO for external devices, hardcoded:

ESP32

// Display pinout
#define DATA_PIN  23         // ESP32 GPIO23
#define CS_PIN    5          // ESP32 GPIO5
#define CLK_PIN   18         // ESP32 GPIO18

// Optional DS18B20 temperature sensor
const int oneWireBus = 4;    // ESP32 GPIO04

ESP8266

// Display pinout
#define DATA_PIN  D7         // WeMos D1 mini or ESP8266 -> GPIO13
#define CS_PIN    D6         // WeMos D1 mini or ESP8266 -> GPIO12
#define CLK_PIN   D5         // WeMos D1 mini or ESP8266 -> GPIO14

// Optional DS18B20 temperature sensor
const int oneWireBus = D4;   // WeMos D1 mini or ESP8266 -> GPIO02

Wiring

The DS18B20 connection shown below is optional. Connect the sensor only if you want local temperature readings.

Wiring diagram

First boot:

  • Device will boot in wifi access point mode and show "AP Mode" on the display.
  • AP wifi name: wledPixel-[short MAC address]
  • AP wifi password: 12345678
  • Connect to this AP and configure your wifi settings (connect to your wifi network)
  • When the device connects to the WIFI network, the device's IP address will be displayed on the zone0
  • Open the browser and go to the device IP address

Building from Source

Prerequisites

Build Steps

  1. Clone the repository:

    git clone https://github.com/widapro/wledPixel.git
    cd wledPixel
  2. Build for ESP32:

    pio run -e esp32
  3. Build for ESP8266 (D1 Mini):

    pio run -e d1_mini
  4. Upload firmware:

    # For ESP32
    pio run -e esp32 -t upload
    
    # For ESP8266
    pio run -e d1_mini -t upload
  5. Monitor serial output:

    pio device monitor -b 115200

Troubleshooting

If the device gets stuck at boot, erase the flash memory:

pio run -e esp32 -t erase
pio run -e esp32 -t upload

API

/api/temperature      - get measured temperature from connected ds18b20 sensor
/api/display/frame    - get a one-shot pixel snapshot of the configured display (GET)
/api/ntp-status       - get device time, UTC offset and NTP synchronization status (GET)
/api/ntp-sync         - queue an NTP synchronization attempt (POST)

The display snapshot contains modules, rows (8), columns, power, capturedAt (device uptime in milliseconds), profileIndex (zero-based), profileName and data (one byte per column, left to right, bit 0 at the top). Only modules in the active zone layout are included; spare driver capacity and layouts in other saved profiles do not increase its width. A powered-off display returns unlit pixels. The snapshot represents firmware output; it cannot detect disconnected or faulty LED hardware.

MQTT Topics

Topic Structure: [devicePrefix]/[zone]/[command]

  • devicePrefix: wledPixel-{shortMAC} (shown as wledPixel-XXXX in the examples below)
  • zone: zoneN where N is 0, 1, 2, or 3.

Custom zone topics and progress-bar source IDs in profiles support up to 127 UTF-8 bytes. Longer values are rejected when saving. If an older firmware already truncated a topic, enter its full value again and save the profile.

Zone Parameters

Topic Suffix Description Payload / Values
/text Zone text Text to display (active when workmode=mqttClient)
/scrolleffectIn Scroll effect IN Effect name (e.g., PA_PRINT)
/scrolleffectOut Scroll effect OUT Effect name
/scrollspeed Scroll speed 0 - 100
/scrollpause Scroll pause Seconds
/scrollalign Scroll alignment PA_LEFT, PA_CENTER, PA_RIGHT
/charspacing Character spacing Pixels
/workmode Zone work mode mqttClient, manualInput, wallClock, countdown, wopr, etc.
/scrollInfinite Infinite scroll ON/OFF, true/false, 1/0

Global Parameters

Topic Suffix Description Values
/intensity Brightness 0 - 15
/power Power control ON / OFF

Countdown Configuration

Set Target Time

  • Topic: .../zoneN/countdown
  • Payload: String with date/time.

Supported Formats:

Format Example Description
YYYY-MM-DDTHH:MM:SS 2026-12-31T23:59:59 Full ISO format
YYYY-MM-DDTHH:MM 2026-12-31T23:59 ISO without seconds
YYYY-MM-DD 2026-12-31 Date only (Time: 00:00:00)
HH:MM:SS 23:59:59 Time only (Date: Today)

Display Format

  • Topic: .../zoneN/countdownFormat
  • Payload: Format token string.

Options:

  • Basic: SS (seconds), MM (minutes), HH (hours), DD (days)
  • Combined: HHMM, HHMMSS, DDHH, DDHHMM, DDHHMMSS
  • Calendar: YY (years), YYMM, YYMMDDHHMM, YYMMDDHHMMSS
  • Automatic: auto (hides zero leading units)

where devicePrefix = wledPixel-XXXX zoneN = zone number (e.g. Zone0, Zone1, Zone2, Zone3)

Supported workMode:

workMode supported values:

  • mqttClient - MQTT client
  • manualInput - Manual static text inputed in UI
  • wallClock - NTP sync clock
  • owmWeather - Open Weather Map client
  • haClient - Home Assistant client
  • wopr - WarGames effect
  • countdown - Countdown timer

Display Behavior for MQTT and Manual Modes

Both MQTT Client and Manual Input modes share the same display logic:

When the message fits on the screen:

  • The message appears using the selected IN effect.
  • If Infinite Scroll is DISABLED:
    • If OUT effect is NO_EFFECT: The message stays static on the display until a new message arrives.
    • If OUT effect is any other effect: The animation plays once (IN → Scroll pause → OUT) and then stops. The message does not repeat.
  • If Infinite Scroll is ENABLED:
    • If OUT effect is NO_EFFECT: The message stays static on the display until a new message arrives.
    • If OUT effect is any other effect: The message loops continuously (IN → Scroll pause → OUT → repeat).

When the message does not fit on the screen:

  • It automatically scrolls to show the full text.
  • If Infinite Scroll is enabled: It scrolls in a loop.
  • If Infinite Scroll is disabled: It scrolls once and stops.

Service Messages (e.g., "mqtt ok", "mqtt err", mode names)

  • If a service message doesn't fit, it scrolls once and then remains static.
  • Duplicate status messages are ignored to prevent flickering.
  • Can be completely disabled via the "Disable service messages" setting.

Wall clock

Wall clock mode support next following display options:

  • HH:MM - 24-hour Hours : Minutes [21:43]
  • hh:mm - 12-hour Hours : Minutes without am/pm [09:43]
  • hh:mm am/pm - 12-hour Hours : Minutes with am/pm [09:43 pm]
  • HH:MM:SS - Hours : Minutes : Seconds [21:43:54]
  • HH - Hours [21]
  • MM - Minutes [43]
  • dd.mm.yyyy - Day.Month.Year [21.06.2022]
  • dd.mm - Day.Month [21.06]
  • dd.mm aa - Day.Month weekday name (e.g., Sun) [21.06 Tue] *in Cyrillic font weekday name will be in Cyrillic
  • aa - Weekday name (e.g. Sun) *in Cyrillic font weekday name will be in Cyrillic

Display Logic

  • If text fits in the zone:
    • Displays statically.
    • Dots blink (unless disabled).
  • If text does NOT fit in the zone:
    • Text scrolls completely until it disappears.
    • Screen remains blank for the duration of Scroll Pause.
    • Text starts scrolling again.
    • Dots do NOT blink to prevent interrupting the scroll cycle.

Note: The Scroll Effect Out setting in the Web UI is disabled (greyed out) for Wall Clock mode because the loop animation doesn't use an exit effect.

Progress Bar Overlay

A 1-pixel horizontal progress bar rendered on the bottom row (row 7) of any zone. It works as a transparent overlay — the bar coexists with clocks, text, weather, and other modes running in the same zone. Each zone can have its own independent progress bar configured in the "Progress Bar" section of the Settings page.

Data Sources

Source Description
Home Assistant Any HA sensor entity (e.g., sensor.battery_level). Polled at the HA update interval.
MQTT Any MQTT topic. Device subscribes automatically.
Time — Seconds Fills over 60 seconds, resets each minute.
Time — Minutes Fills over 60 minutes, resets each hour.
Time — Hours Fills over 24 hours, resets each day.

Configuration

  • Min / Max values: Define the scale for HA and MQTT sources (e.g., 0–100 for battery percentage). Time mode auto-calculates its scale.
  • Conditional display: Optionally show the bar only when a condition is met — a specific HA sensor or MQTT topic value matches an expected string (exact match).
  • WOPR exclusion: If a zone is running in WOPR mode, the progress bar is automatically disabled.

Use Cases

Use Case Data Source Min Max Notes
Battery level HA sensor / MQTT 0 100 Show charge state alongside clock
Seconds ticker Time — Seconds — — Visual second hand on a clock zone
Hour progress Time — Hours — — See how much of the day has passed
Download progress MQTT 0 100 Publish progress % from a script
Tank / reservoir level HA sensor 0 500 Scale to your sensor's range

Scroll effect list

Default effects:

  • PA_RANDOM
  • PA_PRINT
  • PA_SCAN_HORIZ
  • PA_SCROLL_LEFT
  • PA_WIPE
  • PA_SCAN_VERTX
  • PA_SCROLL_UP_LEFT
  • PA_SCROLL_UP
  • PA_FADE
  • PA_OPENING_CURSOR
  • PA_GROW_UP
  • PA_SCROLL_UP_RIGHT
  • PA_BLINDS
  • PA_CLOSING
  • PA_GROW_DOWN
  • PA_SCAN_VERT
  • PA_SCROLL_DOWN_LEFT
  • PA_WIPE_CURSOR
  • PA_SCAN_HORIZX
  • PA_DISSOLVE
  • PA_MESH
  • PA_OPENING
  • PA_CLOSING_CURSOR
  • PA_SCROLL_DOWN_RIGHT
  • PA_SCROLL_RIGHT
  • PA_SLICE
  • PA_SCROLL_DOWN
  • PA_SPRITE (Generic)

Custom effects (Sprites)

  • PACMAN
  • WAVE
  • ROLL
  • LINES
  • ARROW
  • SAILBOAT
  • STEAMBOAT
  • HEART
  • INVADER
  • ROCKET
  • FBALL
  • CHEVRON
  • WALKER
  • ROBOT — original 8×8 robot with blinking eyes
  • GHOST (New!)
  • DINO (New!)

Existing MARIO settings and profiles automatically use ROBOT, including when restoring older backups. The legacy MARIO identifier is also accepted through MQTT and the API.

Demo Video

Watch the effects demo on YouTube

Home Assistant automation example:

Send sensor value each time when a value has been changed

---
- alias: Outside temp change - send new temp to wled panel mqtt
  initial_state: 'on'
  trigger:
    platform: state
    entity_id: sensor.example_temperature
  action:
    - service: mqtt.publish
      data:
        topic: wledPixel-XXXX/zone0/text
        payload_template: "{{ states('sensor.example_temperature') }} C"

Replace wledPixel-XXXX and sensor.example_temperature with your own device prefix and sensor entity.

Validation

See v4.1.1 release notes for Manual/MQTT zone fixes, MQTT postfix clearing and the Robot sprite, v4.1 release notes for display snapshots, NTP controls and active-profile fixes, v4.0.1 release notes for the MQTT fix and upgrade instructions, and v4.0 release notes for the full feature overview and compatibility details, and local test documentation for the test and HIL workflows. Local tests: ./tools/test_local.sh all.

About

Dot matrix panel management

Resources

Stars

122 stars

Watchers

14 watching

Forks

Releases

Packages

Contributors

Languages