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
Animated Staircase: segments not fading out but switched on/off instantly in version 16.0.0 and 16.0.1 #5731
From version 16 i have a strange behaivor with the staircase mod on my esp32.
When the sensor is getting triggert, it's putting all the led segments on, and you see on background off the leds it's "fading" each segment. And that's also with going out, you see a little fade en then all the segements going out.
When i switch back to a version below 16 its working all fine.
To Reproduce Bug
Working all fine with versions below 16. From version 16 it's starting. Also not fixt in 16.0.1.
Expected Behavior
fading on/of each segment. instead of full on and a little "fade" in de background
Install Method
Self-Compiled
What version of WLED?
WLED 16.0.1 2605010
Which microcontroller/board are you seeing the problem on?
All the segments are going on, and then you see a little bit brightness differance in the segments going up. And if i upload version 15.4 back it's working like it should be.
@coderabbitai please compare the /usermods/Animated_Staircase between the 16_x and 0_15_x branch, and look for differences that can explain the behaviour observed by the user. Also take difference in the wled core into consideration, especially the new segment blending and effect transitions code, and different handling of gamma correction. Assume a nominal configuration witch several segments running the "solid" effect at high brightness.
@softhack007, comparison complete. The likely explanation is the WLED 16 core transition/compositing change, not a functional change in Animated_Staircase.
Animated Staircase: no behavioral regression found
Between 0_15_x and 16_x, the usermod logic is unchanged:
updateSegments() still enables/disables each active segment through seg.setOption(SEG_OPTION_ON, ...).
updateSwipe() still advances the staircase one segment per segment_delay_ms.
Enabling the usermod still sets the global transition duration to segment_delay_ms (default: 150 ms):
However, the rendering route changed substantially.
WLED 15
WLED 16
Effects write directly to the bus output.
Effects write into an individual segment buffer.
Segment colors are gamma-corrected before the effect runs.
Segment buffers are composited, then final output gamma correction is applied.
currentBri() exists, but Solid filling SEGCOLOR(0) does not itself scale its pixels by that transitional brightness.
blendSegment() uses topSegment.currentBri() as the segment opacity during composition.
On/off transitions therefore do not produce the same physically interpolated per-segment fade path.
Each newly enabled segment is visibly faded in, including during Solid.
In 16, WS2812FX::blendSegment() does this:
uint8_t opacity = topSegment.currentBri();
if (gammaCorrectCol) opacity = gamma8inv(opacity);
It blends the segment into the frame buffer with that opacity, and WS2812FX::show() then applies gamma32() to the final pixel output.
So the unchanged usermod sequentially starts an on-transition for every stair segment, while 16 now actually composites that transition as segment opacity. With several high-brightness Solid segments, the latest segment(s) remain visibly dimmer until their 150 ms fade completes. Gamma-correct compositing makes that partial-ramp difference especially obvious.
Conclusion
This explains a temporary brightness gradient during the upward/downward sweep:
Staircase enables a segment.
WLED 16 fades that segment from black to its Solid color.
The next segment starts shortly after.
Previously activated segments are closer to full opacity than newly activated ones.
That behavior is consistent with the supplied 16.0.x video and would not appear equivalently on 15.4 because the old direct-rendering pipeline did not apply the same per-segment opacity composition to Solid.
Recommended verification / mitigation
Set the transition duration to 0 (or otherwise bypass transitions) as a diagnostic. If the brightness differences disappear, this confirms the transition-compositing path.
Alternatively, make the staircase usermod turn segments on immediately while retaining its own segment_delay_ms as only the step timing.
If brightness remains unequal after the whole swipe plus transition time has elapsed, this analysis does not explain it. Then inspect:
automatic brightness limiting / power supply limiting,
segment opacity and blend mode,
segment overlap, grouping, or spacing,
LED power injection and wiring.
The gamma redesign is relevant primarily because it changes the visual shape of partial fades; it should not leave otherwise identical, fully settled, non-overlapping Solid segments at different brightness.
@DedeHai It looks like the usermod changes the segment "on" state directly. Could the problem be related to the known limitation that segment on/off does not use transitions/fading in 16.0?
@softhack007, yes — in 0_15_x, toggling a segment’s on option was designed to cross-fade, provided that fade transitions were enabled and the configured transition duration was non-zero.
The relevant 0.15.x path is:
Segment &Segment::setOption(uint8_t n, bool val) {
bool prevOn = on;
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn)
startTransition(strip.getTransition()); // before changing `on`if (val) options |= 0x01 << n;
else options &= ~(0x01 << n);
...
}
During that transition, Segment::currentBri() interpolates from the saved old brightness to the new effective brightness:
So an on-toggle fades from 0 → opacity, and an off-toggle from opacity → 0. In other words, the Animated Staircase usermod’s direct SEG_OPTION_ON updates could produce the expected per-segment fade on 0.15.x.
This makes #5520 / #5524 highly relevant to the reported regression. WLED 16 retains calls to startTransition() in Segment::setOption(), but the 16.0.x transition/compositing lifecycle has a known defect: its global transition handling can stop per-segment transitions prematurely or otherwise fail to render non-Fade transition styles correctly. #5520’s reports match that: segment toggles snap immediately in 16.0.x, while Fade may be the exception. PR #5524 is explicitly titled “make per-segment on/off and brightness behave the same as global.”
So I would revise the earlier conclusion:
0.15.x: direct segment toggles cross-faded under the Fade transition path.
16.0.x: the intended support exists, but the known segment-transition issue can prevent it from behaving equivalently.
Therefore, this is a plausible explanation for the Animated Staircase behavioral difference, and testing the usermod with the #5524 patch is the most targeted verification.
@softhack007, transitionDelayDefault is not the right one here. It is the persisted configuration default (cfg.json) and is restored during startup:
WLED_GLOBALuint16_t transitionDelayDefault _INIT(750); // default transition time (stored in cfg.json)
For the currently active global transition setting, transitionDelay is the corresponding global:
WLED_GLOBALuint16_t transitionDelay _INIT(750); // global transition duration
However, for Animated_Staircase, neither global alone controls the immediate segment-toggle transition: Segment::setOption() ultimately uses the duration held by strip, so this is the operative call:
strip.setTransition(segment_delay_ms);
Thus, the present transitionDelay assignment is semantically preferable to transitionDelayDefault, but it is redundant for the immediate effect because strip.setTransition() follows it.
The more important issue is that the usermod currently does not restore the previous active transition duration when disabled. It therefore permanently changes the running transition duration to segment_delay_ms for the rest of the session (and transitionDelay may subsequently be serialized as current state).
A safer approach is to save strip.getTransition() when enabling, set only the temporary strip transition for the staircase, and restore the saved value when disabling. transitionDelayDefault should remain untouched.
changed the title [-]version 16.0.0 and 16.0.1 Animated Staircase bug[/-][+]Animated Staircase: segments not fading out but switched on/off instantly in version 16.0.0 and 16.0.1 [/+]on Jul 22, 2026
Just to add something to this issue... which may or may not be relevant, but I have observed when I try to apply Swipe left or right to a 16.0.1 set up with multiple segments it does not work, but yesterday I threw together a very simple set up for a light behind my PC with a single segment and the swipes all worked.
Activity
[-]version 16,0.0 and 16.0.1 Animated Staircase bug[/-][+]version 16.0.0 and 16.0.1 Animated Staircase bug[/+]DedeHai commentedon Jul 10, 2026
not really clear what you mean, a video comparison would help
Alfagek commentedon Jul 10, 2026
Version below 16 (like it should work, this is version 15.4): https://share.icloud.com/photos/064XZHw-sHwW6zwc21e8DooTw
Version 16.0.0 and also 16.0.1: https://share.icloud.com/photos/0c1obqgxZSY6P82gULVyMyfhQ
All the segments are going on, and then you see a little bit brightness differance in the segments going up. And if i upload version 15.4 back it's working like it should be.
Hopely it's a bit more clear now ;-)
softhack007 commentedon Jul 21, 2026
@coderabbitai please compare the /usermods/Animated_Staircase between the
16_xand0_15_xbranch, and look for differences that can explain the behaviour observed by the user. Also take difference in the wled core into consideration, especially the new segment blending and effect transitions code, and different handling of gamma correction. Assume a nominal configuration witch several segments running the "solid" effect at high brightness.coderabbitai commentedon Jul 21, 2026
🧩 Analysis chain
🏁 Script executed:
Length of output: 1454
🏁 Script executed:
Length of output: 4157
🏁 Script executed:
Length of output: 1797
🏁 Script executed:
Length of output: 2022
🏁 Script executed:
Length of output: 117118
🏁 Script executed:
Length of output: 42437
🏁 Script executed:
Length of output: 27255
@softhack007, comparison complete. The likely explanation is the WLED 16 core transition/compositing change, not a functional change inAnimated_Staircase.Animated Staircase: no behavioral regression found
Between
0_15_xand16_x, the usermod logic is unchanged:updateSegments()still enables/disables each active segment throughseg.setOption(SEG_OPTION_ON, ...).updateSwipe()still advances the staircase one segment persegment_delay_ms.segment_delay_ms(default: 150 ms):The only source differences are removing
#pragma onceafter changing the file from.hto.cpp, and adding static usermod registration.Why WLED 16 can show the reported brightness staircase
Soliditself remains unchanged in both branches:However, the rendering route changed substantially.
currentBri()exists, butSolidfillingSEGCOLOR(0)does not itself scale its pixels by that transitional brightness.blendSegment()usestopSegment.currentBri()as the segment opacity during composition.In 16,
WS2812FX::blendSegment()does this:It blends the segment into the frame buffer with that opacity, and
WS2812FX::show()then appliesgamma32()to the final pixel output.So the unchanged usermod sequentially starts an on-transition for every stair segment, while 16 now actually composites that transition as segment opacity. With several high-brightness Solid segments, the latest segment(s) remain visibly dimmer until their 150 ms fade completes. Gamma-correct compositing makes that partial-ramp difference especially obvious.
Conclusion
This explains a temporary brightness gradient during the upward/downward sweep:
That behavior is consistent with the supplied 16.0.x video and would not appear equivalently on 15.4 because the old direct-rendering pipeline did not apply the same per-segment opacity composition to Solid.
Recommended verification / mitigation
0(or otherwise bypass transitions) as a diagnostic. If the brightness differences disappear, this confirms the transition-compositing path.segment_delay_msas only the step timing.The gamma redesign is relevant primarily because it changes the visual shape of partial fades; it should not leave otherwise identical, fully settled, non-overlapping Solid segments at different brightness.
softhack007 commentedon Jul 21, 2026
@DedeHai It looks like the usermod changes the segment "on" state directly. Could the problem be related to the known limitation that segment on/off does not use transitions/fading in 16.0?
WLED/usermods/Animated_Staircase/Animated_Staircase.cpp
Lines 308 to 311 in 0589031
WLED/usermods/Animated_Staircase/Animated_Staircase.cpp
Lines 114 to 122 in 0589031
WLED/usermods/Animated_Staircase/Animated_Staircase.cpp
Lines 264 to 267 in 0589031
@coderabbitai did 0.15.x use cross-fading when segments were toggled on/off ?
coderabbitai commentedon Jul 21, 2026
coderabbitai commentedon Jul 21, 2026
🧩 Analysis chain
🏁 Script executed:
Length of output: 20138
🏁 Script executed:
Length of output: 26955
@softhack007, yes — in0_15_x, toggling a segment’sonoption was designed to cross-fade, provided that fade transitions were enabled and the configured transition duration was non-zero.The relevant 0.15.x path is:
During that transition,
Segment::currentBri()interpolates from the saved old brightness to the new effective brightness:So an on-toggle fades from
0 → opacity, and an off-toggle fromopacity → 0. In other words, the Animated Staircase usermod’s directSEG_OPTION_ONupdates could produce the expected per-segment fade on 0.15.x.This makes
#5520/#5524highly relevant to the reported regression. WLED 16 retains calls tostartTransition()inSegment::setOption(), but the 16.0.x transition/compositing lifecycle has a known defect: its global transition handling can stop per-segment transitions prematurely or otherwise fail to render non-Fade transition styles correctly.#5520’s reports match that: segment toggles snap immediately in 16.0.x, while Fade may be the exception. PR#5524is explicitly titled “make per-segment on/off and brightness behave the same as global.”So I would revise the earlier conclusion:
#5524patch is the most targeted verification.coderabbitai commentedon Jul 21, 2026
coderabbitai commentedon Jul 21, 2026
softhack007 commentedon Jul 21, 2026
@coderabbitai is
transitionDelaythe correct global, or should it betransitionDelayDefault?WLED/usermods/Animated_Staircase/Animated_Staircase.cpp
Lines 308 to 311 in 0589031
coderabbitai commentedon Jul 21, 2026
🧩 Analysis chain
🏁 Script executed:
Length of output: 18048
@softhack007,transitionDelayDefaultis not the right one here. It is the persisted configuration default (cfg.json) and is restored during startup:For the currently active global transition setting,
transitionDelayis the corresponding global:However, for
Animated_Staircase, neither global alone controls the immediate segment-toggle transition:Segment::setOption()ultimately uses the duration held bystrip, so this is the operative call:Thus, the present
transitionDelayassignment is semantically preferable totransitionDelayDefault, but it is redundant for the immediate effect becausestrip.setTransition()follows it.The more important issue is that the usermod currently does not restore the previous active transition duration when disabled. It therefore permanently changes the running transition duration to
segment_delay_msfor the rest of the session (andtransitionDelaymay subsequently be serialized as current state).A safer approach is to save
strip.getTransition()when enabling, set only the temporary strip transition for the staircase, and restore the saved value when disabling.transitionDelayDefaultshould remain untouched.[-]version 16.0.0 and 16.0.1 Animated Staircase bug[/-][+]Animated Staircase: segments not fading out but switched on/off instantly in version 16.0.0 and 16.0.1 [/+]DedeHai commentedon Jul 24, 2026
#5729 may fix it once I am done with it, I have more changes I still need to test before committing but got pulled away from that by the V5 merge
MACCAMCGOO commentedon Aug 19, 2026
Just to add something to this issue... which may or may not be relevant, but I have observed when I try to apply Swipe left or right to a 16.0.1 set up with multiple segments it does not work, but yesterday I threw together a very simple set up for a light behind my PC with a single segment and the swipes all worked.