├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── Responsive_Led_Control.ino
├── colormodes.h
├── data-moved_aside
├── color-selector.htm
├── graphs.htm
└── graphs.js.gz
├── data
├── custom.css
├── edit.htm.gz
├── favicon.ico
├── index.htm.gz
├── jscolor.js.gz
├── offline.appcache
└── palettes
│ ├── 35_blue_waves.bin
│ ├── 37_waves.bin
│ ├── Green_White_Red.bin
│ ├── Lindaa07.bin
│ ├── beading.bin
│ ├── bhw1_29.bin
│ ├── bhw1_greenie.bin
│ ├── bhw1_purpgreen.bin
│ ├── bhw1_purplered.bin
│ ├── bhw1_sunconure.bin
│ ├── bhw2_xmas.bin
│ ├── blueeyedgal.bin
│ ├── brightsong2.bin
│ ├── bud2.bin
│ ├── christmas-candy.bin
│ ├── faewing3.bin
│ ├── goddess-moon.bin
│ ├── lkmtch00.bin
│ ├── patriot.bin
│ ├── plasma.bin
│ ├── prism.bin
│ ├── sls.bin
│ ├── sorcery-2.bin
│ ├── starrynite.bin
│ ├── twilight.bin
│ ├── usa1.bin
│ ├── water1.bin
│ └── wintercolors.bin
├── definitions.h
├── documentation
├── large.png
├── large50.png
├── small.png
└── small50.png
├── eepromsettings.h
├── palette_convert
├── alpen.txt
├── alpen_mango.bin
├── alpen_natural.bin
├── alpen_refuel.bin
├── bhw1_greenie.bin
├── bhw2_23.bin
├── colo_starcrossed.bin
├── colo_tastetherain.bin
├── ggr_blinds.bin
├── ggr_fourbars.bin
├── imagej_edges.bin
├── palette_convert.py
└── vredeling_sleep.bin
├── palettes.h
├── request_handlers.h
└── spiffs_webserver.h
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doctormord/Responsive_LED_Control/18f61be0a325c35fa90150cbecc8023d7f6165d4/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 | .DS_Store
4 | .DS_Store
5 | upload these via file mgr to ESP8266/.DS_Store
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # doctormord's Responsive Led Control
2 | I mixed the work of [McLighting](https://github.com/toblum/McLighting), [Russell](https://github.com/russp81/LEDLAMP_FASTLEDs) and [Jake's "Grisworld"](https://github.com/jake-b/Griswold-LED-Controller) with [FastLED](https://github.com/FastLED/FastLED) (FastLED library 3.1.3 as of this writing), the colorjs colorpicker, color spectrums created via FastLED Palette Knife, and some additional strip animations (included in the Arduino Sketch above).
3 |
4 | FastLED 3.1.3 library:
5 | https://github.com/FastLED/FastLED
6 |
7 | McLighting library:
8 | https://github.com/toblum/McLighting
9 |
10 | Russel's implementation:
11 | https://github.com/russp81/LEDLAMP_FASTLEDs
12 |
13 | Jakes's "Grisworld" Led Controller
14 | https://github.com/jake-b/Griswold-LED-Controller
15 |
16 | jscolor Color Picker:
17 | http://jscolor.com/
18 |
19 | FastLED Palette Knife:
20 | http://fastled.io/tools/paletteknife/
21 |
22 | RemoteDebug:
23 | https://github.com/JoaoLopesF/RemoteDebug
24 |
25 |
26 | If you aren't familiar with how to setup your ESP8266, see the readme on McLighting's git. It's well written and should get you up and running.
27 |
28 | In short you will:
29 |
30 | 1. Configure the Arduino IDE to communicate with the ESP8266
31 | 2. Upload the sketch (from this repo) The sketch is setup for a 120 pixel WS2812B GRB LED Strip.
32 | (change the applicable options in "definitions.h" to your desire)
33 | 3. Patch FastLED Library
34 |
35 | ```arduino
36 | // Note, you need to patch FastLEDs in order to use this. You'll get an
37 | // error related to . Saves more than 3k given the palettes
38 | //
39 | // Simply edit and update the include (Line ~29):
40 |
41 | #if FASTLED_INCLUDE_PGMSPACE == 1
42 | #if (defined(__AVR__))
43 | #include
44 | #else
45 | #include
46 | #endif
47 | #endif
48 | ```
49 |
50 | 4. On first launch, the ESP8266 will advertise it's own WiFi network for you to connect to, once you connect to it, launch your browser
51 | and the web interface is self explanatory. (If the interface doesn't load, type in "192.168.4.1" into your browser and hit go)
52 | 5. Once the ESP is on your wifi network, you can then upload the required files for the web interface by typing the in IP address
53 | of the ESP followed by "/edit" (i.e. 192.168.1.20/edit). Then upload the files from the folder labeled "upload these" from this repo. (Or use ESP8266 filesystem uploader, see below)
54 | 6. Once you have finished uploading, type in the IP of the ESP into your browser and you should be up and running!
55 |
56 | Forked from Russel, i removed Adafruit Neopixel references and library calls.
57 |
58 | # Uploading SPIFFS data all at once
59 |
60 | Use ESP8266FS plugin to upload all files from /data to SPIFFS.
61 |
62 | Arduino ESP8266 filesystem uploader
63 | https://github.com/esp8266/arduino-esp8266fs-plugin
64 |
65 | # Improvements/changes so far:
66 |
67 | * new effect: Fire (from WS2812FX)
68 | * new effect: RainbowFire
69 | * new effect: Fireworks [single color, rainbow, random] (from McLightning, ported to used FastLED instead off Adafruit Neopixel)
70 | * new settings for effects in webinterface *.htm
71 |
72 | * speedup the UI alot by pulling the materialize stuff (.css/.js) from server and using .gz compressed files for the rest
73 | * made the UI more responsive with grouped sections and buttons
74 | * added some more palettes
75 | * integrated Arduino OTA
76 | * included setup of LED-count and maximum allowed LED-current to web-interface and EEprom, so different strings don't need changs in source-code
77 |
78 | Large Screen (Desktop)
79 |
80 | 
81 |
82 | Small Screen (Mobile)
83 |
84 | 
85 |
86 |
87 | ~~I edited clockless_esp8266.h (in the FastLED platforms folder) and
88 | kept getting flickering until I incremented the WAIT_TIME up to 18us.
89 | (also I did "#define FASTLED_INTERRUPT_RETRY_COUNT 3" inside my sketch).~~
90 |
91 | For reference, interrupts issue: https://github.com/FastLED/FastLED/issues/306
92 |
93 | # License
94 |
95 | As per the original [McLighting](https://github.com/toblum/McLighting) and [Jake's "Grisworld"](https://github.com/jake-b/Griswold-LED-Controller) project, this project is released under the GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007.
96 |
97 | Griswold is free software: you can redistribute it and/or modify
98 | it under the terms of the GNU Lesser General Public License as
99 | published by the Free Software Foundation, either version 3 of
100 | the License, or (at your option) any later version.
101 |
102 | This program is distributed in the hope that it will be useful,
103 | but WITHOUT ANY WARRANTY; without even the implied warranty of
104 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105 | GNU General Public License for more details.
106 |
107 | You should have received a copy of the GNU Lesser General Public License
108 | along with this program. If not, see .
109 |
110 |
111 | # Portions of @jake-b "Griswold" LED controller original README
112 |
113 | I bought 1000 WS2811 nodes for my outdoor Christmas light installation this year.
114 | Based on the "Russell's FASTLEDs" project by @russp81, which is in turn based on the "McLighting" project by @toblum
115 |
116 | It seemed necessary to name the thing after Clark Griswold, but really just to differentiate this fork from the originals.
117 |
118 | @russp81 mixed the work of @toblum with the @FastLED (FastLED library 3.1.3 as of this writing), the colorjs colorpicker, color spectrums created via FastLED Palette Knife, and some additional strip animations.
119 |
120 | # Improvements
121 |
122 | - Palettes stored as binary files on SPIFFS. See below for more information on this.
123 | - Display name of the current palette file in the web interface.
124 | - Added ArduinoOTA support so I can update the firmware over WiFi, which will be important when its installed outside.
125 | - Added the ability to store the settings in EEPROM and restore on boot.
126 | - Merged the jscolor interface into the original McLighting interface
127 | - Updated the McLighting interface to retrieve the current settings from the device, and update the UI with the current settings, rather than always default to the defaults.
128 | - General code formatting clean-up.
129 | - Added “RemoteDebug” library for serial console over telnet. (Optional #define)
130 | - Fixed divide-by-zero error that occurs when fps=0 by preventing fps=0 from the UI.
131 | - Updates to the “animated palette” function, now you can select a single palette, or the existing randomized palette after time delay.
132 | - Rearchitected things a bit, now the colormodes.h functions render one single frame, and do not block the main thread.
133 | - Added back the wipe and tv animations from the original McLighting project (removed in LEDLAMP_FASTLEDs)
134 | - Modified TV animation to add some flicker (I like it better)
135 | - Added “effect brightness” setting to allow you to dim the main effect independently of glitter.
136 |
137 | # Palettes on SPIFFS
138 |
139 | Normally, you use [PaletteKnife](http://fastled.io/tools/paletteknife/) to generate arrays with the palette info. You then compile this data into your project. I wanted to be able to update the palettes without recompiling, so I moved them to files in SPIFFS (/palettes directory). There is a little python program that basically takes the logic from PaletteKnife and outputs a binary file with the palette data instead. Load these binary files to SPIFFS using the [Arduino ESP8266 filesystem uploader](https://github.com/esp8266/arduino-esp8266fs-plugin) or manually.
140 |
--------------------------------------------------------------------------------
/Responsive_Led_Control.ino:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016-2019 @doctormord @jake-b, @russp81, @toblum
2 | // Responsive LED Control
3 |
4 | // This is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU Lesser General Public License as
6 | // published by the Free Software Foundation, either version 3 of
7 | // the License, or (at your option) any later version.
8 |
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 |
14 | // You should have received a copy of the GNU Lesser General Public License
15 | // along with this program. If not, see .
16 |
17 | // Griswold is a fork of the LEDLAMP project at
18 | // https://github.com/russp81/LEDLAMP_FASTLEDs
19 |
20 | // The LEDLAMP project is a fork of the McLighting Project at
21 | // https://github.com/toblum/McLighting
22 |
23 | // ***************************************************************************
24 | // Load libraries for: WebServer / WiFiManager / WebSockets
25 | // ***************************************************************************
26 | #include //https://github.com/esp8266/Arduino
27 |
28 | // needed for library WiFiManager
29 | #include
30 | #include
31 | #include //https://github.com/tzapu/WiFiManager
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #include
39 | //#include "RemoteDebug.h" //https://github.com/JoaoLopesF/RemoteDebug
40 |
41 | #include //https://github.com/Links2004/arduinoWebSockets
42 | #include
43 |
44 | // ***************************************************************************
45 | // Sub-modules of this application
46 | // ***************************************************************************
47 | #include "definitions.h"
48 | #include "eepromsettings.h"
49 | #include "palettes.h"
50 | #include "colormodes.h"
51 |
52 | // ***************************************************************************
53 | // Instanciate HTTP(80) / WebSockets(81) Server
54 | // ***************************************************************************
55 | ESP8266WebServer server(80);
56 | WebSocketsServer webSocket = WebSocketsServer(81);
57 |
58 | // ***************************************************************************
59 | // Load library "ticker" for blinking status led
60 | // ***************************************************************************
61 | Ticker ticker;
62 |
63 | void tick() {
64 | // toggle state
65 | int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
66 | digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state
67 | }
68 |
69 | // ***************************************************************************
70 | // Callback for WiFiManager library when config mode is entered
71 | // ***************************************************************************
72 | // gets called when WiFiManager enters configuration mode
73 | void configModeCallback(WiFiManager *myWiFiManager) {
74 | DBG_OUTPUT_PORT.println("Entered config mode");
75 | DBG_OUTPUT_PORT.println(WiFi.softAPIP());
76 | // if you used auto generated SSID, print it
77 | DBG_OUTPUT_PORT.println(myWiFiManager->getConfigPortalSSID());
78 | // entered config mode, make led toggle faster
79 | ticker.attach(0.2, tick);
80 |
81 | // Show USER that module can't connect to stored WiFi
82 | uint16_t i;
83 | for (i = 0; i < 2; i++) {
84 | leds[i].setRGB(0, 0, 50);
85 | }
86 | FastLED.show();
87 | }
88 |
89 | // ***************************************************************************
90 | // Include: Webserver & Request Handlers
91 | // ***************************************************************************
92 | #include "spiffs_webserver.h" // must be included after the 'server' object
93 | #include "request_handlers.h" // is declared.
94 |
95 | // ***************************************************************************
96 | // MAIN
97 | // ***************************************************************************
98 | void setup() {
99 |
100 | // Generate a pseduo-unique hostname
101 | char hostname[strlen(HOSTNAME_PREFIX)+6];
102 | uint16_t chipid = ESP.getChipId() & 0xFFFF;
103 | sprintf(hostname, "%s-%04x",HOSTNAME_PREFIX, chipid);
104 |
105 | #ifdef REMOTE_DEBUG
106 | Debug.begin(hostname); // Initiaze the telnet server - hostname is the used
107 | // in MDNS.begin
108 | Debug.setResetCmdEnabled(true); // Enable the reset command
109 | #endif
110 |
111 | // ***************************************************************************
112 | // Setup: EEPROM
113 | // ***************************************************************************
114 | initSettings(); // setting loaded from EEPROM or defaults if fail
115 | printSettings();
116 |
117 | ///*** Random Seed***
118 | randomSeed(analogRead(0));
119 |
120 | //********color palette setup stuff****************
121 | currentPalette = RainbowColors_p;
122 | loadPaletteFromFile(settings.palette_ndx, &targetPalette);
123 | currentBlending = LINEARBLEND;
124 | //**************************************************
125 |
126 | #ifndef REMOTE_DEBUG
127 | DBG_OUTPUT_PORT.begin(115200);
128 | #endif
129 | DBG_OUTPUT_PORT.printf("system_get_cpu_freq: %d\n", system_get_cpu_freq());
130 |
131 | // set builtin led pin as output
132 | pinMode(LED_BUILTIN, OUTPUT);
133 | // start ticker with 0.5 because we start in AP mode and try to connect
134 | ticker.attach(0.5, tick);
135 |
136 | // ***************************************************************************
137 | // Setup: FASTLED
138 | // ***************************************************************************
139 | delay(500); // 500ms delay for recovery
140 |
141 | // limit my draw to 2.1A at 5v of power draw
142 | FastLED.setMaxPowerInVoltsAndMilliamps(5,settings.max_current);
143 |
144 | // maximum refresh rate
145 | FastLED.setMaxRefreshRate(FASTLED_HZ);
146 |
147 | // tell FastLED about the LED strip configuration
148 | FastLED.addLeds(leds, settings.num_leds)
149 | .setCorrection(TypicalLEDStrip);
150 |
151 | // FastLED.addLeds(leds,
152 | // NUM_LEDS).setCorrection(TypicalLEDStrip);
153 | // set master brightness control
154 | FastLED.setBrightness(settings.overall_brightness);
155 |
156 |
157 | // ***************************************************************************
158 | // Setup: WiFiManager
159 | // ***************************************************************************
160 | // Local intialization. Once its business is done, there is no need to keep it
161 | // around
162 | WiFiManager wifiManager;
163 | // reset settings - for testing
164 | // wifiManager.resetSettings();
165 |
166 | //sets timeout until configuration portal gets turned off
167 | //useful to make it all retry or go to sleep
168 | //in seconds
169 | wifiManager.setTimeout(20);
170 | wifiManager.setBreakAfterConfig(true);
171 |
172 | // set callback that gets called when connecting to previous WiFi fails, and
173 | // enters Access Point mode
174 | wifiManager.setAPCallback(configModeCallback);
175 |
176 |
177 | // fetches ssid and pass and tries to connect
178 | // if it does not connect it starts an access point with the specified name
179 | // here "AutoConnectAP"
180 | // and goes into a blocking loop awaiting configuration
181 |
182 | if (!wifiManager.autoConnect(hostname)) {
183 | DBG_OUTPUT_PORT.println("failed to connect and hit timeout");
184 | DBG_OUTPUT_PORT.println("No connection made, loading last saved show parameters..");
185 | WiFi.forceSleepBegin(); // power down WiFi, as it is not needed anymore.
186 | }
187 |
188 | // if you get here you have connected to the WiFi
189 | DBG_OUTPUT_PORT.println("get the show started.. :)");
190 | ticker.detach();
191 | // keep LED on
192 | digitalWrite(LED_BUILTIN, LOW);
193 |
194 | // ***************************************************************************
195 | // Setup: ArduinoOTA
196 | // ***************************************************************************
197 | ArduinoOTA.setHostname(hostname);
198 | ArduinoOTA.onStart([]() {
199 |
200 | String type;
201 | // if (ArduinoOTA.getCommand() == U_FLASH)
202 | // type = "sketch";
203 | // else
204 | // type = "filesystem";
205 | //
206 | SPIFFS.end(); // unmount SPIFFS for update.
207 | // DBG_OUTPUT_PORT.println("Start updating " + type);
208 | DBG_OUTPUT_PORT.println("Start updating ");
209 | });
210 | ArduinoOTA.onEnd([]() {
211 | DBG_OUTPUT_PORT.println("\nEnd... remounting SPIFFS");
212 | SPIFFS.begin();
213 | paletteCount = getPaletteCount();
214 | });
215 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
216 | DBG_OUTPUT_PORT.printf("Progress: %u%%\r", (progress / (total / 100)));
217 | });
218 | ArduinoOTA.onError([](ota_error_t error) {
219 | DBG_OUTPUT_PORT.printf("Error[%u]: ", error);
220 | if (error == OTA_AUTH_ERROR)
221 | DBG_OUTPUT_PORT.println("Auth Failed");
222 | else if (error == OTA_BEGIN_ERROR)
223 | DBG_OUTPUT_PORT.println("Begin Failed");
224 | else if (error == OTA_CONNECT_ERROR)
225 | DBG_OUTPUT_PORT.println("Connect Failed");
226 | else if (error == OTA_RECEIVE_ERROR)
227 | DBG_OUTPUT_PORT.println("Receive Failed");
228 | else if (error == OTA_END_ERROR)
229 | DBG_OUTPUT_PORT.println("End Failed");
230 | });
231 |
232 | ArduinoOTA.begin();
233 | DBG_OUTPUT_PORT.println("OTA Ready");
234 | DBG_OUTPUT_PORT.print("IP address: ");
235 | DBG_OUTPUT_PORT.println(WiFi.localIP());
236 |
237 |
238 | // ***************************************************************************
239 | // Setup: MDNS responder
240 | // ***************************************************************************
241 | MDNS.begin(hostname);
242 | DBG_OUTPUT_PORT.print("Open http://");
243 | DBG_OUTPUT_PORT.print(hostname);
244 | DBG_OUTPUT_PORT.println(".local/edit to see the file browser");
245 |
246 | // ***************************************************************************
247 | // Setup: WebSocket server
248 | // ***************************************************************************
249 | webSocket.begin();
250 | webSocket.onEvent(webSocketEvent);
251 |
252 | // ***************************************************************************
253 | // Setup: SPIFFS
254 | // ***************************************************************************
255 | SPIFFS.begin();
256 | {
257 | Dir dir = SPIFFS.openDir("/");
258 | while (dir.next()) {
259 | String fileName = dir.fileName();
260 | size_t fileSize = dir.fileSize();
261 | DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(),
262 | formatBytes(fileSize).c_str());
263 | }
264 | DBG_OUTPUT_PORT.printf("\n");
265 | }
266 |
267 | // ***************************************************************************
268 | // Setup: SPIFFS Webserver handler
269 | // ***************************************************************************
270 |
271 | // list directory
272 | server.on("/list", HTTP_GET, handleFileList);
273 |
274 | // load editor
275 | server.on("/edit", HTTP_GET, []() {
276 | if (!handleFileRead("/edit.htm"))
277 | server.send(404, "text/plain", "FileNotFound");
278 | });
279 |
280 | // create file
281 | server.on("/edit", HTTP_PUT, handleFileCreate);
282 |
283 | // delete file
284 | server.on("/edit", HTTP_DELETE, handleFileDelete);
285 |
286 | // first callback is called after the request has ended with all parsed
287 | // arguments
288 | // second callback handles file uploads at that location
289 | server.on("/edit", HTTP_POST, []() { server.send(200, "text/plain", ""); },
290 | handleFileUpload);
291 |
292 | // get heap status, analog input value and all GPIO statuses in one json call
293 | server.on("/esp_status", HTTP_GET, []() {
294 | String json = "{";
295 | json += "\"heap\":" + String(ESP.getFreeHeap());
296 | json += ", \"analog\":" + String(analogRead(A0));
297 | json += ", \"gpio\":" +
298 | String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
299 | json += "}";
300 | server.send(200, "text/json", json);
301 | json = String();
302 | });
303 |
304 | // called when the url is not defined here
305 | // use it to load content from SPIFFS
306 | server.onNotFound([]() {
307 | if (!handleFileRead(server.uri())) handleNotFound();
308 | });
309 |
310 | server.on("/upload", handleMinimalUpload);
311 |
312 | server.on("/restart", []() {
313 | DBG_OUTPUT_PORT.printf("/restart:\n");
314 | server.send(200, "text/plain", "restarting...");
315 | ESP.restart();
316 | });
317 |
318 | server.on("/reset_wlan", []() {
319 | DBG_OUTPUT_PORT.printf("/reset_wlan:\n");
320 | server.send(200, "text/plain", "Resetting WLAN and restarting...");
321 | WiFiManager wifiManager;
322 | wifiManager.resetSettings();
323 | ESP.restart();
324 | });
325 |
326 | // ***************************************************************************
327 | // Setup: SPIFFS Webserver handler
328 | // ***************************************************************************
329 | server.on("/set_brightness", []() {
330 | if (server.arg("c").toInt() > 0) {
331 | settings.overall_brightness = (int)server.arg("c").toInt() * 2.55;
332 | } else {
333 | settings.overall_brightness = server.arg("p").toInt();
334 | }
335 | if (settings.overall_brightness > 255) {
336 | settings.overall_brightness = 255;
337 | }
338 | if (settings.overall_brightness < 0) {
339 | settings.overall_brightness = 0;
340 | }
341 | FastLED.setBrightness(settings.overall_brightness);
342 |
343 | if (settings.mode == HOLD) {
344 | settings.mode = ALL;
345 | }
346 |
347 | getStatusJSON();
348 | });
349 |
350 | server.on("/get_brightness", []() {
351 | String str_brightness = String((int)(settings.overall_brightness / 2.55));
352 | server.send(200, "text/plain", str_brightness);
353 | DBG_OUTPUT_PORT.print("/get_brightness: ");
354 | DBG_OUTPUT_PORT.println(str_brightness);
355 | });
356 |
357 | server.on("/get_switch", []() {
358 | server.send(200, "text/plain", (settings.mode == OFF) ? "0" : "1");
359 | DBG_OUTPUT_PORT.printf("/get_switch: %s\n",
360 | (settings.mode == OFF) ? "0" : "1");
361 | });
362 |
363 | server.on("/get_color", []() {
364 | String rgbcolor = String(settings.main_color.red, HEX) +
365 | String(settings.main_color.green, HEX) +
366 | String(settings.main_color.blue, HEX);
367 | server.send(200, "text/plain", rgbcolor);
368 | DBG_OUTPUT_PORT.print("/get_color: ");
369 | DBG_OUTPUT_PORT.println(rgbcolor);
370 | });
371 |
372 | server.on("/status", []() { getStatusJSON(); });
373 |
374 | server.on("/off", []() {
375 | //exit_func = true;
376 | settings.mode = OFF;
377 | getArgs();
378 | getStatusJSON();
379 | });
380 |
381 | server.on("/all", []() {
382 | //exit_func = true;
383 | settings.mode = ALL;
384 | getArgs();
385 | getStatusJSON();
386 | });
387 |
388 | server.on("/rainbow", []() {
389 | //exit_func = true;
390 | settings.mode = RAINBOW;
391 | getArgs();
392 | getStatusJSON();
393 | });
394 |
395 | server.on("/confetti", []() {
396 | //exit_func = true;
397 | settings.mode = CONFETTI;
398 | getArgs();
399 | getStatusJSON();
400 | });
401 |
402 | server.on("/sinelon", []() {
403 | //exit_func = true;
404 | settings.mode = SINELON;
405 | getArgs();
406 | getStatusJSON();
407 | });
408 |
409 | server.on("/juggle", []() {
410 | //exit_func = true;
411 | settings.mode = JUGGLE;
412 | getArgs();
413 | getStatusJSON();
414 | });
415 |
416 | server.on("/bpm", []() {
417 | //exit_func = true;
418 | settings.mode = BPM;
419 | getArgs();
420 | getStatusJSON();
421 | });
422 |
423 | server.on("/ripple", []() {
424 | //exit_func = true;
425 | settings.mode = RIPPLE;
426 | getArgs();
427 | getStatusJSON();
428 | });
429 |
430 | server.on("/comet", []() {
431 | //exit_func = true;
432 | settings.mode = COMET;
433 | getArgs();
434 | getStatusJSON();
435 | });
436 |
437 | server.on("/wipe", []() {
438 | settings.mode = WIPE;
439 | getArgs();
440 | getStatusJSON();
441 | });
442 |
443 | server.on("/tv", []() {
444 | settings.mode = TV;
445 | getArgs();
446 | getStatusJSON();
447 | });
448 |
449 | server.on("/fire", []() {
450 | //exit_func = true;
451 | settings.mode = FIRE;
452 | getArgs();
453 | getStatusJSON();
454 | });
455 |
456 | server.on("/frainbow", []() {
457 | //exit_func = true;
458 | settings.mode = FIRE_RAINBOW;
459 | getArgs();
460 | getStatusJSON();
461 | });
462 |
463 | server.on("/fworks", []() {
464 | //exit_func = true;
465 | settings.mode = FIREWORKS;
466 | getArgs();
467 | getStatusJSON();
468 | });
469 |
470 | server.on("/fwsingle", []() {
471 | //exit_func = true;
472 | settings.mode = FIREWORKS_SINGLE;
473 | getArgs();
474 | getStatusJSON();
475 | });
476 |
477 | server.on("/fwrainbow", []() {
478 | //exit_func = true;
479 | settings.mode = FIREWORKS_RAINBOW;
480 | getArgs();
481 | getStatusJSON();
482 | });
483 |
484 | server.on("/palette_anims", []() {
485 | settings.mode = PALETTE_ANIMS;
486 | if (server.arg("p") != "") {
487 | uint8_t pal = (uint8_t) strtol(server.arg("p").c_str(), NULL, 10);
488 | if (pal > paletteCount)
489 | pal = paletteCount;
490 |
491 | settings.palette_ndx = pal;
492 | loadPaletteFromFile(settings.palette_ndx, &targetPalette);
493 | currentPalette = targetPalette; //PaletteCollection[settings.palette_ndx];
494 | DBG_OUTPUT_PORT.printf("Palette is: %d", pal);
495 | }
496 | getStatusJSON();
497 | });
498 |
499 | server.begin();
500 |
501 | paletteCount = getPaletteCount();
502 | }
503 |
504 |
505 |
506 | void loop() {
507 | EVERY_N_MILLISECONDS(int(float(1000 / settings.fps))) {
508 | gHue++; // slowly cycle the "base color" through the rainbow
509 | }
510 |
511 | // adjust LED current to actual value;
512 | FastLED.setMaxPowerInVoltsAndMilliamps(5,settings.max_current);
513 |
514 | // Simple statemachine that handles the different modes
515 | switch (settings.mode) {
516 | default:
517 | case OFF:
518 | fill_solid(leds, settings.num_leds, CRGB(0,0,0));
519 | break;
520 |
521 | case ALL:
522 | fill_solid(leds, settings.num_leds, CRGB(settings.main_color.red, settings.main_color.green,
523 | settings.main_color.blue));
524 | break;
525 |
526 | case MIXEDSHOW:
527 | {
528 | gPatterns[gCurrentPatternNumber]();
529 |
530 | // send the 'leds' array out to the actual LED strip
531 | int showlength_Millis = settings.show_length * 1000;
532 |
533 | // DBG_OUTPUT_PORT.println("showlengthmillis = " +
534 | // String(showlength_Millis));
535 | if (((millis()) - (lastMillis)) >= showlength_Millis) {
536 | nextPattern();
537 | DBG_OUTPUT_PORT.println( "void nextPattern was called at " + String(millis()) +
538 | " and the current show length set to " + String(showlength_Millis));
539 | }
540 | }
541 | break;
542 |
543 | case RAINBOW:
544 | rainbow();
545 | break;
546 |
547 | case CONFETTI:
548 | confetti();
549 | break;
550 |
551 | case SINELON:
552 | sinelon();
553 | break;
554 |
555 | case JUGGLE:
556 | juggle();
557 | break;
558 |
559 | case BPM:
560 | bpm();
561 | break;
562 |
563 | case PALETTE_ANIMS:
564 | palette_anims();
565 | break;
566 |
567 | case RIPPLE:
568 | ripple();
569 | break;
570 |
571 | case COMET:
572 | comet();
573 | break;
574 |
575 | case THEATERCHASE:
576 | theaterChase();
577 | break;
578 |
579 | case WIPE:
580 | colorWipe();
581 | break;
582 |
583 | case TV:
584 | tv();
585 | break;
586 |
587 | case FIRE:
588 | fire2012();
589 | break;
590 |
591 | case FIRE_RAINBOW:
592 | fire_rainbow();
593 | break;
594 |
595 | case FIREWORKS:
596 | fireworks();
597 | break;
598 |
599 | case FIREWORKS_SINGLE:
600 | fw_single();
601 | break;
602 |
603 | case FIREWORKS_RAINBOW:
604 | fw_rainbow();
605 | break;
606 | }
607 |
608 | // Add glitter if necessary
609 | if (settings.glitter_on == true) {
610 | addGlitter(settings.glitter_density);
611 | }
612 |
613 | // Get the current time
614 | unsigned long continueTime = millis() + int(float(1000 / settings.fps));
615 | // Do our main loop functions, until we hit our wait time
616 |
617 | do {
618 | //long int now = micros();
619 | FastLED.show(); // Display whats rendered.
620 | //long int later = micros();
621 | //DBG_OUTPUT_PORT.printf("Show time is %ld\n", later-now);
622 | server.handleClient(); // Handle requests to the web server
623 | webSocket.loop(); // Handle websocket traffic
624 | ArduinoOTA.handle(); // Handle OTA requests.
625 | #ifdef REMOTE_DEBUG
626 | Debug.handle(); // Handle telnet server
627 | #endif
628 | yield(); // Yield for ESP8266 stuff
629 |
630 | if (WiFi.status() != WL_CONNECTED) {
631 | // Blink the LED quickly to indicate WiFi connection lost.
632 | ticker.attach(0.1, tick);
633 |
634 | //EVERY_N_MILLISECONDS(1000) {
635 | // int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
636 | // digitalWrite(LED_BUILTIN, !state);
637 | // }
638 | } else {
639 | ticker.detach();
640 | // Light on-steady indicating WiFi is connected.
641 | //digitalWrite(LED_BUILTIN, false);
642 | }
643 |
644 | } while (millis() < continueTime);
645 |
646 |
647 | }
648 |
649 | void nextPattern() {
650 | // add one to the current pattern number, and wrap around at the end
651 | // gCurrentPatternNumber = (gCurrentPatternNumber + random(0,
652 | // ARRAY_SIZE(gPatterns))) % ARRAY_SIZE( gPatterns);
653 | gCurrentPatternNumber = random(0, ARRAY_SIZE(gPatterns));
654 | lastMillis = millis();
655 | }
656 |
--------------------------------------------------------------------------------
/colormodes.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 @jake-b, @russp81, @toblum
2 | // Griswold LED Lighting Controller
3 |
4 | // Griswold is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU Lesser General Public License as
6 | // published by the Free Software Foundation, either version 3 of
7 | // the License, or (at your option) any later version.
8 |
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 |
14 | // You should have received a copy of the GNU Lesser General Public License
15 | // along with this program. If not, see .
16 |
17 | // Griswold is a fork of the LEDLAMP project at
18 | // https://github.com/russp81/LEDLAMP_FASTLEDs
19 |
20 | // The LEDLAMP project is a fork of the McLighting Project at
21 | // https://github.com/toblum/McLighting
22 |
23 | // ***************************************************************************
24 | // Color modes
25 | // ***************************************************************************
26 | //#include "definitions.h"
27 |
28 | char* listStatusJSON();
29 |
30 | extern WebSocketsServer webSocket;
31 |
32 | // These functions originally displayed the color using a call to FastLed.show()
33 | // This has been refactored out, theser functions now simply render into the
34 | // leds[] array. The FastLed.show() call happens in the main loop now.
35 | // Furthermore, the 'add glitter' option also refactored out to the main loop.
36 |
37 | void addGlitter(fract8 chanceOfGlitter) {
38 | if (random8() < chanceOfGlitter) {
39 | leds[random16(settings.num_leds)] +=
40 | CRGB(settings.glitter_color.red, settings.glitter_color.green,
41 | settings.glitter_color.blue);
42 | }
43 | }
44 |
45 | void rainbow() {
46 | // FastLED's built-in rainbow generator
47 | fill_rainbow(leds, settings.num_leds, gHue, 7);
48 |
49 | // if (settings.glitter_on == true){addGlitter(settings.glitter_density);}
50 | // frame has been created, now show it
51 | // FastLED.show();
52 | // insert a delay to keep the framerate modest
53 | // FastLED.delay(int(float(500/settings.fps)));
54 | }
55 |
56 | void confetti() {
57 | // random colored speckles that blink in and fade smoothly
58 | fadeToBlackBy(leds, settings.num_leds, settings.ftb_speed);
59 | for (int x=0; x endingLEDIndex) return; //stop condition
124 |
125 | // leds[i] = ColorFromPalette( currentPalette, colorIndex + sin8(i*16),
126 | // brightness);
127 | leds[i] = ColorFromPalette(palette, colorIndex,
128 | settings.effect_brightness);
129 | if (anim_direction == FORWARD) {
130 | colorIndex += 3;
131 | }
132 | if (anim_direction == BACK) {
133 | colorIndex -= 3;
134 | }
135 | }
136 | }
137 |
138 | void ChangePalettePeriodically(bool forceNow) {
139 | if (forceNow || millis() - paletteMillis > (settings.show_length * 1000)) {
140 | paletteMillis = millis();
141 |
142 | targetPaletteIndex = random(0, paletteCount);
143 |
144 | currentPalette = targetPalette;
145 |
146 | anim_direction = (DIRECTION)!anim_direction; // DIRECTION enum allows flipping by boolean not.
147 |
148 | loadPaletteFromFile(targetPaletteIndex, &targetPalette);
149 |
150 | DBG_OUTPUT_PORT.printf("New pallet index: %d\n", targetPaletteIndex);
151 |
152 | if (settings.glitter_wipe_on) {
153 | DBG_OUTPUT_PORT.println("Begin glitter wipe");
154 | wipeInProgress = true;
155 | }
156 | }
157 | }
158 |
159 | void colorWipe() {
160 | static CRGB prevColor = CHSV(gHue, 255, settings.effect_brightness);
161 | static CRGB currentColor = CHSV(gHue+60, 255, settings.effect_brightness);
162 |
163 | // Wrap around if necessary
164 | if (wipePos >= settings.num_leds) {
165 | wipePos = 0;
166 | prevColor = currentColor;
167 | gHue += 60;
168 | currentColor = CHSV(gHue, 255, settings.effect_brightness);
169 | }
170 |
171 | // Render the first half of the wipe
172 | for (int x=0; x= 0 && speckle < settings.num_leds) {
185 | leds[speckle] += CRGB(settings.glitter_color.red, settings.glitter_color.green,
186 | settings.glitter_color.blue);
187 | }
188 | }
189 | }
190 |
191 | // Advance for next frame
192 | wipePos+=WIPE_SPEED;
193 | }
194 |
195 | void palette_anims() {
196 | currentBlending = LINEARBLEND;
197 |
198 | if (settings.palette_ndx == -1) ChangePalettePeriodically(false);
199 |
200 | if (!settings.glitter_wipe_on) {
201 | uint8_t maxChanges = int(float(settings.fps / 2));
202 | nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);
203 |
204 | // Update the current palette if necessary-- and send to any connected clients.
205 | if (currentPaletteIndex != targetPaletteIndex) {
206 | currentPaletteIndex = targetPaletteIndex;
207 |
208 | // Send current palette name to the UI.
209 | String name = getPaletteNameWithIndex(currentPaletteIndex);
210 | webSocket.broadcastTXT("p"+name);
211 | }
212 | }
213 |
214 | static uint8_t startIndex = 0;
215 |
216 | /* motion speed */
217 | startIndex = startIndex + 3;
218 |
219 | FillLEDsFromPaletteColors(currentPalette,startIndex);
220 |
221 | if (settings.glitter_wipe_on && wipeInProgress) {
222 | if (wipePos >= settings.num_leds) {
223 | DBG_OUTPUT_PORT.println("End glitter wipe");
224 | wipeInProgress = false;
225 | wipePos = 0;
226 | currentPalette = targetPalette;
227 | currentPaletteIndex = targetPaletteIndex;
228 |
229 | // Send current palette name to the UI.
230 | String name = getPaletteNameWithIndex(currentPaletteIndex);
231 | webSocket.broadcastTXT("p"+name);
232 | FillLEDsFromPaletteColors(targetPalette,startIndex);
233 | } else {
234 | FillLEDsFromPaletteColors(targetPalette,startIndex, wipePos);
235 | for (int x=0; x < 3; x++) {
236 | int speckle = wipePos + random(-SPARKLE_SPREAD,SPARKLE_SPREAD);
237 | if (speckle >= 0 && speckle < settings.num_leds) {
238 | leds[speckle] += CRGB(settings.glitter_color.red, settings.glitter_color.green,
239 | settings.glitter_color.blue);
240 | }
241 | }
242 | wipePos+=WIPE_SPEED;
243 | }
244 | }
245 |
246 |
247 | }
248 |
249 | //*****************LED RIPPLE*****************************************************
250 |
251 | void one_color_allHSV(int ahue,
252 | int abright) { // SET ALL LEDS TO ONE COLOR (HSV)
253 | for (int i = 0; i < settings.num_leds; i++) {
254 | leds[i] = CHSV(ahue, 255, abright);
255 | }
256 | }
257 |
258 | int wrap(int step) {
259 | if (step < 0) return settings.num_leds + step;
260 | if (step > settings.num_leds - 1) return step - settings.num_leds;
261 | return step;
262 | }
263 |
264 | void ripple() {
265 | if (currentBg == nextBg) {
266 | nextBg = random(256);
267 | } else if (nextBg > currentBg) {
268 | currentBg++;
269 | } else {
270 | currentBg--;
271 | }
272 | for (uint16_t l = 0; l < settings.num_leds; l++) {
273 | leds[l] = CHSV(currentBg, 255,
274 | settings.effect_brightness); // strip.setPixelColor(l,
275 | // Wheel(currentBg, 0.1));
276 | }
277 |
278 | if (step == -1) {
279 | center = random(settings.num_leds);
280 | color = random(256);
281 | step = 0;
282 | }
283 |
284 | if (step == 0) {
285 | leds[center] = CHSV(
286 | color, 255, settings.effect_brightness); // strip.setPixelColor(center,
287 | // Wheel(color, 1));
288 | step++;
289 | } else {
290 | if (step < maxSteps) {
291 | //Serial.println(pow(fadeRate, step));
292 |
293 | leds[wrap(center + step)] =
294 | CHSV(color, 255,
295 | pow(fadeRate, step) * 255); // strip.setPixelColor(wrap(center
296 | // + step), Wheel(color,
297 | // pow(fadeRate, step)));
298 | leds[wrap(center - step)] =
299 | CHSV(color, 255,
300 | pow(fadeRate, step) * 255); // strip.setPixelColor(wrap(center
301 | // - step), Wheel(color,
302 | // pow(fadeRate, step)));
303 | if (step > 3) {
304 | leds[wrap(center + step - 3)] =
305 | CHSV(color, 255, pow(fadeRate, step - 2) *
306 | 255); // strip.setPixelColor(wrap(center +
307 | // step - 3), Wheel(color,
308 | // pow(fadeRate, step - 2)));
309 | leds[wrap(center - step + 3)] =
310 | CHSV(color, 255, pow(fadeRate, step - 2) *
311 | 255); // strip.setPixelColor(wrap(center -
312 | // step + 3), Wheel(color,
313 | // pow(fadeRate, step - 2)));
314 | }
315 | step++;
316 | } else {
317 | step = -1;
318 | }
319 | }
320 | // if (settings.glitter_on == true){addGlitter(settings.glitter_density);}
321 |
322 | // frame has been created, now show it
323 | // FastLED.show();
324 | // insert a delay to keep the framerate modest
325 | // FastLED.delay(int(float(1000/settings.fps)));
326 | }
327 |
328 | //***************************END LED
329 | //RIPPLE*****************************************************
330 |
331 | void comet() {
332 | fadeToBlackBy(leds, settings.num_leds, settings.ftb_speed);
333 | lead_dot = beatsin16(int(float(settings.fps / 3)), 0, settings.num_leds);
334 | leds[lead_dot] = CHSV(dothue, 200, 255);
335 | dothue += 8;
336 | // if (settings.glitter_on == true){addGlitter(settings.glitter_density);}
337 | // FastLED.show();
338 | }
339 |
340 | // Theatre-style crawling lights.
341 | void theaterChase() {
342 | static int8_t frame = 0;
343 |
344 | // turn off the previous frame's led
345 | for (int i = 0; i < settings.num_leds; i = i + 3) {
346 | if (i + frame < settings.num_leds) {
347 | leds[i + frame] = CRGB(0, 0, 0); // turn every third pixel off
348 | }
349 | }
350 |
351 | // advance the frame
352 | frame++;
353 | if (frame > 2) frame = 0;
354 |
355 | // turn on the current frame's leds
356 | for (int i = 0; i < settings.num_leds; i = i + 3) {
357 | if (i + frame < settings.num_leds) {
358 | leds[i + frame] =
359 | CRGB(settings.main_color.red, settings.main_color.green,
360 | settings.main_color.blue); // turn every third pixel on
361 | }
362 | }
363 | }
364 |
365 |
366 | //***********TV
367 | int dipInterval = 10;
368 | int darkTime = 250;
369 | unsigned long currentDipTime;
370 | unsigned long dipStartTime;
371 | unsigned long currentMillis;
372 | int ledState = LOW;
373 | long previousMillis = 0;
374 | int ledBrightness[NUM_LEDS];
375 | uint16_t ledHue[NUM_LEDS];
376 | int led = 5;
377 | int interval = 2000;
378 | int twitch = 50;
379 | int dipCount = 0;
380 | int analogLevel = 100;
381 | boolean timeToDip = false;
382 |
383 | CRGB hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright) {
384 | // Source: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/
385 | uint8_t temp[5], n = (index >> 8) % 3;
386 | temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255);
387 | temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
388 | temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
389 |
390 | return CRGB(temp[n + 2], temp[n + 1], temp[n]);
391 | }
392 |
393 | void _tvUpdateLed (int led, int brightness) {
394 | ledBrightness[led] = brightness;
395 | for (int i=0; i interval) {
406 | previousMillis = currentMillis;
407 | interval = random(750,4001);//Adjusts the interval for more/less frequent random light changes
408 | twitch = random(40,100);// Twitch provides motion effect but can be a bit much if too high
409 | dipCount++;
410 | }
411 | if (currentMillis-previousMillis dipInterval) {
420 | //DBG_OUTPUT_PORT.println("dip");
421 | timeToDip = true;
422 | dipCount = 0;
423 | dipStartTime = millis();
424 | darkTime = random(50,150);
425 | dipInterval = random(5,250);// cycles of flicker
426 | }
427 | }
428 | } else {
429 | //DBG_OUTPUT_PORT.println("Dip Time");
430 | currentDipTime = millis();
431 | if (currentDipTime - dipStartTime < darkTime) {
432 | for (int i=3; i> 8) % 3, 200, ledBrightness[i]);
452 |
453 | leds[i] = hsb2rgbAN1(ledHue[i], sat, ledBrightness[i]).nscale8_video(flicker);
454 | }
455 | }
456 |
457 | // Fire2012 by Mark Kriegsman, July 2012
458 | // as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
459 | ////
460 | // This basic one-dimensional 'fire' simulation works roughly as follows:
461 | // There's a underlying array of 'heat' cells, that model the temperature
462 | // at each point along the line. Every cycle through the simulation,
463 | // four steps are performed:
464 | // 1) All cells cool down a little bit, losing heat to the air
465 | // 2) The heat from each cell drifts 'up' and diffuses a little
466 | // 3) Sometimes randomly new 'sparks' of heat are added at the bottom
467 | // 4) The heat from each cell is rendered as a color into the leds array
468 | // The heat-to-color mapping uses a black-body radiation approximation.
469 | //
470 | // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
471 | //
472 | // This simulation scales it self a bit depending on settings.num_leds; it should look
473 | // "OK" on anywhere from 20 to 100 LEDs without too much tweaking.
474 | //
475 | // I recommend running this simulation at anywhere from 30-100 frames per second,
476 | // meaning an interframe delay of about 10-35 milliseconds.
477 | //
478 | // Looks best on a high-density LED setup (60+ pixels/meter).
479 | //
480 | //
481 | // There are two main parameters you can play with to control the look and
482 | // feel of your fire: COOLING (used in step 1 above), and SPARKING (used
483 | // in step 3 above).
484 | //
485 | // COOLING: How much does the air cool as it rises?
486 | // Less cooling = taller flames. More cooling = shorter flames.
487 | // Default 55, suggested range 20-100
488 | #define COOLING 80
489 |
490 | // SPARKING: What chance (out of 255) is there that a new spark will be lit?
491 | // Higher chance = more roaring fire. Lower chance = more flickery fire.
492 | // Default 120, suggested range 50-200.
493 | #define SPARKING 60
494 |
495 | bool gReverseDirection = false;
496 |
497 | boolean _firerainbow = false; // used for rainbow mode
498 |
499 |
500 | void fire2012()
501 | {
502 |
503 | // Array of temperature readings at each simulation cell
504 | static byte heat[NUM_LEDS];
505 | static byte heat2[NUM_LEDS];
506 |
507 | // Step 1. Cool down every cell a little
508 | for( int i = 0; i < settings.num_leds; i++) {
509 | //heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / settings.num_leds) + 2)); // original with COOLING
510 | heat[i] = qsub8( heat[i], random8(0, ((settings.ftb_speed * 20) / settings.num_leds) + 2)); // modified with FTBspeed
511 | heat2[i] = qsub8( heat2[i], random8(0, ((settings.ftb_speed * 20) / settings.num_leds) + 2)); // modified with FTBspeed
512 | }
513 |
514 | // Step 2. Heat from each cell drifts 'up' and diffuses a little
515 | for( int k= settings.num_leds - 1; k >= 2; k--) {
516 |
517 | heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
518 | heat2[k] = (heat2[k - 1] + heat2[k - 2] + heat2[k - 2] ) / 3;
519 |
520 | }
521 |
522 | // Step 3. Randomly ignite new 'sparks' of heat near the bottom
523 | // if( random8() < SPARKING ) { // Original with SPARKING
524 | if( random8() < settings.show_length ) { // Modified with show_length
525 | int y = random8(7);
526 | int z = random8(7);
527 | heat[y] = qadd8( heat[y], random8(160,255) );
528 | heat2[z] = qadd8( heat2[z], random8(160,255) );
529 | }
530 |
531 | // Step 4. Map from heat cells to LED colors
532 | for( int j = 0; j < (settings.num_leds / 2); j++) {
533 | CRGB color = HeatColor( heat[j]);
534 | int pixelnumber;
535 | if( gReverseDirection ) {
536 | pixelnumber = (settings.num_leds-1) - j;
537 | } else {
538 | pixelnumber = j;
539 | }
540 | leds[pixelnumber] = color;
541 | }
542 |
543 | // Step 4. Map from heat cells to LED colors
544 | for( int j = 0; j < (settings.num_leds / 2); j++) {
545 | CRGB color = HeatColor( heat2[j]);
546 | int pixelnumber;
547 | pixelnumber = (settings.num_leds-1) - j;
548 | leds[pixelnumber] = color;
549 | }
550 |
551 | if (_firerainbow) {
552 | for( int j = 0; j < (settings.num_leds); j++) {
553 | leds[j] += CHSV(gHue, 255, settings.effect_brightness); // set effect brightness
554 | }
555 | _firerainbow = false;
556 | }
557 |
558 | ////frame has been created, now show it
559 | // FastLED.show();
560 | // // insert a delay to keep the framerate modest
561 | // FastLED.delay(int(float(1000/FPS)));
562 |
563 | }
564 |
565 | void fire_rainbow() {
566 | _firerainbow = true;
567 | fire2012();
568 |
569 | }
570 |
571 |
572 | // Fireworks from WS2812FX
573 |
574 | boolean _singlecolor = false; // used for single color mode
575 | boolean _rainbow = false; // used for rainbow mode
576 |
577 | void fireworks() {
578 |
579 |
580 |
581 | // fadeToBlackBy( leds, settings.num_leds, ftb_speed);
582 |
583 |
584 | uint32_t px_rgb = 0;
585 | byte px_r = 0;
586 | byte px_g = 0;
587 | byte px_b = 0;
588 | byte px_boost = 200;
589 |
590 | for(uint16_t i=0; i < settings.num_leds; i++) {
591 |
592 |
593 |
594 | //leds[i] /= 2; // fade out (divide by 2)
595 | leds[i].nscale8(130 - int(float(settings.ftb_speed*0.5)));
596 | //leds[i].fadeToBlackBy(ftb_speed);
597 |
598 | }
599 |
600 | // first LED has only one neighbour
601 | leds[0].r = (leds[1].r >> 1) + leds[0].r;
602 | leds[0].g = (leds[1].g >> 1) + leds[0].g;
603 | leds[0].b = (leds[1].b >> 1) + leds[0].b;
604 | //leds[0].setRGB(px_r, px_g, px_b);
605 |
606 | // set brightness(i) = ((brightness(i-1)/2 + brightness(i+1)) / 2) + brightness(i)
607 | for(uint16_t i=1; i < settings.num_leds-1; i++) {
608 | leds[i].r = ((
609 | (leds[i-1].r >> 1) +
610 | leds[i+1].r ) >> 1) +
611 | leds[i].r;
612 |
613 | leds[i].g = ((
614 | (leds[i-1].g >> 1) +
615 | leds[i+1].g ) >> 1) +
616 | leds[i].g;
617 |
618 | leds[i].b = ((
619 | (leds[i-1].b >> 1) +
620 | leds[i+1].b ) >> 1) +
621 | leds[i].b;
622 | }
623 |
624 | // last LED has only one neighbour
625 | leds[settings.num_leds-1].r = ((leds[settings.num_leds-2].r >> 2) + leds[settings.num_leds-1].r);
626 | leds[settings.num_leds-1].g = ((leds[settings.num_leds-2].g >> 2) + leds[settings.num_leds-1].g);
627 | leds[settings.num_leds-1].b = ((leds[settings.num_leds-2].b >> 2) + leds[settings.num_leds-1].b);
628 |
629 | px_r = random8();
630 | px_g = random8();
631 | px_b = random8();
632 |
633 |
634 |
635 | for(uint16_t i=0; i<_max(1,settings.num_leds/20); i++) {
636 | if(random8(settings.show_length + 4) == 0) {
637 | //Adafruit_NeoPixel::setPixelColor(random(_led_count), _mode_color);
638 | byte pixel = random(settings.num_leds);
639 | if(_singlecolor){
640 | leds[pixel] = CRGB(settings.main_color.red,settings.main_color.green,settings.main_color.blue); // tails are in single color from set color on web interface
641 | } else if(_rainbow) {
642 | leds[pixel] = CHSV( gHue, 255, settings.effect_brightness); // Rainbow cycling color
643 | } else if(!_singlecolor && !_rainbow) {
644 | leds[pixel].setRGB(px_r, px_g, px_b); // Multicolored tale
645 |
646 | }
647 | leds[pixel].maximizeBrightness();
648 |
649 |
650 |
651 | }
652 | }
653 |
654 | _singlecolor = false;
655 | _rainbow = false;
656 |
657 | // if (GLITTER_ON == true){addGlitter(glitter_density);}
658 | // //frame has been created, now show it
659 | FastLED.show();
660 | // insert a delay to keep the framerate modest
661 | // FastLED.delay(int(float(1000/FPS)));
662 | }
663 |
664 |
665 |
666 | void fw_single() {
667 | _singlecolor = true;
668 | fireworks();
669 | }
670 |
671 | void fw_rainbow() {
672 | _rainbow = true;
673 | fireworks();
674 | }
675 |
676 | // END
677 |
678 |
679 | //*******************************ARRAY OF SHOW ANIMATIONS FOR MIXED SHOW
680 | //MODE***********************
681 | typedef void (*SimplePatternList[])();
682 | SimplePatternList gPatterns = {rainbow, confetti, sinelon, juggle,
683 | bpm, palette_anims, ripple, comet};
684 | //**************************************************************************************************
685 |
--------------------------------------------------------------------------------
/data-moved_aside/color-selector.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Getting colors
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
130 |
131 |