Skip to content

DIY build

This page shows you how to build your own AWTRIX clock: what to buy, how to wire it, and what to set after the first start.

Rather not build one?

You can buy a ready-made clock instead: Get a clock.

AWTRIX NG runs on any WS2812-style LED panel 8 pixels high and 32 to 128 pixels wide, on an ESP32 board you wired yourself.

Your build needs only two things: an LED panel on a supported data pin and power. Buttons, light sensor, battery, sound and the temperature sensor are optional. You can leave them off and add them later. You set the pins in the web UI, not in the firmware.

Two pages go with this one

GPIO & boards has every pin rule. System configuration describes every setting you write below. This page gives you the build order.


1. Pick the board

Any classic ESP32 board with 4, 8 or 16 MB of flash works, for example an ESP32 DevKit with a WROOM-32 module.

ESP32
Firmware image usb-awtrix-ng-4mb.bin (or 8/16 MB)
Usable GPIO 0-39, of which 34-39 are input-only
ADC for battery + LDR GPIO 32-39
Sound Passive buzzer, DFPlayer Mini
USB external USB-serial bridge on most boards

A board with 4 MB of flash is fine. More flash gives room for more icons and scripts.


2. Bill of materials

Required

Part Notes
ESP32 board, for example an ESP32 DevKit See above.
WS2812B panel, 8 pixels high 32 x 8 is the classic size. Several smaller panels in a row work too. The total width must be 32–128 px. SK6812 and compatible clones work. APA102, SK9822 and anything else with a separate clock line do not.
5 V power supply Sizing is in section 4. 5 V / 3-4 A for a 32 x 8 build.
1000 uF / 6.3 V+ electrolytic capacitor Across 5 V and GND at the panel input.
330-470 ohm resistor In series with the data line, at the board end.
A diffuser 2-3 mm milky acrylic, or a 3D-printed grid + paper. Bare WS2812B pixels are unreadable as text.

Optional: add what you want

Part Enables Guide
3 x momentary push button App navigation, menus, deep-sleep wake Buttons
LDR (for example GL5528) + 10 k resistor Auto-brightness Brightness & sensors
BME280 / BMP280 / HTU21DF / SHT31 Temperature, humidity, pressure apps Sensor bus
Passive piezo buzzer RTTTL melodies and beeps Sound
DFPlayer Mini + microSD + speaker numbered tracks alongside the buzzer DFPlayer boards
Li-Ion cell + TP4056 charger + 2 x 100 k Battery operation and reporting Power & battery
74AHCT125 level shifter Reliable 5 V data on long runs section 4

You do not need all of it. For each part you leave out, set its pin to -1 (not connected). Its values then disappear from device state, its Home Assistant entities are not created, and its built-in app leaves the rotation.


3. The standard pinout

These are the default pins. If you wire your board exactly like this, you do not need to set any pins. Install the firmware and it works.

The same wiring as the Ulanzi TC001, so a TC001 needs no pin changes either.

Function GPIO Direction Notes
LED data 32 out From the LED matrix list.
Button left 26 in, pull-up Active LOW, wire to GND.
Button select 27 in, pull-up Also the deep-sleep wake pin.
Button right 14 in, pull-up
Battery tap 34 ADC1 Input-only pin, which is fine for an ADC.
LDR tap 35 ADC1 Must be GPIO 32-39.
Buzzer 15 out Passive piezo.
I2C SDA 21 bidirectional Environment sensor.
I2C SCL 22 bidirectional
DFPlayer RX 23 in Set to -1 if unused.
DFPlayer TX 18 out Set to -1 if unused.

System diagram

Only the panel and its power supply are required. Everything else is optional.

5 V supply 3-4 A for 32 x 8 18 AWG to the panel +5 V GND 1000 uF 5V GND 5V GND ESP32 DevKit WS2812B panel 32 x 8 = 256 LEDs 8 px high, 32–128 px wide 470 R DIN GPIO 32 3 x push button each to GND, internal pull-up left / select / right select = deep-sleep wake GPIO 26 GPIO 27 GPIO 14 LDR divider GL5528 + 10 k, ADC1 GPIO 35 Battery divider 100 k / 100 k, ADC1 GPIO 34 Passive piezo buzzer RTTTL melodies GPIO 15 BME280 / SHT31 I2C, auto-detected at boot GPIO 21 SDA GPIO 22 SCL +5 V GND signal Peripheral ground returns are omitted - every block shares one ground with the board.

Connection list

