Individual LED control via JSON (closes #226 )

This commit is contained in:
cschwinne 2020-08-29 22:26:39 +02:00
parent ac9a567e1f
commit 36e0a1eb23
6 changed files with 85 additions and 7 deletions

View File

@ -2,11 +2,17 @@
### Development versions after 0.10.0 release ### Development versions after 0.10.0 release
#### Build 2008290
- Added individual LED control support to JSON API
- Added internal Segment Freeze/Pause option
#### Build 2008250 #### Build 2008250
- Made `platformio_override.ini` example easier to use by including the `default_envs` property - Made `platformio_override.ini` example easier to use by including the `default_envs` property
- FastLED uses `now` as timer, so effects using e.g. `beatsin88()` will sync correctly - FastLED uses `now` as timer, so effects using e.g. `beatsin88()` will sync correctly
- Extended the speed range of Pacifica effect - Extended the speed range of Pacifica effect
- Improved TPM2.net receiving (#1100)
- Fixed exception on empty MQTT payload (#1101) - Fixed exception on empty MQTT payload (#1101)
#### Build 2008200 #### Build 2008200

View File

@ -434,6 +434,7 @@ class WS2812FX {
init(bool supportWhite, uint16_t countPixels, bool skipFirst), init(bool supportWhite, uint16_t countPixels, bool skipFirst),
service(void), service(void),
blur(uint8_t), blur(uint8_t),
fill(uint32_t),
fade_out(uint8_t r), fade_out(uint8_t r),
setMode(uint8_t segid, uint8_t m), setMode(uint8_t segid, uint8_t m),
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
@ -448,7 +449,8 @@ class WS2812FX {
setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void), show(void),
setRgbwPwm(void); setRgbwPwm(void),
setPixelSegment(uint8_t n);
bool bool
reverseMode = false, //is the entire LED strip reversed? reverseMode = false, //is the entire LED strip reversed?
@ -632,7 +634,6 @@ class WS2812FX {
void load_gradient_palette(uint8_t); void load_gradient_palette(uint8_t);
void handle_palette(void); void handle_palette(void);
void fill(uint32_t);
bool bool
_useRgbw = false, _useRgbw = false,

View File

@ -81,13 +81,18 @@ void WS2812FX::service() {
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
{ {
if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check
_virtualSegmentLength = SEGMENT.virtualLength();
doShow = true; doShow = true;
uint16_t delay = FRAMETIME;
if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
_virtualSegmentLength = SEGMENT.virtualLength();
handle_palette(); handle_palette();
uint16_t delay = (this->*_mode[SEGMENT.mode])(); delay = (this->*_mode[SEGMENT.mode])(); //effect function
SEGENV.next_time = nowUp + delay;
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++; if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
} }
SEGENV.next_time = nowUp + delay;
}
} }
} }
_virtualSegmentLength = 0; _virtualSegmentLength = 0;
@ -386,6 +391,12 @@ void WS2812FX::setBrightness(uint8_t b) {
if (_brightness == b) return; if (_brightness == b) return;
_brightness = (gammaCorrectBri) ? gamma8(b) : b; _brightness = (gammaCorrectBri) ? gamma8(b) : b;
_segment_index = 0; _segment_index = 0;
if (b == 0) { //unfreeze all segments on power off
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
_segments[i].setOption(SEG_OPTION_FREEZE, false);
}
}
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
} }
@ -535,6 +546,18 @@ void WS2812FX::resetSegments() {
_segment_runtimes[0].reset(); _segment_runtimes[0].reset();
} }
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
void WS2812FX::setPixelSegment(uint8_t n)
{
if (n < MAX_NUM_SEGMENTS) {
_segment_index = n;
_virtualSegmentLength = SEGMENT.length();
} else {
_segment_index = 0;
_virtualSegmentLength = 0;
}
}
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
{ {
if (i2 >= i) if (i2 >= i)

View File

@ -101,6 +101,7 @@
#define SEG_OPTION_ON 2 #define SEG_OPTION_ON 2
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment #define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor #define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
#define SEG_OPTION_TRANSITIONAL 7 #define SEG_OPTION_TRANSITIONAL 7
//Timer mode types //Timer mode types

View File

@ -74,6 +74,53 @@ void deserializeSegment(JsonObject elem, byte it)
seg.intensity = elem["ix"] | seg.intensity; seg.intensity = elem["ix"] | seg.intensity;
seg.palette = elem["pal"] | seg.palette; seg.palette = elem["pal"] | seg.palette;
} }
JsonArray iarr = elem["i"]; //set individual LEDs
if (!iarr.isNull()) {
strip.setPixelSegment(id);
//freeze and init to black
if (!seg.getOption(SEG_OPTION_FREEZE)) {
seg.setOption(SEG_OPTION_FREEZE, true);
strip.fill(0);
}
uint16_t start = 0, stop = 0;
byte set = 0; //0 nothing set, 1 start set, 2 range set
for (uint16_t i = 0; i < iarr.size(); i++) {
if(iarr[i].is<JsonInteger>()) {
if (!set) {
start = iarr[i];
set = 1;
} else {
stop = iarr[i];
set = 2;
}
} else {
JsonArray icol = iarr[i];
if (icol.isNull()) break;
byte sz = icol.size();
if (sz == 0 && sz > 4) break;
int rgbw[] = {0,0,0,0};
byte cp = copyArray(icol, rgbw);
if (set < 2) stop = start + 1;
for (uint16_t i = start; i < stop; i++) {
strip.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
}
if (!set) start++;
set = 0;
}
}
strip.setPixelSegment(255);
strip.trigger();
} else { //return to regular effect
seg.setOption(SEG_OPTION_FREEZE, false);
}
} }
} }

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2008250 #define VERSION 2008290
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS). // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).