From 41936b85e92d8abc89086bd77eea510598df7ce7 Mon Sep 17 00:00:00 2001 From: Keith Lord Date: Mon, 15 Jun 2020 08:01:51 -0400 Subject: [PATCH] Changed _modes[] to a static array. Tweaked RUNNING_COLOR effect. (#232) * made _modes[] a static array * fixed typo * fixed the modes being out of order * updated documentation * changed RUNNING_COLOR mode to use color[1] instead of WHITE for the background color * updated change log Co-authored-by: Keith Lord --- README.md | 13 +- .../ws2812fx_virtual_strip.ino | 80 +++++++++++ extras/WS2812FX Users Guide.md | 14 ++ extras/WS2812FX change log.txt | 21 ++- library.json | 2 +- library.properties | 2 +- src/WS2812FX.cpp | 6 +- src/WS2812FX.h | 136 +++++++++--------- 8 files changed, 193 insertions(+), 81 deletions(-) create mode 100644 examples/ws2812fx_virtual_strip/ws2812fx_virtual_strip.ino diff --git a/README.md b/README.md index 2235cfa..a2a86f2 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Note, some effects make use of more then one color (up to three) and are program // divide the string of LEDs into two independent segments uint32_t colors[] = {RED, GREEN}; ws2812fx.setSegment(0, 0, (LED_COUNT/2)-1, FX_MODE_BLINK, colors, 1000, false); -ws2812fx.setSegment(1, LED_COUNT/2, LED_COUNT-1, FX_MODE_BLINK, (const uint32_t[]) {ORANGE, PURPLE}, 1000, false); +ws2812fx.setSegment(1, LED_COUNT/2, LED_COUNT-1, FX_MODE_BLINK, COLORS(ORANGE, PURPLE), 1000, false); ``` @@ -124,13 +124,10 @@ Effects 50. **Fire Flicker (intense)** - Fire flickering effect. More range of color. 51. **Circus Combustus** - Alternating white/red/black pixels running. 52. **Halloween** - Alternating orange/purple pixels running. -53. **Bicolor Chase** - Two LEDs running on a background color (set three colors). -54. **Tricolor Chase** - Alternating three color pixels running (set three colors). -55. **ICU** - Two eyes looking around. -56. **Custom** - Up to four user created custom effects. -57. **Custom** -58. **Custom** -59. **Custom** +53. **Bicolor Chase** - Two LEDs running on a background color. +54. **Tricolor Chase** - Alternating three color pixels running. +55. thru 62. **Custom** - Up to eight user created custom effects. + Projects using WS2812FX ----------------------- diff --git a/examples/ws2812fx_virtual_strip/ws2812fx_virtual_strip.ino b/examples/ws2812fx_virtual_strip/ws2812fx_virtual_strip.ino new file mode 100644 index 0000000..926fbc3 --- /dev/null +++ b/examples/ws2812fx_virtual_strip/ws2812fx_virtual_strip.ino @@ -0,0 +1,80 @@ +/* + Demo sketch which shows how to configure WS2812FX such that two physical + stips of LEDs, driven by two separate GPIO pins, get their pixel data + from one virtual strip. One effect can be spread across two strips. + + + LICENSE + + The MIT License (MIT) + + Copyright (c) 2020 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, sub-license, 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 + 2020-05-29 initial version +*/ + +#include + +#define LED_PIN_V1 10 // virtual digital pin used to drive the virtual LED strip +#define LED_PIN_P1 10 // physical digital pin used to drive the first physical LED strip +#define LED_PIN_P2 11 // physical digital pin used to drive the second physical LED strip +#define LED_COUNT_P1 30 // number of LEDs on the first physical strip +#define LED_COUNT_P2 30 // number of LEDs on the second physical strip + +// create an instance of one virtual strip and two physical strips. +// the physical strips are only initialized with a count of one LED, since +// these strips will ultimately use the pixel data of the virtual strip. +// (Note the instances are created with support of only one segment and one +// segment_runtime, just so the sketch fits in an Arduino's limited SRAM.) +WS2812FX ws2812fx_v1 = WS2812FX(LED_COUNT_P1 + LED_COUNT_P2, LED_PIN_V1, NEO_GRB + NEO_KHZ800, 1, 1); +WS2812FX ws2812fx_p1 = WS2812FX(1, LED_PIN_P1, NEO_GRB + NEO_KHZ800, 1, 1); +WS2812FX ws2812fx_p2 = WS2812FX(1, LED_PIN_P2, NEO_GRB + NEO_KHZ800, 1, 1); + +void setup() { + // initialize the virtual strip as you would any normal ws2812fx instance + ws2812fx_v1.init(); + ws2812fx_v1.setBrightness(255); + ws2812fx_v1.setSegment(0, 0, ws2812fx_v1.getLength()-1, FX_MODE_COMET, RED, 2000, NO_OPTIONS); + ws2812fx_v1.start(); + + // init the physical strip's GPIOs and reassign their pixel data + // pointer to use the virtual strip's pixel data. + ws2812fx_p1.init(); + ws2812fx_p1.setPixels(LED_COUNT_P1, ws2812fx_v1.getPixels()); + ws2812fx_p2.init(); + ws2812fx_p2.setPixels(LED_COUNT_P2, ws2812fx_v1.getPixels() + (LED_COUNT_P1 * ws2812fx_v1.getNumBytesPerPixel())); + + // config a custom show() function for the virtual strip, so pixel + // data gets sent to the physical strips's LEDs instead + ws2812fx_v1.setCustomShow(myCustomShow); +} + +void loop() { + // update the virtual strip's pixel data by calling service() as you normally would + ws2812fx_v1.service(); +} + +// update the physical strips's LEDs +void myCustomShow(void) { + ws2812fx_p1.show(); + ws2812fx_p2.show(); +} diff --git a/extras/WS2812FX Users Guide.md b/extras/WS2812FX Users Guide.md index e0a724c..98e4141 100644 --- a/extras/WS2812FX Users Guide.md +++ b/extras/WS2812FX Users Guide.md @@ -522,6 +522,20 @@ show() function. ```c++ ws2812fx.setCustomShow(myCustomShow); ``` + +*** + +## Segment management + +As of v1.3.0 WS2812FX provides more fine grained management of segments by +introducing the idea of idle segments. Segments can be created +in an "idle" state using the setIdleSegment() function. These segments are +initially inactive and can be activated at a later time by using the +addActiveSegment() or swapActiveSegment() functions. Active segments can be +returned to the idle state by using the removeActiveSegment() function. In this +way you can create a bunch of segments, and then pick and choose which segments +are active at runtime. See the **ws2812fx_segment_sequence** example sketch. + *** ## One More Thing diff --git a/extras/WS2812FX change log.txt b/extras/WS2812FX change log.txt index c517568..1004d96 100644 --- a/extras/WS2812FX change log.txt +++ b/extras/WS2812FX change log.txt @@ -1,6 +1,23 @@ WS2182FX Change Log +v1.3.1 changes 6/2/2020 +------------------------ + +1) Changed _modes[] to a static array. Saves a bunch of flash + and SRAM memory when instantiating more than one WS2812FX object. + +2) Added ws2812fx_virtual_strip example sketch to demonstrate how to + use setPixels() to manage the Adafruit_NeoPixel pixel data. + +3) Changed RUNNING_COLOR effect so that the background color is + set to colors[1] instead of hardcoded to WHITE. The default + background color will be BLACK now. Set color[1]=WHITE if + you want the old behavior. + +4) Updated the README.md file. + + v1.3.0 changes 5/11/2020 ------------------------ @@ -40,6 +57,8 @@ v1.3.0 changes 5/11/2020 9) Substantial refactoring of the segment code to use global variables instead of macros, which makes sketches significantly smaller. +10) added setPixels() function to allow users to manually manage the + underlying Adafruit_NeoPixel pixel data. v1.2.4 changes 5/8/2020 @@ -230,7 +249,7 @@ v1.1.4 changes 12/1/2018 1) Refactored the custom effect code to make it more flexible. You can now dynamically assign custom effects to any one of the - four _mode 'slots' by using the setCustomMode(index, name, *p) + four _modes[] 'slots' by using the setCustomMode(index, name, *p) function. 2) Fixed a bug in the DualLarson custom effect that caused it to diff --git a/library.json b/library.json index b4e97b3..1c33765 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "name": "Harm Aldick", "url": "https://github.com/kitesurfer1404/WS2812FX" }, - "version": "1.3.0", + "version": "1.3.1", "downloadUrl": "https://github.com/kitesurfer1404/WS2812FX/archive/master.zip", "export": { "include": "WS2812FX-master" diff --git a/library.properties b/library.properties index c59667a..db7e6e9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=WS2812FX -version=1.3.0 +version=1.3.1 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 3833fe8..4bad735 100644 --- a/src/WS2812FX.cpp +++ b/src/WS2812FX.cpp @@ -61,7 +61,7 @@ void WS2812FX::init() { // void WS2812FX::timer() { // for (int j=0; j < 1000; j++) { -// uint16_t delay = (this->*_mode[_seg->mode])(); +// uint16_t delay = (this->*_modes[_seg->mode])(); // } // } @@ -78,7 +78,7 @@ void WS2812FX::service() { if(now > _seg_rt->next_time || _triggered) { SET_FRAME; doShow = true; - uint16_t delay = (this->*_mode[_seg->mode])(); + uint16_t delay = (this->*_modes[_seg->mode])(); _seg_rt->next_time = now + max(delay, SPEED_MIN); _seg_rt->counter_mode_call++; } @@ -1377,7 +1377,7 @@ uint16_t WS2812FX::running(uint32_t color1, uint32_t color2) { * Alternating color/white pixels running. */ uint16_t WS2812FX::mode_running_color(void) { - return running(_seg->colors[0], WHITE); + return running(_seg->colors[0], _seg->colors[1]); } diff --git a/src/WS2812FX.h b/src/WS2812FX.h index d028a2c..aeb4846 100644 --- a/src/WS2812FX.h +++ b/src/WS2812FX.h @@ -322,9 +322,9 @@ static const __FlashStringHelper* _names[] = { class WS2812FX : public Adafruit_NeoPixel { -typedef uint16_t (WS2812FX::*mode_ptr)(void); - public: + typedef uint16_t (WS2812FX::*mode_ptr)(void); + // segment parameters typedef struct Segment { // 20 bytes uint16_t start; @@ -349,69 +349,6 @@ typedef uint16_t (WS2812FX::*mode_ptr)(void); uint8_t max_num_segments=MAX_NUM_SEGMENTS, uint8_t max_num_active_segments=MAX_NUM_ACTIVE_SEGMENTS) : Adafruit_NeoPixel(num_leds, pin, type) { - _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; - _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; - _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; - _mode[FX_MODE_COLOR_WIPE_INV] = &WS2812FX::mode_color_wipe_inv; - _mode[FX_MODE_COLOR_WIPE_REV] = &WS2812FX::mode_color_wipe_rev; - _mode[FX_MODE_COLOR_WIPE_REV_INV] = &WS2812FX::mode_color_wipe_rev_inv; - _mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random; - _mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color; - _mode[FX_MODE_SINGLE_DYNAMIC] = &WS2812FX::mode_single_dynamic; - _mode[FX_MODE_MULTI_DYNAMIC] = &WS2812FX::mode_multi_dynamic; - _mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow; - _mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle; - _mode[FX_MODE_SCAN] = &WS2812FX::mode_scan; - _mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan; - _mode[FX_MODE_FADE] = &WS2812FX::mode_fade; - _mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase; - _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; - _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; - _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; - _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; - _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; - _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; - _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; - _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; - _mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe; - _mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow; - _mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe; - _mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow; - _mode[FX_MODE_CHASE_WHITE] = &WS2812FX::mode_chase_white; - _mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color; - _mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random; - _mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow; - _mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash; - _mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random; - _mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white; - _mode[FX_MODE_CHASE_BLACKOUT] = &WS2812FX::mode_chase_blackout; - _mode[FX_MODE_CHASE_BLACKOUT_RAINBOW] = &WS2812FX::mode_chase_blackout_rainbow; - _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; - _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; - _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; - _mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; - _mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; - _mode[FX_MODE_COMET] = &WS2812FX::mode_comet; - _mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; - _mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; - _mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; - _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; - _mode[FX_MODE_FIRE_FLICKER_SOFT] = &WS2812FX::mode_fire_flicker_soft; - _mode[FX_MODE_FIRE_FLICKER_INTENSE] = &WS2812FX::mode_fire_flicker_intense; - _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; - _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween; - _mode[FX_MODE_BICOLOR_CHASE] = &WS2812FX::mode_bicolor_chase; - _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; - _mode[FX_MODE_BREATH] = &WS2812FX::mode_breath; - _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; - _mode[FX_MODE_CUSTOM_0] = &WS2812FX::mode_custom_0; - _mode[FX_MODE_CUSTOM_1] = &WS2812FX::mode_custom_1; - _mode[FX_MODE_CUSTOM_2] = &WS2812FX::mode_custom_2; - _mode[FX_MODE_CUSTOM_3] = &WS2812FX::mode_custom_3; - _mode[FX_MODE_CUSTOM_4] = &WS2812FX::mode_custom_4; - _mode[FX_MODE_CUSTOM_5] = &WS2812FX::mode_custom_5; - _mode[FX_MODE_CUSTOM_6] = &WS2812FX::mode_custom_6; - _mode[FX_MODE_CUSTOM_7] = &WS2812FX::mode_custom_7; brightness = DEFAULT_BRIGHTNESS + 1; // Adafruit_NeoPixel internally offsets brightness by 1 _running = false; @@ -637,8 +574,6 @@ typedef uint16_t (WS2812FX::*mode_ptr)(void); _running, _triggered; - mode_ptr _mode[MODE_COUNT]; // array of mode function pointers (4 bytes per element) - segment* _segments; // array of segments (20 bytes per element) segment_runtime* _segment_runtimes; // array of segment runtimes (16 bytes per element) uint8_t* _active_segments; // array of active segments (1 bytes per element) @@ -653,4 +588,71 @@ typedef uint16_t (WS2812FX::*mode_ptr)(void); uint16_t _seg_len; // num LEDs in the currently active segment }; +// 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] = { + &WS2812FX::mode_static, + &WS2812FX::mode_blink, + &WS2812FX::mode_breath, + &WS2812FX::mode_color_wipe, + &WS2812FX::mode_color_wipe_inv, + &WS2812FX::mode_color_wipe_rev, + &WS2812FX::mode_color_wipe_rev_inv, + &WS2812FX::mode_color_wipe_random, + &WS2812FX::mode_random_color, + &WS2812FX::mode_single_dynamic, + &WS2812FX::mode_multi_dynamic, + &WS2812FX::mode_rainbow, + &WS2812FX::mode_rainbow_cycle, + &WS2812FX::mode_scan, + &WS2812FX::mode_dual_scan, + &WS2812FX::mode_fade, + &WS2812FX::mode_theater_chase, + &WS2812FX::mode_theater_chase_rainbow, + &WS2812FX::mode_running_lights, + &WS2812FX::mode_twinkle, + &WS2812FX::mode_twinkle_random, + &WS2812FX::mode_twinkle_fade, + &WS2812FX::mode_twinkle_fade_random, + &WS2812FX::mode_sparkle, + &WS2812FX::mode_flash_sparkle, + &WS2812FX::mode_hyper_sparkle, + &WS2812FX::mode_strobe, + &WS2812FX::mode_strobe_rainbow, + &WS2812FX::mode_multi_strobe, + &WS2812FX::mode_blink_rainbow, + &WS2812FX::mode_chase_white, + &WS2812FX::mode_chase_color, + &WS2812FX::mode_chase_random, + &WS2812FX::mode_chase_rainbow, + &WS2812FX::mode_chase_flash, + &WS2812FX::mode_chase_flash_random, + &WS2812FX::mode_chase_rainbow_white, + &WS2812FX::mode_chase_blackout, + &WS2812FX::mode_chase_blackout_rainbow, + &WS2812FX::mode_color_sweep_random, + &WS2812FX::mode_running_color, + &WS2812FX::mode_running_red_blue, + &WS2812FX::mode_running_random, + &WS2812FX::mode_larson_scanner, + &WS2812FX::mode_comet, + &WS2812FX::mode_fireworks, + &WS2812FX::mode_fireworks_random, + &WS2812FX::mode_merry_christmas, + &WS2812FX::mode_fire_flicker, + &WS2812FX::mode_fire_flicker_soft, + &WS2812FX::mode_fire_flicker_intense, + &WS2812FX::mode_circus_combustus, + &WS2812FX::mode_halloween, + &WS2812FX::mode_bicolor_chase, + &WS2812FX::mode_tricolor_chase, + &WS2812FX::mode_custom_0, + &WS2812FX::mode_custom_1, + &WS2812FX::mode_custom_2, + &WS2812FX::mode_custom_3, + &WS2812FX::mode_custom_4, + &WS2812FX::mode_custom_5, + &WS2812FX::mode_custom_6, + &WS2812FX::mode_custom_7 +}; #endif