Power. Wire these first. Never feed the panel through the ESP32 board.

From To Wire
PSU +5 V Panel 5 V, both ends on a wide panel 18 AWG
PSU GND Panel GND and board GND 18 AWG
PSU +5 V / GND 1000 uF capacitor, at the panel input short leads
PSU +5 V Board 5 V / VIN pin 22 AWG

Signals

Peripheral Its pin Board pin In line
Panel DIN GPIO 32 470 ohm series resistor
Button left one leg GPIO 26 other leg to GND
Button select one leg GPIO 27 other leg to GND
Button right one leg GPIO 14 other leg to GND
LDR divider tap GPIO 35 10 k to GND
Battery divider tap GPIO 34 100 k / 100 k
Buzzer + GPIO 15 - to GND
I2C sensor SDA GPIO 21 4.7 k pull-up if the breakout has none
I2C sensor SCL GPIO 22 same
DFPlayer Mini RX GPIO 18 (TX) 1 k in series
DFPlayer Mini TX GPIO 23 (RX) -

The buzzer and the DFPlayer are separate outputs, and you can build both. Set the pins of every part you did not build to -1.

Pins you cannot freely choose

AWTRIX checks these rules every time you save pins, and again at every start. All rules and the exact error messages are in GPIO & boards.

Rule Pins
Matrix pin must be on the LED matrix list 2, 4, 5, 13, 14, 15, 16, 18, 21, 25, 26, 27, 32, 33
Battery and LDR must be ADC1 32-39
Reserved, never assignable 6-11 (SPI flash)
Input-only, so no buttons, buzzer, I2C or TX there 34-39

Two more points. AWTRIX accepts these pins, but your hardware may not like them:

  • Strapping pins: 0, 2, 5, 12, 15. The chip reads them at power-on. Anything that holds them high or low can stop the board from starting.
  • Deep-sleep wake: only a select button on GPIO 0, 2, 4, 12–15, 25–27, 32–39 can end a /device/sleep early. On any other pin the button works normally while AWTRIX is awake, but it cannot wake it up.

AWTRIX reports the rules for its own chip. Use this instead of copying the tables into your own tools:

curl http://<awtrix-ip>/api/v1/capabilities

4. Power the panel first

Most DIY problems come from the power wiring.

AWTRIX NG does not limit LED current. A full-white picture at brightness 255 draws the full current, whether it comes from the mood light, Art-Net or a script. Plan your supply for that.

Build LEDs Worst case (all white, full brightness) Realistic clock use
32 x 8 256 ~15 A at 5 V 0.3-0.8 A
64 x 8 512 ~30 A at 5 V 0.6-1.5 A

You do not need a supply for the full maximum. 5 V / 3–4 A for a 32 x 8 panel covers every normal app and a bright notification. To stay inside it, limit the brightness instead of buying a bigger supply:

curl -X PATCH http://<awtrix-ip>/api/v1/settings \
  -H "Content-Type: application/json" \
  -d '{"autoBrightness":false,"brightness":120}'

With auto-brightness on, brightness is ignored. Cap the panel with maxBrightness in the system configuration instead.

Follow these wiring rules:

  1. Never power the panel through the ESP32 board's 5 V pin. Connect the panel directly to the supply. The board is fed from the same supply.
  2. Common ground. Connect board GND and panel GND. Without it the data signal has no reference and the panel shows random pixels.
  3. 1000 uF across 5 V/GND at the panel input, and a 330–470 ohm resistor in series with the data line at the board end. Both protect the first LED from voltage spikes.
  4. Feed power at both ends of panels wider than 32 px. Use proper wire: 18 AWG for the 5 V line, not breadboard jumpers.
  5. Data level. A WS2812B needs at least 0.7 × its supply voltage on DIN: 3.5 V at 5 V. An ESP32 sends only 3.3 V. Short cables usually work anyway. If the first pixels flicker or show wrong colors, add a 74AHCT125 level shifter. Or lower the panel supply to about 4.5 V with a diode in series, so 3.3 V is high enough.

Li-Ion safety

A battery build needs a protected cell and a proper charger (TP4056 with protection, or a dedicated charger chip). Never connect a cell directly to a GPIO. Connect it only through the divider in section 5. AWTRIX does not control or watch the charging.


5. Wire the options

Buttons

Wire three push buttons, each between its GPIO and GND. AWTRIX turns on the internal pull-up, so a pressed button reads LOW. You need no external resistors. If a button is noisy, add a 100 nF capacitor across it.

