Skip to content

Commit 031e083

Browse files
committed
Move the rack example to WS2815 on 12 V
WS2812B has no answer to the failure this install will actually have: one dead pixel darkens the rest of that row, and the row is 114 pixels glued behind wine bins nobody can reach. WS2815 carries a backup data line - each pixel also receives from the one two places back - so a dead chip is a dark bin rather than a dark row. Twelve volts is the other half of it. The same picture that drew 17.8 A draws 8.3 A, which takes the feed from 10 AWG to 14, the fuse from 25 A to 15, and the power taps from twenty-six to thirteen: at 0.6 A a strand can be fed from its head end alone. Rev B's summary claimed 12 V gives "about 5x the margin" on voltage drop. That framing was wrong. What matters is the gap to the pixel's minimum working voltage, and that is 1.5 V either way - 5.0 to 3.5 for a WS2812B, 12.0 to 10.5 for a WS2815. The gain is the 2.15x current reduction, which turns a 1.2x margin into 2.6x. Decisive, but 2x rather than 5x. Two costs, both stated in the file. Total power rises slightly, because each pixel regulates 12 V down and dissipates the difference as heat in the strip. And the always-on backup-line logic doubles idle draw to 18 W, which in a room being actively cooled is worth switching off. The firmware is unchanged apart from comments: WS2815 speaks the same 800 kHz protocol, so `chipset: WS2812B` is still what ESPHome is told. Compiles clean; 466 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011au3uaZneMFTbnssPSwpLt
1 parent 7edb910 commit 031e083

3 files changed

Lines changed: 45 additions & 25 deletions

File tree

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ in the room rather than on a screen. `examples/` holds a working pair of configu
482482

483483
| File | What it is |
484484
|---|---|
485-
| `examples/esphome/winerack1led.yaml` | An ESPHome node driving one WS2812 strand per rack row, with a block of LEDs behind each bin |
485+
| `examples/esphome/winerack1led.yaml` | An ESPHome node driving one WS2815 strand per rack row, with a block of LEDs behind each bin |
486486
| `examples/home_assistant/wine_rack_leds.yaml` | The Home Assistant package that turns this integration's inventory into what the node paints |
487487

488488
The rack is a 13 x 13 grid: rows **A**-**M**, bins **1**-**13**, addressed the way CellarTracker
@@ -540,9 +540,12 @@ Three things are worth knowing before you cut LED strip:
540540
can have, so the config drives them with FastLED, which takes a channel per strand and hands it
541541
back for the next one. `neopixelbus` cannot: it holds a channel per strand for the life of the
542542
node and runs out at ten.
543-
- **Power.** 1014 pixels can be lit at once. At the palette in the file that is 10.2 A for a
544-
fully green rack and 17.8 A worst case — a 5 V 25 A supply, or half of everything if you drop
545-
`bin_leds` from 6 to 3. Every strand wants feeding at both ends. The file shows the arithmetic.
543+
- **Power.** 1014 pixels can be lit at once. On the 12 V WS2815 strip the file assumes, that is
544+
5.1 A for a fully green rack and 8.3 A worst case — a 12 V 12.5 A supply, a 15 A fuse, and a
545+
single feed at the head of each strand. The file shows the arithmetic.
546+
- **WS2815, not WS2812B.** The backup data line means one dead pixel is one dark bin rather than
547+
a dark row, which matters behind a rack you cannot get at. It costs a second rail: 12 V for the
548+
LEDs, 5 V from a buck for the ESP32 and the level shifters.
546549

547550
---
548551

examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ loaded by Home Assistant on its own — copy what you want.
55

66
| File | What it is |
77
|---|---|
8-
| [`esphome/winerack1led.yaml`](esphome/winerack1led.yaml) | An ESPHome node that lights a 13 × 13 wine rack with WS2812 strips, one strand per row |
8+
| [`esphome/winerack1led.yaml`](esphome/winerack1led.yaml) | An ESPHome node that lights a 13 × 13 wine rack with WS2815 strips, one strand per row |
99
| [`home_assistant/wine_rack_leds.yaml`](home_assistant/wine_rack_leds.yaml) | The Home Assistant package that turns the cellar's inventory into what that node paints |
1010

1111
The two are halves of one thing: the node owns the pixels and knows nothing about wine, and the

