You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Support for SM16824E and SM167035P3 and help with protocol #1941
I'm currently working on building a custom controller for a Chinese LED strobe.
The LED board contains 48 RGB pixels, each controlled by its own SM16703P3 IC.
In addition to the 48 RGB pixels, there are 8 white-only LEDs. These are controlled by three SM16824E ICs, where:
Red channel = White Pixel 1
Green channel = White Pixel 2
Blue channel = White Pixel 3
...and so on.
The problem I'm encountering is that there are three SM16824E ICs available for a total of 9 white LEDs, but only 8 are actually connected. So one output channel remains unused.
When I control the strobe using the factory controller, the white LED dimming works perfectly.
However, when I use my custom controller, as soon as I try to increase the brightness of the second-last (in this case led 8, because 9 is not connected) white LED, all the other white LEDs begin to flicker.
So my question is:
Could this be an issue with the library, or is it more likely a hardware problem?
I'm asking because the original factory controller doesn't show this behavior at all.
My current setup looks like this:
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); (also tried any other protocol than neopixel, like the SM1670)
Where NUM_LEDS = 48 (RGB ICs) + 3 (White ICs)
Actually for this specific pair it should work — the SM16824E datasheet you attached specifies T0H=300 / T0L=900 / T1H=900 / T1L=300 ns, which is identical to the SM16703 RZ timing. Both are WS2811-800kHz clones at the wire level.
The flicker on the shared bus is on us: TIMING_SM16824E in FastLED currently emits T1H=1200 ns / T1L=100 ns, which is out of spec on the SM16703 side (T1H max 1000 ns) and doesn't match your SM16824E datasheet either. The doc comment in src/chipsets.h even contradicts the numbers being clocked out.
Workaround until that's fixed: drive the whole bus with SM16703 — the SM16824Es will then see waveforms that match their own datasheet.
@einlichtvogel — fix is in flight: PR #3204 (tracked in #3203) aligns TIMING_SM16824E with the datasheet you attached. Algorithmically validated via ci/tools/led_timing_conversions.py against both the SM16703P datasheet window and the SM16824E datasheet window — old 300/900/100 emitted T1H=1200 ns / T1L=100 ns (out of spec both ways), new 300/600/300 emits T0H=300 / T0L=900 / T1H=900 / T1L=300 / cycle=1200 ns (in spec for both).
Once merged you can drive the whole shared bus with either controller:
// Either of these will now emit a waveform that satisfies// both SM16703P and SM16824E datasheets:
FastLED.addLeds<SM16703, DATA_PIN, RGB>(leds, total_slots);
FastLED.addLeds<SM16824E, DATA_PIN, RGB>(leds, total_slots);
If you'd be willing to confirm the fix on the hardware combo (SM16703 + SM16824E on one data line) once #3204 merges, that would close the loop on this thread.
TIMING_SM16824E now emits T0H=300 / T0L=900 / T1H=900 / T1L=300 / cycle=1200 ns — algorithmically verified spec-compliant against both the SM16824E datasheet and the SM16703P datasheet (via ci/tools/led_timing_conversions.py).
Because both chips share the same RZ-code profile, you can now drive a mixed SM16703 + SM16824E bus from a single controller — either SM16703 or SM16824E works on the shared data line.
@einlichtvogel — please feel free to reopen if it doesn't resolve your mixed-bus case on hardware. (The network-induced flicker you saw later in this thread is a separate ESP32 + RMT + WiFi issue and not affected by this fix.)
Oh, one more thing, for flicker during WIFI, you can try out one of the new drivers that we have, like the UART/parlio/lcd (not sure which esp you have or if you have an esp at all). RMT does not have a lot of memory so it can buffer underrun easily. The other drivers have large DMA buffers and are resistant to flicker.
Tried it with ESP32 Pico D4 (M5Stack Matrix ATOM 1)
Both are classic ESP32 (the original dual-core LX6 generation, internally FL_IS_ESP_32DEV). That matters for driver choice — the menu of "WiFi-resistant" drivers is not the same set you'd have on an ESP32-S3 or -C6.
What you can / can't use on classic ESP32
From src/platforms/esp/32/feature_flags/enabled.h:
Driver (fl::Bus::X)
Classic ESP32 (yours)
Notes
RMT
✅
What you're on today. Small per-channel buffer → underruns under WiFi interrupt load.
I2S
✅
Recommended. Original ESP32's I2S parallel mode. Large DMA, immune to WiFi jitter, can drive multiple strips in parallel. Disabled on every newer ESP32 variant.
UART
✅
DMA-backed, one strip per UART peripheral (you have 3). Also WiFi-resistant. Good if you only need one strip.
SPI (clockless)
✅ (IDF 5.0+)
Clockless-over-SPI MOSI, DMA. Useful if I2S/UART pins conflict.
PARLIO
❌
ESP32-P4 / C6 / H2 / C5 only. Not on classic ESP32.
LCD_RGB, LCD_SPI, LCD_CLOCKLESS
❌
ESP32-S3 / P4 only.
I2S_LCD_CAM
❌
ESP32-S3 only.
So ignore the PARLIO / LCD suggestion — they don't exist on your chip. The two real answers for you are I2S (best) or UART (simpler).
Option A — quickest fix: keep addLeds<>, pin to I2S at compile time
This is a one-line change to the code you already have. Every FastLED.addLeds<> variant now accepts an optional trailing fl::Bus template parameter (#2460). Naming fl::Bus::I2S at the call site is what links the I2S driver translation unit, so it actually runs your show().
#include"FastLED.h"// The per-driver bus_traits.h #include is the explicit opt-in that links// the driver TU. Without it you'll get// "implicit instantiation of undefined template BusTraits<Bus::I2S>".
#include"platforms/esp/32/drivers/i2s/bus_traits.h"
#defineDATA_PIN4
#defineNUM_LEDS51// your existing buffer lengthCRGB leds[NUM_LEDS];
voidsetup() {
// Trailing fl::Bus::I2S template arg routes show() through the// DMA-backed I2S parallel engine instead of RMT.
FastLED.addLeds<SM16703, DATA_PIN, RGB, fl::Bus::I2S>(leds, NUM_LEDS);
}
voidloop() {
// your existing code, unchanged
FastLED.show();
}
Use SM16703 (works for both your SM16703 and SM16824E ICs — confirmed in PR #3204 that just merged).
#include"FastLED.h"
#include"fl/channels/channel.h"
#include"fl/channels/config.h"
#include"fl/chipsets/led_timing.h"
#defineDATA_PIN4
#defineNUM_LEDS51CRGB leds[NUM_LEDS];
voidsetup() {
auto timing = fl::makeTimingConfig<fl::TIMING_SM16703>();
fl::ChannelConfig cfg("strip", fl::ClocklessChipset(DATA_PIN, timing),
fl::span<CRGB>(leds, NUM_LEDS), RGB);
// Pick the I2S driver at runtime. The non-template FastLED.add(cfg)// path auto-enables every driver on the platform; larger binary but// no per-driver #include needed.
cfg.options.mBus = fl::Bus::I2S;
FastLED.add(cfg);
}
voidloop() {
FastLED.show();
}
Switching to UART is one line: cfg.options.mBus = fl::Bus::UART;.
What to expect
Compile-time path (Option A) keeps your binary small — --gc-sections drops every driver you didn't name.
Runtime path (Option B) links every driver on the platform — bigger flash footprint, but you can choose the bus from config/UI without recompiling.
Either way, the WiFi-induced flicker you were seeing on RMT should drop dramatically because the I2S/UART DMA engines aren't sensitive to short interrupt bursts the way RMT's per-channel buffer is.
If I2S doesn't fit (e.g. the ETH01's LAN8720 PHY is using pins you also need), UART is a clean fallback for a single strip. If neither works for layout reasons, ping back and we'll look at clockless-SPI (fl::Bus::SPI).
... uh you are on the esp32 and not one of the newer ones. I2S may or may not work for you at this point. Esp32 is the final boss before FastLED 4 is released.
Activity
[-]Support for SM16824E and SM167035P3[/-][+]Support for SM16824E and SM167035P3 and help with protocol[/+]zackees commentedon Jun 17, 2025
Timing could be off. I'm guessing this is a WS2812 clone.
Quick solution is to use the overlock feature (see readme and we also have an example).
Use an overlock factor of .9 or 1.1 and see if the problem goes away. If it does then post the results here and I'll add the controller type.
The over clock will compress/expand the THO timing, which is critical in the clockless chipset.
einlichtvogel commentedon Jun 17, 2025
No, overclocking does not help anything.
Maybe, because these two types of ICs are on the same data line?
Also: When LED 8 is at 0, all other LEDs have normal dim behaviour, as soon as led 8 is up, they begin to flicker.
einlichtvogel commentedon Jun 17, 2025
https://github.com/user-attachments/assets/3deb967f-a34a-41db-9e03-5c9f66e075e8
This is the behaviour with the factory controller
https://github.com/user-attachments/assets/0cd85eb3-9c0d-4406-8822-2a7b43598e5b
This is the behaviour with the libary
zackees commentedon Jun 17, 2025
hmmm having trouble seeing the attachment. github is throwing an error.
On a high level, I don't believe we actually support that chipset? Can you confirm? I'm on mobile. See the readme to confirm supported chipsets.
zackees commentedon Jun 17, 2025
I was able to download your vids on desktop.
zackees commentedon Jun 17, 2025
Yeah it's not one of the supported led chipsets.
I'm having trouble finding the datasheet for the timings, can you provide it?
einlichtvogel commentedon Jun 17, 2025
Oh well, I already thought this will be the case.
This is the only datasheet I found: https://de.scribd.com/document/757938003/SM16824E-zh-CN-en-1
zackees commentedon Jun 17, 2025
SM16824E
FastLED timings
einlichtvogel commentedon Jun 17, 2025
But then, for reference, if the timing finally would work, I have the case that 2 different ICs are on the same data line.
What to do about that one?
zackees commentedon Jun 17, 2025
I added controller SM16824E
It's now in master.
You can add it like this:
You hope the IC's are close enough in timing that it works.
einlichtvogel commentedon Jun 17, 2025
Now, none of the LEDs work anymore.
Just the first channel of the IC does.
EDIT: No, it doesn't, just random flickering leds.
zackees commentedon Jun 17, 2025
Can you edit this
FastLED/src/chipsets.h
Line 1132 in 24a0c0e
With timings until it works?
einlichtvogel commentedon Jun 17, 2025
I can try, which of the 3 do I need to change?
zackees commentedon Jun 17, 2025
All of them. FastLED uses a weird timing code called T0, T1, T3
T0 is the length of time before a 0, T1 is the additional time before a 1, T3 is the additional time before the next bit is signaled.
So the total duration will be = T1 + T2 + T3
You can generate a T1, T2, T3 from T0H...T1L timings using this python script:
FastLED/src/chipsets.h
Line 969 in 24a0c0e
52 remaining items
zackees commentedon Jun 15, 2026
most likely fail
einlichtvogel commentedon Jun 15, 2026
So, running different ICs on one DL is not possible?
zackees commentedon Jun 15, 2026
it's possible if their protocols are compatible
einlichtvogel commentedon Jun 15, 2026
so in this case, it might not be the case, correct?
einlichtvogel commentedon Jun 15, 2026
SM16824E seems not to be working, the flickering is still there.
Tried it with ESP32 Pico D4 (M5Stack Matrix ATOM 1)
I'll give up, longe have we tried, and thank you for officially implementing it.
Will contact the manuafacturer, see what they say.
zackees commentedon Jun 17, 2026
Actually for this specific pair it should work — the SM16824E datasheet you attached specifies T0H=300 / T0L=900 / T1H=900 / T1L=300 ns, which is identical to the SM16703 RZ timing. Both are WS2811-800kHz clones at the wire level.
The flicker on the shared bus is on us:
TIMING_SM16824Ein FastLED currently emits T1H=1200 ns / T1L=100 ns, which is out of spec on the SM16703 side (T1H max 1000 ns) and doesn't match your SM16824E datasheet either. The doc comment insrc/chipsets.heven contradicts the numbers being clocked out.Workaround until that's fixed: drive the whole bus with
SM16703— the SM16824Es will then see waveforms that match their own datasheet.Tracking the timing fix separately in #3203.
zackees commentedon Jun 17, 2026
@einlichtvogel — fix is in flight: PR #3204 (tracked in #3203) aligns
TIMING_SM16824Ewith the datasheet you attached. Algorithmically validated viaci/tools/led_timing_conversions.pyagainst both the SM16703P datasheet window and the SM16824E datasheet window — old300/900/100emitted T1H=1200 ns / T1L=100 ns (out of spec both ways), new300/600/300emits T0H=300 / T0L=900 / T1H=900 / T1L=300 / cycle=1200 ns (in spec for both).Once merged you can drive the whole shared bus with either controller:
If you'd be willing to confirm the fix on the hardware combo (SM16703 + SM16824E on one data line) once #3204 merges, that would close the loop on this thread.
fix(SM16824E): align TIMING_SM16824E with datasheet (300/600/300) (#3204
zackees commentedon Jun 17, 2026
Resolved by #3204 (merged ba46ef1 → master).
Summary of the fix:
TIMING_SM16824Enow emits T0H=300 / T0L=900 / T1H=900 / T1L=300 / cycle=1200 ns — algorithmically verified spec-compliant against both the SM16824E datasheet and the SM16703P datasheet (viaci/tools/led_timing_conversions.py).SM16703orSM16824Eworks on the shared data line.@einlichtvogel — please feel free to reopen if it doesn't resolve your mixed-bus case on hardware. (The network-induced flicker you saw later in this thread is a separate ESP32 + RMT + WiFi issue and not affected by this fix.)
zackees commentedon Jun 18, 2026
Oh, one more thing, for flicker during WIFI, you can try out one of the new drivers that we have, like the UART/parlio/lcd (not sure which esp you have or if you have an esp at all). RMT does not have a lot of memory so it can buffer underrun easily. The other drivers have large DMA buffers and are resistant to flicker.
It's easiest if you use the channels api, as the legacy api for enabling a specific driver is not well documented, but will be soon. See https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md
AI come in shortly and give you more details.
zackees commentedon Jun 18, 2026
Hi @einlichtvogel — Claude here, following up as @zackees said.
Your platform
Pulled from your earlier messages:
…and later:
Both are classic ESP32 (the original dual-core LX6 generation, internally
FL_IS_ESP_32DEV). That matters for driver choice — the menu of "WiFi-resistant" drivers is not the same set you'd have on an ESP32-S3 or -C6.What you can / can't use on classic ESP32
From
src/platforms/esp/32/feature_flags/enabled.h:fl::Bus::X)RMTI2SUARTSPI(clockless)PARLIOLCD_RGB,LCD_SPI,LCD_CLOCKLESSI2S_LCD_CAMSo ignore the PARLIO / LCD suggestion — they don't exist on your chip. The two real answers for you are I2S (best) or UART (simpler).
Option A — quickest fix: keep
addLeds<>, pin to I2S at compile timeThis is a one-line change to the code you already have. Every
FastLED.addLeds<>variant now accepts an optional trailingfl::Bustemplate parameter (#2460). Namingfl::Bus::I2Sat the call site is what links the I2S driver translation unit, so it actually runs your show().Use
SM16703(works for both your SM16703 and SM16824E ICs — confirmed in PR #3204 that just merged).To try UART instead, swap two things:
Option B — the Channels API (runtime bus selection)
Same outcome, more explicit configuration. Better when you want to change the driver at runtime or have multiple strips with different drivers. Full docs: https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md
Switching to UART is one line:
cfg.options.mBus = fl::Bus::UART;.What to expect
--gc-sectionsdrops every driver you didn't name.If I2S doesn't fit (e.g. the ETH01's LAN8720 PHY is using pins you also need), UART is a clean fallback for a single strip. If neither works for layout reasons, ping back and we'll look at clockless-SPI (
fl::Bus::SPI).zackees commentedon Jun 18, 2026
... uh you are on the esp32 and not one of the newer ones. I2S may or may not work for you at this point. Esp32 is the final boss before FastLED 4 is released.
einlichtvogel commentedon Jun 20, 2026
Will try it in a week, currently on tour.
I was using the M5Stack Atom1 with the matrix as test in this case. Think it has a ESP32-PICO-D4