If the panel ends up upside down, fix it in the settings instead of resoldering: rotate turns the picture and swaps left and right, swapButtons swaps only the buttons.

Light sensor (auto-brightness)

Build a voltage divider from a GL5528-type LDR and a 10 k resistor, and connect the middle to the ADC pin:

3V3 LDR GL5528 GPIO 35 ADC1 10 k

Wired this way, more light gives a higher voltage. This matches the default ldrOnGround: false. If you swap the two parts, set {"ldrOnGround": true}.

Then calibrate: ldrFactor sets what counts as full light on your divider, ldrGamma shapes the curve. Both take effect at once. The full steps are in Brightness & sensors.

No LDR? Auto-brightness has no effect

With pinLdr: -1 the board has no light sensor. autoBrightness changes nothing and the panel uses brightness. The web UI hides the auto-brightness switch and its fields.

Battery monitoring

Build a 2:1 divider from the cell to an ADC1 pin:

BAT+ 4.2 V max 100 k GPIO 34 2.1 V at 4.2 V cell 100 k

4.2 V at the cell becomes 2.1 V at the pin, safely inside the ADC range. Tell AWTRIX the ratio, then correct it with a fully charged cell:

curl -X PUT http://<awtrix-ip>/api/v1/system \
  -H "Content-Type: application/json" \
  -d '{"batteryDividerRatio":2.0}'

batteryDividerRatio is V_cell / V_pin. To correct it:

  1. Charge the cell fully.
  2. Read batteryPinMillivolts from GET /api/v1/device.
  3. Write 4.2 / (batteryPinMillivolts / 1000) as batteryDividerRatio.

The percentage is estimated from the voltage of a typical Li-Ion cell, so it is not exact. See Power & battery.

Environment sensor

Connect one of BME280 (0x76/0x77), BMP280 (same addresses), HTU21DF or SHT31 (0x44) to the I2C pins. AWTRIX finds it at startup, looking in that order, and uses the first one that answers. So connect only one sensor. Most breakout boards have pull-up resistors. If yours does not, add 4.7 k from each line to 3V3.

All four measure temperature. BME280, HTU21DF and SHT31 also measure humidity. BME280 and BMP280 also measure air pressure. If the sensor reads too warm because of heat from the clock, correct it with tempOffset and humOffset.

Sound options

Option Hardware What you get Requires
Passive buzzer Piezo on pinBuzzer RTTTL melodies, notification beeps anything
DFPlayer Mini Module on pinDfRx/pinDfTx + microSD MP3 playback by track number dfplayer: true and both pins set

Buzzer: a passive piezo (not an active buzzer with its own oscillator), connected directly to the GPIO. It is quiet. A small NPN transistor with a 100 ohm base resistor makes it louder.

DFPlayer Mini: 5 V supply, a 1 k resistor in the line to the module's RX, and the speaker on SPK1/SPK2. It plays numbered tracks from its microSD card. The buzzer keeps playing melodies and RTTTL tunes. Set dfplayer: true.


6. Describe the panel

Tell AWTRIX how your panel is built. Every panel is 8 pixels high. The total width can be 32–128.

Key Range Default Meaning
panelWidth 1-128 32 Width of one panel. A new total width needs a restart.
panels 1-128 1 How many identical panels the cable runs through, left to right. panelWidth x panels must be 32–128.
panelStart topLeft topRight bottomLeft bottomRight topLeft Corner of the first LED.
panelWiring rows columns rows Whether the strip runs along rows or down columns.
panelColorOrder rgb rbg grb gbr brg bgr grb Color order the LEDs expect.
panelSerpentine bool true Every second row (or column) runs back the other way, the usual zigzag.
panelChainReverse bool false The cable enters the chain of panels at the other end. Does not change the wiring inside a panel.
panelChainSerpentine bool false Every second panel is turned by 180°, so its output sits next to the next panel's input.
mirror / rotate bool false For a panel mounted the wrong way round. Each does the same as picking a different panelStart. rotate also swaps the left and right button.

panelStart, panelWiring, panelColorOrder and panelSerpentine describe one panel. The two chain keys describe how the panels are joined. With a single panel the chain keys change nothing.

Common builds:

