From a02c0d70fed359c56622dd12cb325f09a37549ce Mon Sep 17 00:00:00 2001 From: Keith Lord Date: Fri, 19 Nov 2021 08:19:52 -0500 Subject: [PATCH] Added built-in rain effect and bug fixes. See change log. (#301) * Minor updates * Fixed bug that prevented the last LED from updaing on some effects. * added rain effect and updated library.json file --- .../esp8266_webinterface.ino | 15 +-- examples/ws2812fx_esp32/ESP32_RMT_Driver.h | 71 -------------- examples/ws2812fx_esp32/ws2812fx_esp32.ino | 93 ------------------- .../ws2812fx_limit_current.ino | 2 +- examples/ws2812fx_matrix/ws2812fx_matrix.ino | 2 +- examples/ws2812fx_msgeq7/ws2812fx_msgeq7.ino | 6 +- .../ws2812fx_overlay/ws2812fx_overlay.ino | 2 +- .../ws2812fx_patterns_web.ino | 16 ++-- .../ws2812fx_segments_web.ino | 4 +- .../ws2812fx_soundfx/ws2812fx_soundfx.ino | 14 +-- extras/WS2812FX Users Guide.md | 28 +++--- extras/WS2812FX change log.txt | 28 ++++++ keywords.txt | 10 +- library.json | 6 +- library.properties | 2 +- src/WS2812FX.cpp | 81 +++++++--------- src/WS2812FX.h | 75 ++++++++------- src/custom/Rain.h | 6 ++ src/custom/RainbowLarson.h | 2 +- src/custom/TriFade.h | 2 +- 20 files changed, 162 insertions(+), 303 deletions(-) delete mode 100644 examples/ws2812fx_esp32/ESP32_RMT_Driver.h delete mode 100644 examples/ws2812fx_esp32/ws2812fx_esp32.ino diff --git a/examples/esp8266_webinterface/esp8266_webinterface.ino b/examples/esp8266_webinterface/esp8266_webinterface.ino index b461f36..9a3c384 100644 --- a/examples/esp8266_webinterface/esp8266_webinterface.ino +++ b/examples/esp8266_webinterface/esp8266_webinterface.ino @@ -76,11 +76,6 @@ extern const char main_js[]; #define WIFI_TIMEOUT 30000 // checks WiFi every ...ms. Reset after this time, if WiFi cannot reconnect. #define HTTP_PORT 80 -#define DEFAULT_COLOR 0xFF5900 -#define DEFAULT_BRIGHTNESS 128 -#define DEFAULT_SPEED 1000 -#define DEFAULT_MODE FX_MODE_STATIC - unsigned long auto_last_change = 0; unsigned long last_wifi_check_time = 0; String modes = ""; @@ -100,10 +95,10 @@ void setup(){ Serial.println("WS2812FX setup"); ws2812fx.init(); - ws2812fx.setMode(DEFAULT_MODE); - ws2812fx.setColor(DEFAULT_COLOR); - ws2812fx.setSpeed(DEFAULT_SPEED); - ws2812fx.setBrightness(DEFAULT_BRIGHTNESS); + ws2812fx.setMode(FX_MODE_STATIC); + ws2812fx.setColor(0xFF5900); + ws2812fx.setSpeed(1000); + ws2812fx.setBrightness(128); ws2812fx.start(); Serial.println("Wifi setup"); @@ -231,7 +226,7 @@ void srv_handle_set() { for (uint8_t i=0; i < server.args(); i++){ if(server.argName(i) == "c") { uint32_t tmp = (uint32_t) strtol(server.arg(i).c_str(), NULL, 10); - if(tmp >= 0x000000 && tmp <= 0xFFFFFF) { + if(tmp <= 0xFFFFFF) { ws2812fx.setColor(tmp); } } diff --git a/examples/ws2812fx_esp32/ESP32_RMT_Driver.h b/examples/ws2812fx_esp32/ESP32_RMT_Driver.h deleted file mode 100644 index a401be1..0000000 --- a/examples/ws2812fx_esp32/ESP32_RMT_Driver.h +++ /dev/null @@ -1,71 +0,0 @@ -#include "driver/rmt.h" - -#define APB_CLK_MHZ 80 // default RMT CLK source (80MHz) -#define RMT_CLK_DIV 2 // RMT CLK divider -#define RMT_TICK (RMT_CLK_DIV * 1000 / APB_CLK_MHZ) // 25ns - -// timing parameters for WS2812B LEDs. you may need to -// tweek these if you're using a different kind of LED -#define T1_TICKS 250 / RMT_TICK // 250ns -#define T2_TICKS 625 / RMT_TICK // 625ns -#define T3_TICKS 375 / RMT_TICK // 375ns -#define RESET_TICKS 50000 / RMT_TICK // 50us - -/* - * Convert uint8_t type of data to rmt format data. - */ -static void IRAM_ATTR u8_to_rmt(const void* src, rmt_item32_t* dest, size_t src_size, - size_t wanted_num, size_t* translated_size, size_t* item_num) { - if(src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ T1_TICKS, 1, T2_TICKS + T3_TICKS, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ T1_TICKS + T2_TICKS, 1, T3_TICKS , 0 }}}; //Logical 1 - const rmt_item32_t reset = {{{ RESET_TICKS/2 , 0, RESET_TICKS/2 , 0 }}}; //Reset - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t* pdest = dest; - while (size < src_size && num < wanted_num) { - if(size < src_size - 1) { // have more pixel data, so translate into RMT items - (pdest++)->val = (*psrc & B10000000) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B01000000) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00100000) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00010000) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00001000) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00000100) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00000010) ? bit1.val : bit0.val; - (pdest++)->val = (*psrc & B00000001) ? bit1.val : bit0.val; - num += 8; - } else { // no more pixel data, last RMT item is the reset pulse - (pdest++)->val = reset.val; - num++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -/* - * Initialize the RMT Tx channel - */ -static void rmt_tx_int(rmt_channel_t channel, uint8_t gpio) { - rmt_config_t config; - config.rmt_mode = RMT_MODE_TX; - config.channel = channel; - config.gpio_num = gpio_num_t(gpio); - config.clk_div = RMT_CLK_DIV; - config.mem_block_num = 1; // 64 pulse "items" per block - config.tx_config.loop_en = 0; - config.tx_config.carrier_en = 0; - config.tx_config.idle_output_en = 1; - config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - rmt_translator_init(config.channel, u8_to_rmt); -} diff --git a/examples/ws2812fx_esp32/ws2812fx_esp32.ino b/examples/ws2812fx_esp32/ws2812fx_esp32.ino deleted file mode 100644 index 9e597c1..0000000 --- a/examples/ws2812fx_esp32/ws2812fx_esp32.ino +++ /dev/null @@ -1,93 +0,0 @@ -/* - WS2812FX ESP32 demo - - Keith Lord - 2019 - - FEATURES - * demonstrates driving ws2812b leds using the ESP32's RMT hardware - - - LICENSE - - The MIT License (MIT) - - Copyright (c) 2019 Keith Lord - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - - CHANGELOG - 2019-03-13 initial version - -*/ - -#include -#include "ESP32_RMT_Driver.h" - -// The ESP32's RMT hardware supports up to 8 channels, so it -// can drive up to 8 independent WS2812FX instances. We'll use 2. -WS2812FX ws2812fx1 = WS2812FX(144, 12, NEO_GRB + NEO_KHZ800); // 144 RGB LEDs driven by GPIO_12 -WS2812FX ws2812fx2 = WS2812FX( 60, 13, NEO_GRBW + NEO_KHZ800); // 60 RGBW LEDs driven by GPIO_13 - -void setup() { - Serial.begin(115200); - delay(500); - - ws2812fx1.init(); // initialize the ws2812fx instances - ws2812fx2.init(); - - ws2812fx1.setBrightness(64); // set the overall LED brightnesses - ws2812fx2.setBrightness(32); - - rmt_tx_int(RMT_CHANNEL_0, ws2812fx1.getPin()); // assign ws2812fx1 to RMT channel 0 - rmt_tx_int(RMT_CHANNEL_1, ws2812fx2.getPin()); // assign ws2812fx2 to RMT channel 1 - - ws2812fx1.setCustomShow(myCustomShow1); // set the custom show function to forgo the NeoPixel - ws2812fx2.setCustomShow(myCustomShow2); // bit-bang method and instead use the RMT hardware - - // parameters: seg_index, start, stop, mode, color, speed, options - ws2812fx1.setSegment(0, 0, 144-1, FX_MODE_COMET, GREEN, 1000, NO_OPTIONS); // setup each ws2812fx's effect - ws2812fx2.setSegment(0, 0, 60-1, FX_MODE_COMET, BLUE, 1000, NO_OPTIONS); - - ws2812fx1.start(); // start'em up - ws2812fx2.start(); -} - -void loop() { - ws2812fx1.service(); // service each ws2812fx instance - ws2812fx2.service(); -} - -// Custom show functions which will use the RMT hardware to drive the LEDs. -// Need a separate function for each ws2812fx instance. -void myCustomShow1(void) { - uint8_t *pixels = ws2812fx1.getPixels(); - // numBytes is one more then the size of the ws2812fx's *pixels array. - // the extra byte is used by the driver to insert the LED reset pulse at the end. - uint16_t numBytes = ws2812fx1.getNumBytes() + 1; - rmt_write_sample(RMT_CHANNEL_0, pixels, numBytes, false); // channel 0 -} - -void myCustomShow2(void) { - uint8_t *pixels = ws2812fx2.getPixels(); - // numBytes is one more then the size of the *pixels array. - // the extra byte is used by the driver to insert the LED reset pulse at the end. - uint16_t numBytes = ws2812fx2.getNumBytes() + 1; - rmt_write_sample(RMT_CHANNEL_1, pixels, numBytes, false); // channel 1 -} diff --git a/examples/ws2812fx_limit_current/ws2812fx_limit_current.ino b/examples/ws2812fx_limit_current/ws2812fx_limit_current.ino index f10a134..b045317 100644 --- a/examples/ws2812fx_limit_current/ws2812fx_limit_current.ino +++ b/examples/ws2812fx_limit_current/ws2812fx_limit_current.ino @@ -173,7 +173,7 @@ void recvChar(void) { #define MAX_CURRENT 500 // maximum allowed current draw for the entire strip (mA) #define QUIESCENT_CURRENT 56 // current draw for the entire strip with all LEDs off (mA) #define INCREMENTAL_CURRENT 40 // increase in current for each intensity step per RGB color (uA) -#define MAX_INTENSITY_SUM ((MAX_CURRENT - QUIESCENT_CURRENT) * 1000) / INCREMENTAL_CURRENT +#define MAX_INTENSITY_SUM ((MAX_CURRENT - QUIESCENT_CURRENT) * (uint32_t)1000) / INCREMENTAL_CURRENT void myCustomShow(void) { static uint32_t lastSum = 0; uint32_t intensitySum = ws2812fx.intensitySum(); // get intensity sum for all LEDs diff --git a/examples/ws2812fx_matrix/ws2812fx_matrix.ino b/examples/ws2812fx_matrix/ws2812fx_matrix.ino index f8f5fb3..4a0509e 100644 --- a/examples/ws2812fx_matrix/ws2812fx_matrix.ino +++ b/examples/ws2812fx_matrix/ws2812fx_matrix.ino @@ -8,7 +8,7 @@ #define PSTR // Make Arduino Due happy #endif -#define PIN D5 +#define PIN 4 // MATRIX DECLARATION: // Parameter 1 = width of NeoPixel matrix diff --git a/examples/ws2812fx_msgeq7/ws2812fx_msgeq7.ino b/examples/ws2812fx_msgeq7/ws2812fx_msgeq7.ino index d0298ed..335491e 100644 --- a/examples/ws2812fx_msgeq7/ws2812fx_msgeq7.ino +++ b/examples/ws2812fx_msgeq7/ws2812fx_msgeq7.ino @@ -35,7 +35,7 @@ #include #define LED_COUNT 140 -#define LED_PIN D1 +#define LED_PIN 4 // include and config the VUMeter custom effect #define NUM_BANDS 7 @@ -43,8 +43,8 @@ #include "custom/VUMeter.h" // MSGEQ7 pin assignments -#define STROBE D5 -#define RESET D6 +#define STROBE 5 +#define RESET 6 #define OUT A0 #define MSGEQ7_DELAY 50 diff --git a/examples/ws2812fx_overlay/ws2812fx_overlay.ino b/examples/ws2812fx_overlay/ws2812fx_overlay.ino index 3f21356..cf280e9 100644 --- a/examples/ws2812fx_overlay/ws2812fx_overlay.ino +++ b/examples/ws2812fx_overlay/ws2812fx_overlay.ino @@ -83,7 +83,7 @@ void myCustomShow(void) { // blend the pixel data from the virtual strips and save it // to the physical strip - for (int i=0; i < ws2812fx_p.getNumBytes(); i++) { + for (uint16_t i=0; i < ws2812fx_p.getNumBytes(); i++) { pixels_p[i] = (pixels_v1[i] / 2) + (pixels_v2[i] / 2); } diff --git a/examples/ws2812fx_patterns_web/ws2812fx_patterns_web.ino b/examples/ws2812fx_patterns_web/ws2812fx_patterns_web.ino index 923817a..013b107 100644 --- a/examples/ws2812fx_patterns_web/ws2812fx_patterns_web.ino +++ b/examples/ws2812fx_patterns_web/ws2812fx_patterns_web.ino @@ -54,7 +54,7 @@ uint16_t numLeds = 30; // default number of LEDs on the strip #define MAX_NUM_PATTERNS 8 // duration, brightness, numSegments, [ { first, last, speed, mode, options, colors[] } ] -#define DEFAULT_PATTERN {30, 64, 1, { {0, numLeds-1, numLeds*20, FX_MODE_STATIC, NO_OPTIONS, {RED, BLACK, BLACK}} }} +#define DEFAULT_PATTERN {30, 64, 1, { {0, (uint16_t)(numLeds-1), (uint16_t)(numLeds*20), FX_MODE_STATIC, NO_OPTIONS, {RED, BLACK, BLACK}} }} typedef struct Pattern { // 208 bytes/pattern int duration; @@ -143,7 +143,7 @@ void loop() { // if it's time to change pattern, do it now unsigned long now = millis(); - if (lastTime == 0 || (now - lastTime > patterns[currentPattern].duration * 1000)) { + if (lastTime == 0 || (now - lastTime > patterns[currentPattern].duration * 1000ul)) { ws2812fx.clear(); ws2812fx.resetSegments(); @@ -176,7 +176,7 @@ void configServer() { String auxFunc = server.arg("auxFunc"); if (auxFunc.length() > 0) { int auxFuncIndex = auxFunc.toInt(); - if (auxFuncIndex >= 0 && auxFuncIndex < sizeof(customAuxFunc) / sizeof(customAuxFunc[0])) { + if (auxFuncIndex >= 0 && (size_t)auxFuncIndex < sizeof(customAuxFunc) / sizeof(customAuxFunc[0])) { customAuxFunc[auxFuncIndex](); } } @@ -371,7 +371,7 @@ bool json2patterns(String &json) { JsonArray patternsJson = deviceJson["patterns"]; if (patternsJson.size() > 0 ) { numPatterns = 0; - for (int i = 0; i < patternsJson.size(); i++) { + for (size_t i = 0; i < patternsJson.size(); i++) { JsonObject patt = patternsJson[i]; // bool isEnabled = patt["isEnabled"]; // if (! isEnabled) continue; // disabled patterns are not stored @@ -383,7 +383,7 @@ bool json2patterns(String &json) { patterns[numPatterns].duration = patt["duration"]; patterns[numPatterns].numSegments = segmentsJson.size(); - for (int j = 0; j < segmentsJson.size(); j++) { + for (size_t j = 0; j < segmentsJson.size(); j++) { JsonObject seg = segmentsJson[j]; //seg.printTo(Serial);Serial.println(); @@ -420,9 +420,9 @@ bool json2patterns(String &json) { JsonArray colors = seg["colors"]; // the web interface sends three color values // convert colors from strings ('#ffffff') to uint32_t - patterns[numPatterns].segments[j].colors[0] = strtoul(colors[0].as() + 1, 0, 16); - patterns[numPatterns].segments[j].colors[1] = strtoul(colors[1].as() + 1, 0, 16); - patterns[numPatterns].segments[j].colors[2] = strtoul(colors[2].as() + 1, 0, 16); + patterns[numPatterns].segments[j].colors[0] = strtoul(colors[0].as() + 1, 0, 16); + patterns[numPatterns].segments[j].colors[1] = strtoul(colors[1].as() + 1, 0, 16); + patterns[numPatterns].segments[j].colors[2] = strtoul(colors[2].as() + 1, 0, 16); } numPatterns++; if (numPatterns >= MAX_NUM_PATTERNS) break; diff --git a/examples/ws2812fx_segments_web/ws2812fx_segments_web.ino b/examples/ws2812fx_segments_web/ws2812fx_segments_web.ino index 3e648b2..c109d63 100644 --- a/examples/ws2812fx_segments_web/ws2812fx_segments_web.ino +++ b/examples/ws2812fx_segments_web/ws2812fx_segments_web.ino @@ -72,7 +72,7 @@ WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); AsyncWebServer server(80); -typedef struct Preset { +struct Preset { int pin = LED_PIN; int numPixels = LED_COUNT; int brightness = 64; @@ -203,7 +203,7 @@ void initWebAPI() { JsonArray segments = jsonObj["segments"]; preset.numSegments = segments.size(); - for (int i = 0; i < segments.size(); i++) { + for (size_t i = 0; i < segments.size(); i++) { JsonObject seg = segments[i]; preset.segments[i].start = seg["start"]; diff --git a/examples/ws2812fx_soundfx/ws2812fx_soundfx.ino b/examples/ws2812fx_soundfx/ws2812fx_soundfx.ino index feb2248..d6a3341 100644 --- a/examples/ws2812fx_soundfx/ws2812fx_soundfx.ino +++ b/examples/ws2812fx_soundfx/ws2812fx_soundfx.ino @@ -5,10 +5,10 @@ FEATURES * example of running an LED animation with sound effects. - * The WAV audio files are stored in the ESP's SPIFFS + * The WAV audio files are stored in the ESP8266's LittleFS * filesystem and need to be uploaded to the ESP before * uploading the sketch, as described here: - * https://arduino-esp8266.readthedocs.io/en/stable/filesystem.html#file-system-object-spiffs + * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#uploading-files-to-file-system * * We're using the fantastic ESP8266Audio library available here: * https://github.com/earlephilhower/ESP8266Audio. @@ -67,7 +67,7 @@ */ #include -#include "AudioFileSourceSPIFFS.h" +#include "AudioFileSourceLittleFS.h" #include "AudioGeneratorWAV.h" #include "AudioOutputI2S.h" @@ -77,15 +77,15 @@ WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); AudioGeneratorWAV *wav = NULL; -AudioFileSourceSPIFFS *file = NULL; +AudioFileSourceLittleFS *file = NULL; AudioOutputI2S *out = NULL; -char* soundfx = "/pew.wav"; +const char* soundfx = "/pew.wav"; void setup() { Serial.begin(115200); - SPIFFS.begin(); // init SPIFFS file system where the audio samples are stored + LittleFS.begin(); // init LittleFS file system where the audio samples are stored ws2812fx.init(); ws2812fx.setBrightness(255); @@ -115,7 +115,7 @@ void playSound() { if(out != NULL) delete out; if(wav != NULL) delete wav; - file = new AudioFileSourceSPIFFS(soundfx); + file = new AudioFileSourceLittleFS(soundfx); out = new AudioOutputI2S(); wav = new AudioGeneratorWAV(); diff --git a/extras/WS2812FX Users Guide.md b/extras/WS2812FX Users Guide.md index 23b8e6b..37c2ec1 100644 --- a/extras/WS2812FX Users Guide.md +++ b/extras/WS2812FX Users Guide.md @@ -412,20 +412,20 @@ correction, fade rate and size. The options are spelled out in the ws2812fx.h file. ```c++ -#define NO_OPTIONS (uint8_t)B00000000 -#define REVERSE (uint8_t)B10000000 -#define FADE_XFAST (uint8_t)B00010000 -#define FADE_FAST (uint8_t)B00100000 -#define FADE_MEDIUM (uint8_t)B00110000 -#define FADE_SLOW (uint8_t)B01000000 -#define FADE_XSLOW (uint8_t)B01010000 -#define FADE_XXSLOW (uint8_t)B01100000 -#define FADE_GLACIAL (uint8_t)B01110000 -#define GAMMA (uint8_t)B00001000 -#define SIZE_SMALL (uint8_t)B00000000 -#define SIZE_MEDIUM (uint8_t)B00000010 -#define SIZE_LARGE (uint8_t)B00000100 -#define SIZE_XLARGE (uint8_t)B00000110 +#define NO_OPTIONS (uint8_t)0b00000000 +#define REVERSE (uint8_t)0b10000000 +#define FADE_XFAST (uint8_t)0b00010000 +#define FADE_FAST (uint8_t)0b00100000 +#define FADE_MEDIUM (uint8_t)0b00110000 +#define FADE_SLOW (uint8_t)0b01000000 +#define FADE_XSLOW (uint8_t)0b01010000 +#define FADE_XXSLOW (uint8_t)0b01100000 +#define FADE_GLACIAL (uint8_t)0b01110000 +#define GAMMA (uint8_t)0b00001000 +#define SIZE_SMALL (uint8_t)0b00000000 +#define SIZE_MEDIUM (uint8_t)0b00000010 +#define SIZE_LARGE (uint8_t)0b00000100 +#define SIZE_XLARGE (uint8_t)0b00000110 ``` Options can be combined. If you wanted to create a segment with both reverse diff --git a/extras/WS2812FX change log.txt b/extras/WS2812FX change log.txt index 1d4041c..bb766aa 100644 --- a/extras/WS2812FX change log.txt +++ b/extras/WS2812FX change log.txt @@ -1,6 +1,34 @@ WS2182FX Change Log +v1.3.5 changes 11/18/2021 +------------------------ + +1) When specifying a binary number, changed from "Bxxxx" notation + to "0bxxxx" notation. Apparently this is the preferred notation, + since the old notation threw compiler warnings. See issue #292. + +2) Minor tweaks to some example sketches to remove compiler warnings. + +3) Updated ws2812fx_soundfx example sketch to use LittleFS file + system instead of SPIFFS. + +4) Updated the keywords.txt file. + +5) Removed the ws2812fx_esp32 example sketch since the + Adafruit_Neopixel lib (v1.7.0) implemented an ESP32 RMT driver + and we can just use that. + +6) Fixed a bug in some of the effects that caused the last LED in + a segment to always be off. See issue #299. Thanks @DanielWeigl + for catching that. + +7) moved the rain effect from a custon effect to a built-in effect. + +8) Added "headers": "WS2812FX.h" to the library.json file as + suggested by @ivankravets in PR #300. + + v1.3.4 changes 8/21/2021 ------------------------ diff --git a/keywords.txt b/keywords.txt index b272916..731c7f6 100644 --- a/keywords.txt +++ b/keywords.txt @@ -97,6 +97,9 @@ getSegmentRuntime KEYWORD2 getSegmentRuntimes KEYWORD2 color_wheel KEYWORD2 get_random_wheel_index KEYWORD2 +blend KEYWORD2 +color_blend KEYWORD2 +startTransition KEYWORD2 FX_MODE_STATIC KEYWORD2 FX_MODE_BLINK KEYWORD2 @@ -157,10 +160,15 @@ FX_MODE_DUAL_COLOR_WIPE_OUT_IN KEYWORD2 FX_MODE_CIRCUS_COMBUSTUS KEYWORD2 FX_MODE_BICOLOR_CHASE KEYWORD2 FX_MODE_TRICOLOR_CHASE KEYWORD2 -FX_MODE_ICU KEYWORD2 +FX_MODE_TWINKLEFOX KEYWORD2 +FX_MODE_RAIN KEYWORD2 FX_MODE_CUSTOM KEYWORD2 FX_MODE_CUSTOM_0 KEYWORD2 FX_MODE_CUSTOM_1 KEYWORD2 FX_MODE_CUSTOM_2 KEYWORD2 FX_MODE_CUSTOM_3 KEYWORD2 +FX_MODE_CUSTOM_4 KEYWORD2 +FX_MODE_CUSTOM_5 KEYWORD2 +FX_MODE_CUSTOM_6 KEYWORD2 +FX_MODE_CUSTOM_7 KEYWORD2 diff --git a/library.json b/library.json index 6955b76..3b52eeb 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "name": "Harm Aldick", "url": "https://github.com/kitesurfer1404/WS2812FX" }, - "version": "1.3.4", + "version": "1.3.5", "downloadUrl": "https://github.com/kitesurfer1404/WS2812FX/archive/master.zip", "export": { "include": "WS2812FX-master" @@ -23,7 +23,5 @@ "version": ">=1.1.7" } ], - "examples": [ - "examples/*/*.ino" - ] + "headers": "WS2812FX.h" } diff --git a/library.properties b/library.properties index ad1665d..8709c1c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=WS2812FX -version=1.3.4 +version=1.3.5 author=Harm Aldick maintainer=Harm Aldick sentence=WS2812 FX Library for Arduino and ESP microprocessors. diff --git a/src/WS2812FX.cpp b/src/WS2812FX.cpp index 606f558..3135854 100644 --- a/src/WS2812FX.cpp +++ b/src/WS2812FX.cpp @@ -211,19 +211,19 @@ void WS2812FX::setColors(uint8_t seg, uint32_t* c) { } void WS2812FX::setBrightness(uint8_t b) { - b = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); +//b = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); Adafruit_NeoPixel::setBrightness(b); show(); } void WS2812FX::increaseBrightness(uint8_t s) { - s = constrain(getBrightness() + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - setBrightness(s); +//s = constrain(getBrightness() + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); + setBrightness(getBrightness() + s); } void WS2812FX::decreaseBrightness(uint8_t s) { - s = constrain(getBrightness() - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - setBrightness(s); +//s = constrain(getBrightness() - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); + setBrightness(getBrightness() - s); } void WS2812FX::setLength(uint16_t b) { @@ -486,7 +486,7 @@ void WS2812FX::swapActiveSegment(uint8_t oldSeg, uint8_t newSeg) { // reset all runtime parameters EXCEPT next_time, // allowing the current animation frame to complete - segment_runtime seg_rt = _segment_runtimes[i]; + __attribute__ ((unused)) segment_runtime seg_rt = _segment_runtimes[i]; seg_rt.counter_mode_step = 0; seg_rt.counter_mode_call = 0; seg_rt.aux_param = 0; @@ -1135,7 +1135,7 @@ uint16_t WS2812FX::twinkle_fade(uint32_t color) { if(random8(3) == 0) { uint8_t size = 1 << SIZE_OPTION; - uint16_t index = _seg->start + random16(_seg_len - size); + uint16_t index = _seg->start + random16(_seg_len - size + 1); fill(color, index, size); SET_CYCLE; } @@ -1171,7 +1171,7 @@ uint16_t WS2812FX::sparkle(uint32_t color1, uint32_t color2) { uint8_t size = 1 << SIZE_OPTION; fill(color1, _seg->start + _seg_rt->aux_param3, size); - _seg_rt->aux_param3 = random16(_seg_len - size); // aux_param3 stores the random led index + _seg_rt->aux_param3 = random16(_seg_len - size + 1); // aux_param3 stores the random led index fill(color2, _seg->start + _seg_rt->aux_param3, size); SET_CYCLE; @@ -1206,7 +1206,7 @@ uint16_t WS2812FX::mode_hyper_sparkle(void) { uint8_t size = 1 << SIZE_OPTION; for(uint8_t i=0; i<8; i++) { - fill(WHITE, _seg->start + random16(_seg_len - size), size); + fill(WHITE, _seg->start + random16(_seg_len - size + 1), size); } SET_CYCLE; @@ -1532,14 +1532,14 @@ uint16_t WS2812FX::fireworks(uint32_t color) { if(!_triggered) { for(uint16_t i=0; istart + random16(_seg_len - size); + uint16_t index = _seg->start + random16(_seg_len - size + 1); fill(color, index, size); SET_CYCLE; } } } else { for(uint16_t i=0; istart + random16(_seg_len - size); + uint16_t index = _seg->start + random16(_seg_len - size + 1); fill(color, index, size); SET_CYCLE; } @@ -1606,44 +1606,6 @@ uint16_t WS2812FX::mode_fire_flicker_intense(void) { return fire_flicker(1); } - -/* - * ICU mode (moved to the custom effect folder) - */ -// uint16_t WS2812FX::mode_icu(void) { -// uint16_t dest = _seg_rt->counter_mode_step & 0xFFFF; - -// setPixelColor(_seg->start + dest, _seg->colors[0]); -// setPixelColor(_seg->start + dest + _seg_len/2, _seg->colors[0]); - -// if(_seg_rt->aux_param3 == dest) { // pause between eye movements -// if(random8(6) == 0) { // blink once in a while -// setPixelColor(_seg->start + dest, BLACK); -// setPixelColor(_seg->start + dest + _seg_len/2, BLACK); -// return 200; -// } -// _seg_rt->aux_param3 = random16(_seg_len/2); -// SET_CYCLE; -// return 1000 + random16(2000); -// } - -// setPixelColor(_seg->start + dest, BLACK); -// setPixelColor(_seg->start + dest + _seg_len/2, BLACK); - -// if(_seg_rt->aux_param3 > _seg_rt->counter_mode_step) { -// _seg_rt->counter_mode_step++; -// dest++; -// } else if (_seg_rt->aux_param3 < _seg_rt->counter_mode_step) { -// _seg_rt->counter_mode_step--; -// dest--; -// } - -// setPixelColor(_seg->start + dest, _seg->colors[0]); -// setPixelColor(_seg->start + dest + _seg_len/2, _seg->colors[0]); - -// return (_seg->speed / _seg_len); -// } - // An adaptation of Mark Kriegsman's FastLED twinkeFOX effect // https://gist.github.com/kriegsman/756ea6dcae8e30845b5a uint16_t WS2812FX::mode_twinkleFOX(void) { @@ -1697,6 +1659,27 @@ uint16_t WS2812FX::mode_twinkleFOX(void) { return _seg->speed / 32; } +// A combination of the Fireworks effect and the running effect +// to create an effect that looks like rain. +uint16_t WS2812FX::mode_rain(void) { + // randomly choose colors[0] or colors[2] + uint32_t rainColor = (random8() & 1) == 0 ? _seg->colors[0] : _seg->colors[2]; + // if colors[0] == colors[1], choose a random color + if(_seg->colors[0] == _seg->colors[1]) rainColor = color_wheel(random8()); + + // run the fireworks effect to create a "raindrop" + fireworks(rainColor); + + // shift everything two pixels + if(IS_REVERSE) { + copyPixels(_seg->start + 2, _seg->start, _seg_len - 2); + } else { + copyPixels(_seg->start, _seg->start + 2, _seg_len - 2); + } + + return (_seg->speed / 16); +} + /* * Custom modes */ diff --git a/src/WS2812FX.h b/src/WS2812FX.h index 7c8cf05..5bb010d 100644 --- a/src/WS2812FX.h +++ b/src/WS2812FX.h @@ -93,30 +93,30 @@ // bit 3: gamma correction // bits 1-2: size // bits 0: TBD -#define NO_OPTIONS (uint8_t)B00000000 -#define REVERSE (uint8_t)B10000000 +#define NO_OPTIONS (uint8_t)0b00000000 +#define REVERSE (uint8_t)0b10000000 #define IS_REVERSE ((_seg->options & REVERSE) == REVERSE) -#define FADE_XFAST (uint8_t)B00010000 -#define FADE_FAST (uint8_t)B00100000 -#define FADE_MEDIUM (uint8_t)B00110000 -#define FADE_SLOW (uint8_t)B01000000 -#define FADE_XSLOW (uint8_t)B01010000 -#define FADE_XXSLOW (uint8_t)B01100000 -#define FADE_GLACIAL (uint8_t)B01110000 +#define FADE_XFAST (uint8_t)0b00010000 +#define FADE_FAST (uint8_t)0b00100000 +#define FADE_MEDIUM (uint8_t)0b00110000 +#define FADE_SLOW (uint8_t)0b01000000 +#define FADE_XSLOW (uint8_t)0b01010000 +#define FADE_XXSLOW (uint8_t)0b01100000 +#define FADE_GLACIAL (uint8_t)0b01110000 #define FADE_RATE ((_seg->options >> 4) & 7) -#define GAMMA (uint8_t)B00001000 +#define GAMMA (uint8_t)0b00001000 #define IS_GAMMA ((_seg->options & GAMMA) == GAMMA) -#define SIZE_SMALL (uint8_t)B00000000 -#define SIZE_MEDIUM (uint8_t)B00000010 -#define SIZE_LARGE (uint8_t)B00000100 -#define SIZE_XLARGE (uint8_t)B00000110 +#define SIZE_SMALL (uint8_t)0b00000000 +#define SIZE_MEDIUM (uint8_t)0b00000010 +#define SIZE_LARGE (uint8_t)0b00000100 +#define SIZE_XLARGE (uint8_t)0b00000110 #define SIZE_OPTION ((_seg->options >> 1) & 3) // segment runtime options (aux_param2) -#define FRAME (uint8_t)B10000000 +#define FRAME (uint8_t)0b10000000 #define SET_FRAME (_seg_rt->aux_param2 |= FRAME) #define CLR_FRAME (_seg_rt->aux_param2 &= ~FRAME) -#define CYCLE (uint8_t)B01000000 +#define CYCLE (uint8_t)0b01000000 #define SET_CYCLE (_seg_rt->aux_param2 |= CYCLE) #define CLR_CYCLE (_seg_rt->aux_param2 &= ~CYCLE) #define CLR_FRAME_CYCLE (_seg_rt->aux_param2 &= ~(FRAME | CYCLE)) @@ -179,15 +179,16 @@ #define FX_MODE_BICOLOR_CHASE 53 #define FX_MODE_TRICOLOR_CHASE 54 #define FX_MODE_TWINKLEFOX 55 -#define FX_MODE_CUSTOM 56 // keep this for backward compatiblity -#define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end -#define FX_MODE_CUSTOM_1 57 -#define FX_MODE_CUSTOM_2 58 -#define FX_MODE_CUSTOM_3 59 -#define FX_MODE_CUSTOM_4 60 -#define FX_MODE_CUSTOM_5 61 -#define FX_MODE_CUSTOM_6 62 -#define FX_MODE_CUSTOM_7 63 +#define FX_MODE_RAIN 56 +#define FX_MODE_CUSTOM 57 // keep this for backward compatiblity +#define FX_MODE_CUSTOM_0 57 // custom modes need to go at the end +#define FX_MODE_CUSTOM_1 58 +#define FX_MODE_CUSTOM_2 59 +#define FX_MODE_CUSTOM_3 60 +#define FX_MODE_CUSTOM_4 61 +#define FX_MODE_CUSTOM_5 62 +#define FX_MODE_CUSTOM_6 63 +#define FX_MODE_CUSTOM_7 64 // create GLOBAL names to allow WS2812FX to compile with sketches and other libs // that store strings in PROGMEM (get rid of the "section type conflict with __c" @@ -248,14 +249,15 @@ const char name_52[] PROGMEM = "Halloween"; const char name_53[] PROGMEM = "Bicolor Chase"; const char name_54[] PROGMEM = "Tricolor Chase"; const char name_55[] PROGMEM = "TwinkleFOX"; -const char name_56[] PROGMEM = "Custom 0"; // custom modes need to go at the end -const char name_57[] PROGMEM = "Custom 1"; -const char name_58[] PROGMEM = "Custom 2"; -const char name_59[] PROGMEM = "Custom 3"; -const char name_60[] PROGMEM = "Custom 4"; -const char name_61[] PROGMEM = "Custom 5"; -const char name_62[] PROGMEM = "Custom 6"; -const char name_63[] PROGMEM = "Custom 7"; +const char name_56[] PROGMEM = "Rain"; +const char name_57[] PROGMEM = "Custom 0"; // custom modes need to go at the end +const char name_58[] PROGMEM = "Custom 1"; +const char name_59[] PROGMEM = "Custom 2"; +const char name_60[] PROGMEM = "Custom 3"; +const char name_61[] PROGMEM = "Custom 4"; +const char name_62[] PROGMEM = "Custom 5"; +const char name_63[] PROGMEM = "Custom 6"; +const char name_64[] PROGMEM = "Custom 7"; static const __FlashStringHelper* _names[] = { FSH(name_0), @@ -321,7 +323,8 @@ static const __FlashStringHelper* _names[] = { FSH(name_60), FSH(name_61), FSH(name_62), - FSH(name_63) + FSH(name_63), + FSH(name_64) }; class WS2812FX : public Adafruit_NeoPixel { @@ -572,6 +575,7 @@ class WS2812FX : public Adafruit_NeoPixel { mode_bicolor_chase(void), mode_tricolor_chase(void), mode_twinkleFOX(void), + mode_rain(void), mode_custom_0(void), mode_custom_1(void), mode_custom_2(void), @@ -680,7 +684,7 @@ class WS2812FXT { // define static array of member function pointers. // function pointers MUST be in the same order as the corresponding name in the _name array. -static WS2812FX::mode_ptr _modes[MODE_COUNT] = { +__attribute__ ((unused)) static WS2812FX::mode_ptr _modes[MODE_COUNT] = { &WS2812FX::mode_static, &WS2812FX::mode_blink, &WS2812FX::mode_breath, @@ -737,6 +741,7 @@ static WS2812FX::mode_ptr _modes[MODE_COUNT] = { &WS2812FX::mode_bicolor_chase, &WS2812FX::mode_tricolor_chase, &WS2812FX::mode_twinkleFOX, + &WS2812FX::mode_rain, &WS2812FX::mode_custom_0, &WS2812FX::mode_custom_1, &WS2812FX::mode_custom_2, diff --git a/src/custom/Rain.h b/src/custom/Rain.h index 45045ae..2cadc97 100644 --- a/src/custom/Rain.h +++ b/src/custom/Rain.h @@ -37,6 +37,12 @@ 2018-12-14 initial version */ +/* +Note: rain is now one of the normal, built-in WS2812FX effects, so doesn't need to be +included as a custom effect. I left it here just for historical reference. Eventually it'll +be removed from the custom folder. +*/ + #ifndef Rain_h #define Rain_h diff --git a/src/custom/RainbowLarson.h b/src/custom/RainbowLarson.h index 74777b0..081e6d8 100644 --- a/src/custom/RainbowLarson.h +++ b/src/custom/RainbowLarson.h @@ -42,7 +42,7 @@ #include -#define DIR_BIT (uint8_t)B00000001 // segrt->aux_param2 direction bit +#define DIR_BIT (uint8_t)0b00000001 // segrt->aux_param2 direction bit extern WS2812FX ws2812fx; diff --git a/src/custom/TriFade.h b/src/custom/TriFade.h index 2e1488f..edc87f6 100644 --- a/src/custom/TriFade.h +++ b/src/custom/TriFade.h @@ -35,7 +35,7 @@ #ifndef TriFade_h #define TriFade_h -#define TRIFADE_BLACK (uint8_t)B10000000 // same as REVERSE macro +#define TRIFADE_BLACK (uint8_t)0b10000000 // same as REVERSE macro #include