examples/esphome/winerack1led.yaml

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Wine rack 1 - bin lighting for the CellarTracker integration
22
# =============================================================================
33
#
4-
# One WS2812 strand per rack row, one block of LEDs per bin. Home Assistant
4+
# One WS2815 strand per rack row, one block of LEDs per bin. Home Assistant
55
# tells the board what to show; the board owns nothing but the pixels.
66
#
77
# Two things are drawn:
@@ -54,8 +54,8 @@
5454
# repository should be regenerated before it goes in there.
5555
#
5656
# 2. Why FastLED and not neopixelbus. A classic ESP32 has eight RMT channels
57-
# and two I2S buses to get WS2812 timing from - ten strands' worth of
58-
# hardware for thirteen strands. That is a limit on how many can transmit
57+
# and two I2S buses to get WS2812-protocol timing from - ten strands' worth
58+
# of hardware for thirteen strands. That is a limit on how many can transmit
5959
# at once rather than on how many you can have, and it is the whole
6060
# difference between the two components: FastLED takes a channel per strand
6161
# as it goes and hands it back for the next one, so thirteen strands
@@ -74,30 +74,42 @@
7474
# ESPHome's supported component, and the one that works under ESP-IDF. That
7575
# means reworking the per-strand lambdas to cover more than one row.
7676
#
77-
# 3. Power. Budget a WS2812 at 20 mA per colour channel at full scale plus
78-
# 1 mA for being powered at all, so one pixel is
77+
# 3. Power. The strips are WS2815 on a 12 V rail. Budget a pixel at 0.3 W -
78+
# 25 mA at 12 V - at full white, scaling with the sum of its channels,
79+
# plus about 1 mA standing for the controller and the backup-line logic:
7980
#
80-
# (R + G + B) / 255 * 20 mA + 1 mA
81+
# (R + G + B) / 765 * 25 mA + 1 mA @ 12 V
8182
#
8283
# 13 rows x 13 bins x 6 LEDs is 1014 pixels that can be lit at once, out of
8384
# 1482 powered. That makes the whole rack:
8485
#
85-
# everything off ............................ 1.5 A
86-
# every bin ready (0, 110, 0) .............. 10.2 A
87-
# every bin drink-this-year (150, 55, 0) ... 17.8 A <- the worst case
88-
# per strand, at that worst case ............ 1.4 A
86+
# everything off ............................ 1.5 A (18 W)
87+
# every bin ready (0, 110, 0) ............... 5.1 A
88+
# every bin drink-this-year (150, 55, 0) .... 8.3 A <- the worst case
89+
# per strand, at that worst case ............ 0.6 A
8990
#
90-
# So: a 5 V supply of 25 A, a fuse that protects the feed cable rather than
91-
# the LEDs, and power injected at BOTH ends of every strand - a 1 m strand
92-
# at 1.4 A fed from one end only drops its far bins to around 3.1 V, and a
93-
# WS2812 wants 3.5 V. Halving `bin_leds` to 3 halves all of it and still
94-
# reads as a solid marker behind a bottle; that is much the cheapest way to
95-
# get to a 15 A supply and 14 AWG.
91+
# So: a 12 V supply of 12.5 A, a 15 A fuse protecting the 14 AWG feed
92+
# rather than the LEDs, and - unlike the 5 V version this replaced - a
93+
# single feed at the head of each strand is enough. A 1.1 m strand at
94+
# 0.6 A drops about 0.3 V, against the 1.5 V of budget between 12 V and
95+
# the 10.5 V a WS2815 wants. Measure your strip's copper before trusting
96+
# that; over 1 ohm/m per rail, or strands longer than 1.5 m, feed both ends.
9697
#
97-
# The palette is what keeps those numbers reachable - no channel goes above
98-
# 150, and gamma_correct is 1.0, so these values are what the LEDs actually
99-
# draw. Full white on every pixel would be 62 A. Do not raise the palette
100-
# without redoing the arithmetic.
98+
# The 12 V rail powers only the LEDs. The ESP32 and the level shifters run
99+
# from a small 12 V -> 5 V buck off the same bus, and every ground - buck
100+
# included - returns to the PSU terminal rather than through a strip.
101+
#
102+
# Two things 12 V costs you. Total power is slightly higher than the 5 V
103+
# equivalent, because each pixel regulates 12 V down and dissipates the
104+
# difference as heat in the strip. And the always-on backup-line logic
105+
# makes idle 18 W rather than 7 W, which in a room you are paying to keep
106+
# cold is worth switching off - see the blueprint for the high-side switch
107+
# and the output-enable interlock that goes with it.
108+
#
109+
# The palette is what keeps those numbers modest - no channel goes above
110+
# 150, and gamma_correct is 1.0, so these values are what the pixels
111+
# actually draw. Full white everywhere would be 28 A. Halving `bin_leds`
112+
# to 3 halves the lot and still reads as a solid marker behind a bottle.
101113
#
102114
# =============================================================================
103115

@@ -379,6 +391,11 @@ script:
379391
# still scales the whole row, so Home Assistant's slider is a master dimmer.
380392
.strand: &strand
381393
platform: fastled_clockless
394+
# The hardware is WS2815 - 12 V, and with the backup data line that keeps a
395+
# row alive when one pixel dies. ESPHome has no name for it because it does
396+
# not need one: WS2815 speaks the same 800 kHz protocol as a WS2812B, so
397+
# that is the chipset to declare. Wire the first pixel's BI pad alongside
398+
# its DI; left floating it can oscillate and take the row with it.
382399
chipset: WS2812B
383400
rgb_order: GRB
384401
num_leds: ${strand_leds}

0 commit comments

Comments
 (0)