Build Configuration
Standard 32 x 8 panel the defaults
Four chained 8 x 8 tiles panelWidth 8, panels 4, panelSerpentine false
Four 8 x 8 tiles, each wired from its right edge panelWidth 8, panels 4, panelStart topRight, panelChainReverse true
Tiles mounted alternately, output next to input panelChainSerpentine true
32 x 8 wired in columns panelWiring columns
Panel shows red as green and green as red panelColorOrder rgb
64 px wide panel panelWidth 64
Four chained 32 x 8 panels (128 x 8) panelWidth 32, panels 4

If the picture is scrambled, try panelSerpentine first, then panelStart, then panelWiring. If each panel looks right but the panels are in the wrong order, or every second one is upside down, try panelChainReverse and panelChainSerpentine. These keys take effect at once, so you can watch the panel while you change them. Only a new total width needs a restart.


7. Flash and configure

  1. Install the firmware for your chip. See Install AWTRIX NG, with the browser installer or esptool. In the browser installer, choose Fresh install for a new board.
  2. Connect to Wi-Fi through the setup hotspot. See Connect to Wi-Fi.
  3. Write the pin map. Send all pins in one request. Some rules compare pins with each other (no duplicates, all three I2S pins). If you send only part of the map, a pin you have not yet moved can cause a rejection.
curl -X PUT http://<awtrix-ip>/api/v1/system \
  -H "Content-Type: application/json" \
  -d '{
        "pinMatrix": 32,
        "pinBtnLeft": 26,
        "pinBtnSelect": 27,
        "pinBtnRight": 14,
        "pinBattery": -1,
        "pinLdr": 35,
        "pinBuzzer": 15,
        "pinI2cSda": 21,
        "pinI2cScl": 22,
        "pinDfRx": -1,
        "pinDfTx": -1,
        "dfplayer": false,
        "panelWidth": 32,
        "panels": 1
      }'
  1. Restart. A new pin map takes effect only after a restart:
curl -X POST http://<awtrix-ip>/api/v1/device/reboot
  1. Calibrate what you wired: batteryDividerRatio for the divider, ldrFactor / ldrGamma / ldrOnGround for the light sensor, tempOffset / humOffset for the sensor. The defaults match the Ulanzi TC001 and will be wrong for your parts.
  2. Adjust the colors if the panel looks too cold or too warm: colorCorrection and colorTint in Settings.

You can also edit the pins under System → GPIO in the web UI. Each field is a dropdown that offers only the pins your chip can use for that part.

A pin map cannot make AWTRIX unusable

AWTRIX checks the stored map at every start. If it is not valid, for example a map saved on a board with another chip, AWTRIX starts with the default pins and stays reachable, so you can fix it. It keeps using the defaults until you save a valid map.


8. Verify the build

Work down this list. Each step tests one part of the hardware.

Check How Expected
Chip and rules curl http://<ip>/api/v1/capabilities soc matches your board. gpio lists the ranges from section 3
Panel geometry Web UI System → Panel 32 × 8 = 256 LEDs, or your size
Every pixel Send a full-white notification, or a mood light frame No dead pixels, no color shift down the run
Color order Push red text Red, not green or blue
Buttons Press each The app rotation moves; state/buttons/<button> fires over MQTT
Light sensor curl http://<ip>/api/v1/device while covering the LDR lightLevel falls towards 0
Battery same call batteryVoltage near 4.2 V on a full cell
Sensor same call temperature present and plausible
Sound Play a melody Audible

Troubleshooting a fresh build

Symptom Cause
Panel dark, device reachable Wrong pinMatrix, no common ground, or the panel has no 5 V of its own
First pixel wrong color, rest fine Missing series resistor or the 1000 uF capacitor
Flicker, colors drift down the strip 3.3 V data on 5 V pixels. Add a level shifter or drop the panel supply to ~4.5 V
Picture scrambled or mirrored panelSerpentine, then panelStart, then panelWiring
Red, green or blue appear as another color Select the panel's panelColorOrder. Red and green swapped usually needs rgb
Panels each correct but in the wrong order panelChainReverse: the cable enters the chain at the other end
Every second panel upside down panelChainSerpentine: the tiles are mounted alternately
Board resets on bright frames Supply too small, or panel current flowing through the dev board
Buttons dead or inverted Wired to 3V3 instead of GND. The buttons must pull the pin to ground
Left/right reversed swapButtons, or rotate if the whole panel is upside down
Panel stuck dim with autoBrightness on LDR not wired to pinLdr, or ldrOnGround set the wrong way
Percentage nonsense batteryDividerRatio still at the default
No temperature Sensor not on the bus, missing pull-ups, or a second chip answering first
invalidPinConfig on a write The message names the field and the rule. See Errors