├── ESPixelClock.jpg ├── Instructions.docx ├── README.md ├── compileInstructions.md ├── enclosures ├── ESPixelClockDiffuser1.stl ├── ESPixelClock_diffuser_combo.jpg ├── LightGuide.svg ├── Light_Guide_v5.f3z └── readme.md ├── examples ├── ESPixelClock │ ├── ESPixelClock.ino │ ├── ESPixelClock_timer.jpg │ ├── LICENSE │ ├── Map.h │ ├── Noise.h │ ├── compiled │ │ ├── ESPixelClock.bat │ │ ├── ESPixelClock.ino.bin │ │ ├── ESPixelClock.ino.partitions.bin │ │ └── ESPixelClock.spiffs.bin │ ├── css.7z │ ├── data │ │ ├── _index.htm │ │ ├── css │ │ │ ├── bootstrap.min.css.gz │ │ │ ├── jquery.minicolors.min.css │ │ │ └── jquery.minicolors.min.css.gz │ │ ├── favicon.ico │ │ ├── giticon.svg │ │ ├── index.htm.gz │ │ ├── js │ │ │ ├── app.js.gz │ │ │ ├── bootstrap.min.js.gz │ │ │ ├── jquery-3.1.1.min.js.gz │ │ │ ├── jquery.minicolors.min.js.gz │ │ │ └── reconnecting-websocket.min.js.gz │ │ └── wifi.htm │ ├── esp32fs.jar │ ├── field.h │ ├── fields.h │ ├── fonts.7z │ ├── gradientPalettes.h │ ├── hardware │ │ ├── ESPixel Clock Enclosure Bottom Drawing v1.pdf │ │ ├── ESPixel Clock Enclosure.3mf │ │ └── ESPixel Clock Enclosure.stl │ ├── js.7z │ ├── libspiffs.a │ ├── palettes.h │ ├── patterns.h │ ├── temp.txt │ ├── twinkleFox.h │ ├── web.h │ └── wifi.h ├── matrix_test │ └── Neo7SegmentClock_matrixtest.ino └── simple │ ├── Neo7SegmentClock.ino │ ├── Neo7SegmentCount.ino │ ├── secrets.h │ └── temp.txt └── hardware ├── ESPixelClock_Board.stl ├── Neo7Segment3535-bot.pdf ├── Neo7Segment3535-sch2.pdf ├── Neo7Segment3535-top.pdf ├── Neo7Segment3535.dxf ├── PixelMap.xlsx └── temp.txt /ESPixelClock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/ESPixelClock.jpg -------------------------------------------------------------------------------- /Instructions.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/Instructions.docx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESPixelClock 2 | ![Photo](ESPixelClock.jpg) 3 | Collection of code examples for the ESPixelClock 4 | 5 | [This](https://github.com/mattncsu/ESPixelClock/tree/master/examples/ESPixelClock) is the code that comes pre-flashed on clocks that shipped with an ESP32 attached. 6 | 7 | For those starting off with a bare board, I recommend taking a look at the examples in the [simple](https://github.com/mattncsu/ESPixelClock/tree/master/examples/simple) folder because they'll be easier to adapt to other microcontrollers. 8 | 9 | ESP-ready version is now available on Amazon: https://www.amazon.com/ESPixel-Pixel-Based-Segment-Display-Raspberry/dp/B08TGLGM2F 10 | ESP-32 included version on Amazon: https://www.amazon.com/ESPixel-Clock-Pixel-Based-Segment-Display/dp/B08XQ449VJ 11 | -------------------------------------------------------------------------------- /compileInstructions.md: -------------------------------------------------------------------------------- 1 | This document is intended to describe the steps needed to compile and upload modified firmware to the ESPixelClock 2 | Note that it is currently a work in progress, and may not be comprehensive, but should provide a good starting point at least. 3 | 4 | 5 | Follow these instructions to install the ESP32 boards into the arduino IDE, https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md 6 | 7 | Set the board to "ESP32 Dev module" in the Boards Menu, 8 | 9 | install the required libraries, including (but not necessarily limited to) 10 | - FastLED.h 11 | - AsyncTCP.h 12 | - ESPAsyncWebServer.h 13 | - AsyncElegantOTA.h 14 | - DS3231M.h 15 | - SHT21.h 16 | 17 | Compile code to verify changes, 18 | 19 | Then Go to the _Sketch_ menu > and click _Export Compiled Binary_ 20 | 21 | The web files are stored in the data subdirectory and uploaded to the file system of the clock. To update the files on the clock, use the ESP32 Sketch Data Upload plugin to generate a binary of the spiffs partition. Ignore errors about not being connected. Watch the status messages for the path to the temporary binary files generated. On my machine, they were in C:\Users\\AppData\Local\Temp\arduino_build_299134. 22 | 23 | Upload the .bin file created using the web UI. 24 | 25 | -------------------------------------------------------------------------------- /enclosures/ESPixelClockDiffuser1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/enclosures/ESPixelClockDiffuser1.stl -------------------------------------------------------------------------------- /enclosures/ESPixelClock_diffuser_combo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/enclosures/ESPixelClock_diffuser_combo.jpg -------------------------------------------------------------------------------- /enclosures/LightGuide.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 63 | 67 | 71 | 75 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 107 | 111 | 115 | 119 | 123 | 127 | 131 | 135 | 139 | 143 | 147 | 151 | 155 | 159 | 163 | 167 | 171 | 175 | 179 | 183 | 187 | 191 | 195 | 199 | 203 | 207 | 211 | 215 | 219 | 223 | 227 | 231 | 235 | 239 | 243 | 247 | 251 | 255 | 259 | 263 | 267 | 271 | 275 | 279 | 283 | 287 | 291 | 295 | 299 | 303 | 307 | 311 | 315 | 319 | 323 | 327 | 331 | 335 | 339 | 343 | 347 | 351 | 355 | 359 | 363 | 367 | 371 | 375 | 379 | 383 | 387 | 391 | 395 | 399 | 403 | 407 | 411 | 415 | 419 | 423 | 427 | 431 | 435 | 439 | 443 | 447 | 451 | 455 | 459 | 463 | 467 | 471 | 475 | 479 | 483 | 487 | 491 | 495 | 499 | 503 | 507 | 511 | 515 | 519 | 523 | 527 | 531 | 535 | 539 | 543 | 547 | 551 | 555 | 559 | 563 | 567 | 571 | 572 | 573 | -------------------------------------------------------------------------------- /enclosures/Light_Guide_v5.f3z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/enclosures/Light_Guide_v5.f3z -------------------------------------------------------------------------------- /enclosures/readme.md: -------------------------------------------------------------------------------- 1 | Here is a place to post cases, enclosures, and other miscellaneous bits. 2 | 3 | [DXF](hardware/Neo7Segment3535.dxf) and [STL](hardware/ESPixelClock_Board.stl) files are posted in the hardware folder to facilitate new designs. 4 | 5 | [Light Diffuser](https://www.thingiverse.com/thing:4218698): This offsets the LEDs from the opaqe screen a bit causing the individual pixels to blur together: 6 | ![diffuser](ESPixelClock_diffuser_combo.jpg) 7 | 8 | [Simple Enclosure](https://www.thingiverse.com/thing:4145818): Simple enclosure design by Jason Coon: 9 | ![photo](https://cdn.thingiverse.com/assets/8a/95/cd/cb/06/featured_preview_IMG_20200113_201147830.jpg) 10 | 11 | [ESPixelClock Case](https://www.thingiverse.com/thing:4355887): Nice design by Tedder: 12 | ![photo](https://cdn.thingiverse.com/assets/db/9c/6e/50/e2/featured_preview_2020-05-11_09.59.41.jpg) 13 | -------------------------------------------------------------------------------- /examples/ESPixelClock/ESPixelClock.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ESPixelClock 3 | https://github.com/mattncsu/ESPixelClock 4 | 5 | 6 | 7 | 8 | 9 | Timezone codes from: https://github.com/jdlambert/micro_tz_db 10 | Based on: 11 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 12 | Copyright (C) 2017 Jason Coon 13 | 14 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 15 | https://github.com/FastLED/FastLED 16 | 17 | ESP32 support provided by the hard work of Sam Guyer: 18 | https://github.com/samguyer/FastLED 19 | 20 | This program is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | This program is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with this program. If not, see . 32 | */ 33 | 34 | #include 35 | #include 36 | #include "esp_wifi.h" 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include //https://github.com/SV-Zanshin/DS3231M 47 | #include //https://github.com/markbeee/SHT21 48 | DS3231M_Class DS3231M; 49 | SHT21 SHT21; 50 | wifi_sta_list_t stationList; //Used to determine if anyone connected to softAP 51 | Preferences preferences; 52 | AsyncWebServer server(80); //for the update server 53 | 54 | #if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001008) 55 | #warning "Requires FastLED 3.1.8 or later; check github for latest code." 56 | #endif 57 | 58 | String ssid,password,tzInfo,ntpServer1,ntpServer2,clockName; 59 | 60 | int8_t timezoneOffset = -6; // Central Time 61 | bool tzChanged=false; 62 | int8_t temperatureOffset = 0; 63 | long gmtOffset_sec = timezoneOffset * 3600; 64 | const int daylightOffset_sec = 3600; 65 | 66 | int16_t timeInt = 8888; // keeps track of what number to display 67 | bool colon = false; 68 | bool timerMode,countdownMode; 69 | int16_t countdown; 70 | long startTime; 71 | float temp,rh; 72 | DateTime now; 73 | 74 | #define LED_PIN 27 //LED from lighted switch 75 | #define BTN_PIN 32 //Push button to start stop watch mode 76 | #define IDLE_TIME 5*60*1000 //terminate stop watch mode after 5 minutes 77 | 78 | uint8_t autoplay = 0; 79 | uint8_t autoplayDuration = 10; 80 | unsigned long autoPlayTimeout = 0; 81 | 82 | uint8_t currentPatternIndex = 0; // Index number of which pattern is current 83 | 84 | uint8_t gHue = 0; // rotating "base color" used by many of the patterns 85 | 86 | uint8_t power = 1; 87 | uint8_t leadingZeroEnabled = 1; 88 | uint8_t blinkingColonEnabled = 1; 89 | uint8_t time24 = 1; 90 | uint8_t brightness = 8; 91 | 92 | uint8_t speed = 30; 93 | 94 | // COOLING: How much does the air cool as it rises? 95 | // Less cooling = taller flames. More cooling = shorter flames. 96 | // Default 50, suggested range 20-100 97 | uint8_t cooling = 50; 98 | 99 | // SPARKING: What chance (out of 255) is there that a new spark will be lit? 100 | // Higher chance = more roaring fire. Lower chance = more flickery fire. 101 | // Default 120, suggested range 50-200. 102 | uint8_t sparking = 120; 103 | 104 | CRGB solidColor = CRGB::Blue; 105 | 106 | uint8_t cyclePalettes = 0; 107 | uint8_t paletteDuration = 10; 108 | uint8_t currentPaletteIndex = 3; 109 | unsigned long paletteTimeout = 0; 110 | 111 | #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) 112 | 113 | #define DATA_PIN 18 114 | #define LED_TYPE WS2812B 115 | #define COLOR_ORDER GRB 116 | #define NUM_LEDS 86 117 | CRGBArray leds; 118 | 119 | #define MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA) 120 | #define FRAMES_PER_SECOND 60 121 | 122 | #include "patterns.h" 123 | #include "field.h" 124 | #include "fields.h" 125 | 126 | 127 | #include "wifi.h" 128 | #include "web.h" 129 | 130 | // wifi ssid and password should be added to a file in the sketch named secrets.h 131 | // the secrets.h file should be added to the .gitignore file and never committed or 132 | // pushed to public source control (GitHub). 133 | // const char* ssid = "........"; 134 | // const char* password = "........"; 135 | 136 | struct Button { 137 | const uint8_t PIN; 138 | bool pressed; 139 | }; 140 | Button button1 = {BTN_PIN, false}; 141 | 142 | void IRAM_ATTR isr(void* arg) { 143 | static unsigned long last_interrupt_time = 0; 144 | unsigned long interrupt_time = millis(); 145 | // If interrupts come faster than 200ms, assume it's a bounce and ignore 146 | if (interrupt_time - last_interrupt_time > 200) 147 | { 148 | Button* s = static_cast(arg); 149 | s->pressed = true; 150 | } 151 | last_interrupt_time = interrupt_time; 152 | 153 | } 154 | 155 | void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { 156 | Serial.printf("Listing directory: %s\n", dirname); 157 | 158 | File root = fs.open(dirname); 159 | if (!root) { 160 | Serial.println("Failed to open directory"); 161 | return; 162 | } 163 | if (!root.isDirectory()) { 164 | Serial.println("Not a directory"); 165 | return; 166 | } 167 | 168 | File file = root.openNextFile(); 169 | while (file) { 170 | if (file.isDirectory()) { 171 | Serial.print(" DIR : "); 172 | Serial.println(file.name()); 173 | if (levels) { 174 | listDir(fs, file.name(), levels - 1); 175 | } 176 | } else { 177 | Serial.print(" FILE: "); 178 | Serial.print(file.name()); 179 | Serial.print(" SIZE: "); 180 | Serial.println(file.size()); 181 | } 182 | file = root.openNextFile(); 183 | } 184 | } 185 | 186 | void printLocalTime() 187 | { 188 | 189 | setenv("TZ", tzInfo.c_str(), 1); 190 | tzset(); 191 | now = DS3231M.now(); 192 | 193 | //struct tm timeinfo; 194 | 195 | Serial.printf("%04d-%02d-%02d %02d:%02d:%02d Temp: %.1fC RH:%.1f%% %s\n", now.year(), // Use sprintf() to pretty print // 196 | now.month(), now.day(), now.hour(), now.minute(), now.second(), 197 | temp, rh, tzInfo.c_str()); 198 | if (time24 == 0){ 199 | if (now.hour() > 12){ 200 | timeInt = (now.hour()-12)*100+now.minute(); 201 | } 202 | else{ 203 | timeInt = now.hour()*100+now.minute(); 204 | } 205 | } 206 | else{ 207 | timeInt = now.hour()*100+now.minute(); 208 | } 209 | } 210 | 211 | void getNTPTime(){ 212 | if ( WiFi.status() == WL_CONNECTED) { 213 | Serial.println("Getting NTP Time..."); 214 | configTzTime(tzInfo.c_str(), ntpServer1.c_str(), ntpServer2.c_str()); //get fresh NTP time 215 | struct tm timeinfo; 216 | if(!getLocalTime(&timeinfo)){ 217 | Serial.println("Failed to obtain NTP time"); 218 | return; 219 | } 220 | Serial.println(&timeinfo, "NTP Time: %A, %B %d %Y %H:%M:%S"); 221 | int hour = timeinfo.tm_hour; 222 | int minute = timeinfo.tm_min; 223 | int second = timeinfo.tm_sec; 224 | int day = timeinfo.tm_mday; 225 | int month = timeinfo.tm_mon + 1; 226 | int year = timeinfo.tm_year +1900; 227 | DS3231M.adjust(DateTime(year,month,day,hour,minute,second)); // Adjust the RTC date/time 228 | Serial.print(F("RTC time/date has been set.\n")); 229 | 230 | } else { 231 | Serial.println("Can't get NTP time without WiFi..."); 232 | } 233 | } 234 | 235 | 236 | void setup() { 237 | pinMode(button1.PIN,INPUT_PULLUP); 238 | attachInterruptArg(button1.PIN, isr, &button1, FALLING); 239 | pinMode(LED_PIN, OUTPUT); 240 | 241 | Serial.begin(115200); 242 | Serial.println("Reading data from EEPROM..."); 243 | 244 | preferences.begin("ESPixelClock", true); 245 | ssid = preferences.getString("ssid", "none"); //NVS key ssid,default="none" 246 | Serial.printf(" SSID: %s\n",ssid.c_str()); 247 | password = preferences.getString("password", "none"); //NVS key password,default="none" 248 | Serial.printf(" WiFi pass: %s\n","*****"); 249 | tzInfo = preferences.getString("timezone", "EST5EDT,M3.2.0,M11.1.0"); //load eastern time if no tz stored 250 | Serial.printf(" Timezone: %s\n",tzInfo.c_str()); 251 | ntpServer1 = preferences.getString("ntpServer1", "time.google.com"); 252 | Serial.printf(" ntpServer1: %s\n",ntpServer1.c_str()); 253 | ntpServer2 = preferences.getString("ntpServer2", "pool.ntp.org"); 254 | Serial.printf(" ntpServer2: %s\n",ntpServer2.c_str()); 255 | clockName = preferences.getString("clockName", "ESPixelClock"); 256 | preferences.end(); 257 | Serial.println("Done loading data from EEPROM"); 258 | 259 | if (DS3231M.begin()){ 260 | Serial.print(F("DS3231M found!\n")); 261 | printLocalTime(); 262 | } 263 | else { 264 | Serial.print(F("DS3231M not found, moving on...\n")); 265 | } 266 | SHT21.begin(); 267 | 268 | SPIFFS.begin(); 269 | listDir(SPIFFS, "/", 1); 270 | 271 | FastLED.addLeds(leds, NUM_LEDS); 272 | FastLED.setCorrection(TypicalSMD5050); 273 | FastLED.setMaxPowerInVoltsAndMilliamps(5, MILLI_AMPS); 274 | 275 | // set master brightness control 276 | FastLED.setBrightness(brightness); 277 | fill_rainbow( leds, NUM_LEDS, gHue, speed); 278 | FastLED.show(); 279 | FastLED.delay(250); 280 | autoPlayTimeout = millis() + (autoplayDuration * 1000); 281 | 282 | loadFieldsFromEEPROM(fields, fieldCount); 283 | setupWifi(); 284 | setupWeb(); 285 | AsyncElegantOTA.begin(&server); // Start ElegantOTA 286 | server.begin(); 287 | Serial.println("HTTP server started on port 80"); 288 | getNTPTime(); //get initial time 289 | temp = SHT21.getTemperature()+temperatureOffset; //get inital temp reading 290 | rh = SHT21.getHumidity(); 291 | } 292 | 293 | void maskTime(int timeInt){ 294 | // Based on the current timeInt set number segments on or off 295 | uint8_t c1 = 0; // Variable to store 1s digit 296 | uint8_t c10 = 0; // Variable to store 10s digit 297 | uint8_t c100 = 0; // Variable to store 100s digit 298 | uint8_t c1000 = 0; // Variable to store 100s digit 299 | int c; 300 | 301 | c1 = timeInt % 10; 302 | c10 = (timeInt / 10) % 10; 303 | c100 = (timeInt / 100) % 10; 304 | c1000 = (timeInt / 1000) % 10; 305 | 306 | CRGB color = CRGB::Black; //unused segment color 307 | 308 | //next block of if statements sets segments to black to form digits 309 | if (c1000 == 0) { 310 | if (leadingZeroEnabled==1){ //set leading value to black if zero 311 | seg1G = color; 312 | } else { 313 | seg1A = seg1B = seg1C = seg1D = seg1E = seg1F = seg1G = color; 314 | } 315 | } 316 | if (c1000 == 1) { seg1A = seg1D = seg1E = seg1F = seg1G = color; } 317 | if (c1000 == 2) { seg1C = seg1F = color; } 318 | if (c1000 == 3) { seg1E = seg1F = color; } 319 | if (c1000 == 4) { seg1A = seg1D = seg1E = color; } 320 | if (c1000 == 5) { seg1B = seg1E = color; } 321 | if (c1000 == 6) { seg1B = color; } //B 322 | if (c1000 == 7) { seg1D = seg1E = seg1F = seg1G = color; } 323 | if (c1000 == 8) { } 324 | if (c1000 == 9) { seg1D = seg1E = color; } 325 | 326 | if (c100 == 0) { seg2G = color; } 327 | if (c100 == 1) { seg2A = seg2D = seg2E = seg2F = seg2G = color; } 328 | if (c100 == 2) { seg2C = seg2F = color; } 329 | if (c100 == 3) { seg2E = seg2F = color; } 330 | if (c100 == 4) { seg2A = seg2D = seg2E = color; } 331 | if (c100 == 5) { seg2B = seg2E = color; } 332 | if (c100 == 6) { seg2B = color; } //B 333 | if (c100 == 7) { seg2D = seg2E = seg2F = seg2G = color; } 334 | if (c100 == 8) { } 335 | if (c100 == 9) { seg2D = seg2E = color; } 336 | 337 | if (c10 == 0) { seg3G = color; } 338 | if (c10 == 1) { seg3A = seg3D = seg3E = seg3F = seg3G = color; } 339 | if (c10 == 2) { seg3C = seg3F = color; } 340 | if (c10 == 3) { seg3E = seg3F = color; } 341 | if (c10 == 4) { seg3A = seg3D = seg3E = color; } 342 | if (c10 == 5) { seg3B = seg3E = color; } 343 | if (c10 == 6) { seg3B = color; } //B 344 | if (c10 == 7) { seg3D = seg3E = seg3F = seg3G = color; } 345 | if (c10 == 8) { } 346 | if (c10 == 9) { seg3D = seg3E = color; } 347 | 348 | if (c1 == 0) { seg4G = color; } 349 | if (c1 == 1) { seg4A = seg4D = seg4E = seg4F = seg4G = color; } 350 | if (c1 == 2) { seg4C = seg4F = color; } 351 | if (c1 == 3) { seg4E = seg4F = color; } 352 | if (c1 == 4) { seg4A = seg4D = seg4E = color; } 353 | if (c1 == 5) { seg4B = seg4E = color; } 354 | if (c1 == 6) { seg4B = color; } //B 355 | if (c1 == 7) { seg4D = seg4E = seg4F = seg4G = color; } 356 | if (c1 == 8) { } 357 | if (c1 == 9) { seg4D = seg4E = color; } 358 | 359 | if (!colon && blinkingColonEnabled == 1){ 360 | col = CRGB::Black; //turns off colon to make it blink 361 | } 362 | if (timerMode){ 363 | if (millis() - startTime <99000){ 364 | leds[84]=CRGB::Black; //convert colon to decimal if timer < 99 seconds 365 | } 366 | } 367 | } 368 | 369 | void nextPattern() 370 | { 371 | // add one to the current pattern number, and wrap around at the end 372 | currentPatternIndex = (currentPatternIndex + 1) % patternCount; 373 | } 374 | 375 | void nextPalette() 376 | { 377 | currentPaletteIndex = (currentPaletteIndex + 1) % paletteCount; 378 | targetPalette = palettes[currentPaletteIndex]; 379 | } 380 | 381 | void loop() 382 | { 383 | //handleWeb(); 384 | AsyncElegantOTA.loop(); 385 | if (button1.pressed) { 386 | Serial.printf("Button 1 has been pressed\n"); 387 | button1.pressed = false; 388 | if (!timerMode){ 389 | countdownMode=true; 390 | countdown=10; 391 | digitalWrite(LED_PIN,HIGH); 392 | } else { 393 | digitalWrite(LED_PIN,LOW); 394 | FastLED.delay(15000); 395 | timerMode=false; 396 | } 397 | } 398 | 399 | if (power == 0) { 400 | fill_solid(leds, NUM_LEDS, CRGB::Black); 401 | } 402 | else { 403 | // Call the current pattern function once, updating the 'leds' array 404 | patterns[currentPatternIndex].pattern(); 405 | maskTime(timeInt); 406 | 407 | EVERY_N_MILLISECONDS(40) { 408 | // slowly blend the current palette to the next 409 | nblendPaletteTowardPalette(currentPalette, targetPalette, 8); 410 | gHue++; // slowly cycle the "base color" through the rainbow 411 | } 412 | 413 | if (autoplay == 1 && (millis() > autoPlayTimeout)) { 414 | nextPattern(); 415 | autoPlayTimeout = millis() + (autoplayDuration * 1000); 416 | } 417 | 418 | if (cyclePalettes == 1 && (millis() > paletteTimeout)) { 419 | nextPalette(); 420 | paletteTimeout = millis() + (paletteDuration * 1000); 421 | } 422 | } 423 | 424 | // send the 'leds' array out to the actual LED strip 425 | FastLED.show(); 426 | 427 | // insert a delay to keep the framerate modest 428 | // delay(1000 / FRAMES_PER_SECOND); 429 | FastLED.delay(1000 / FRAMES_PER_SECOND); 430 | 431 | // time stuff 432 | EVERY_N_SECONDS(1){ 433 | colon = !colon; // flash the colon 434 | } 435 | 436 | // EVERY_N_SECONDS(120){ //UNCOMMENT TO TEST THE PUSH BUTTON ISR THAT STARTS TIMER MODE AFTER 2 MINUTES 437 | // static unsigned long last_interrupt_time = 0; 438 | // unsigned long interrupt_time = millis(); 439 | // // If interrupts come faster than 200ms, assume it's a bounce and ignore 440 | // if (interrupt_time - last_interrupt_time > 200) 441 | // { 442 | // Button* s = static_cast(&button1); 443 | // s->pressed = true; 444 | // } 445 | // last_interrupt_time = interrupt_time; 446 | // } 447 | 448 | EVERY_N_MILLISECONDS(1000){ 449 | 450 | if(countdownMode && countdown==0){ //check if countdown is over, if so, start stopwatch 451 | countdownMode=false; 452 | timerMode=true; 453 | startTime=millis(); 454 | timeInt=0; 455 | } 456 | if(countdownMode){ 457 | countdown--; 458 | } 459 | } 460 | 461 | EVERY_N_MILLISECONDS(10){ 462 | int x = millis() - startTime; 463 | if (countdownMode){ 464 | timeInt=countdown; 465 | } 466 | if (timerMode){ //show stopwatch on clock as xx.xx up to 99 seconds 467 | if(x < 99000){ 468 | timeInt=(x)/10; 469 | colon=true; 470 | 471 | } 472 | else{ 473 | timeInt = (x/1000/60)*100 + (x/1000) % 60; //show stopwatch in mm:ss until IDLE_TIME reached 474 | } 475 | if (millis()-startTime>IDLE_TIME){ //revert back to a clock mode 476 | timerMode=false; 477 | } 478 | } 479 | } 480 | 481 | EVERY_N_MILLISECONDS(250){ //flash LED in stopwatch mode 482 | if (timerMode){ 483 | digitalWrite(LED_PIN,(!digitalRead(LED_PIN))); 484 | } 485 | } 486 | 487 | EVERY_N_SECONDS(5){ //refesh display every 5 seconds 488 | if (!timerMode && !countdownMode){ 489 | printLocalTime(); 490 | } 491 | } 492 | 493 | EVERY_N_HOURS(12){ //get NTP time every 12 hours, clock relies on RTC with <5ppm drift to keep time between intervals (<15 sec/month at normal temperatures) 494 | getNTPTime(); //get fresh NTP time 495 | } 496 | if (tzChanged){ 497 | getNTPTime(); 498 | Serial.println("tz changed"); 499 | tzChanged=false; 500 | } 501 | 502 | EVERY_N_MINUTES(5){ //I2C reading causes studder in pattern 503 | temp = SHT21.getTemperature()+temperatureOffset; 504 | rh = SHT21.getHumidity(); 505 | } 506 | 507 | } 508 | -------------------------------------------------------------------------------- /examples/ESPixelClock/ESPixelClock_timer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/ESPixelClock_timer.jpg -------------------------------------------------------------------------------- /examples/ESPixelClock/Map.h: -------------------------------------------------------------------------------- 1 | uint8_t pps = 3; // number of Pixels Per Segment 2 | CHSV segBlack(0,0,0); //black 3 | 4 | // Name segments and define pixel ranges. 5 | // 1....2....3....4 6 | // AAA 7 | // F B 8 | // GGG 9 | // E C 10 | // DDD 11 | 12 | //PCB Layout: 13 | // .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 10 11.12 13 14 15 16 17 18 19 20 21 22 23 24 14 | // 0 .. .0 .1 .2 .. .. .. 21 22 23 .. .. .. .. .. 42 43 44 .. .. .. 63 64 65 .. 15 | // 1 17 .. .. .. .3 .. 38 .. .. .. 24 .. .. .. 59 .. .. .. 45 .. 80 .. .. .. 66 16 | // 2 16 .. .. .. .4 .. 37 .. .. .. 25 .. 84 .. 58 .. .. .. 46 .. 79 .. .. .. 67 17 | // 3 15 .. .. .. .5 .. 36 .. .. .. 26 .. .. .. 57 .. .. .. 47 .. 78 .. .. .. 68 18 | // 4 .. 18 19 20 .. .. .. 39 40 41 .. .. .. .. .. 60 61 62 .. .. .. 81 82 83 .. 19 | // 5 14 .. .. .. .6 .. 35 .. .. .. 27 .. .. .. 56 .. .. .. 48 .. 77 .. .. .. 69 20 | // 6 13 .. .. .. .7 .. 34 .. .. .. 28 .. 85 .. 55 .. .. .. 49 .. 76 .. .. .. 70 21 | // 7 12 .. .. .. .8 .. 33 .. .. .. 29 .. .. .. 54 .. .. .. 50 .. 75 .. .. .. 71 22 | // 8 .. 11 10 .9 .. .. .. 32 31 30 .. .. .. .. .. 53 52 51 .. .. .. 74 73 72 .. 23 | 24 | CRGBSet seg1A( leds(pps*0, pps-1+(pps*0) )); 25 | CRGBSet seg1B( leds(pps*1, pps-1+(pps*1) )); 26 | CRGBSet seg1C( leds(pps*2, pps-1+(pps*2) )); 27 | CRGBSet seg1D( leds(pps*3, pps-1+(pps*3) )); 28 | CRGBSet seg1E( leds(pps*4, pps-1+(pps*4) )); 29 | CRGBSet seg1F( leds(pps*5, pps-1+(pps*5) )); 30 | CRGBSet seg1G( leds(pps*6, pps-1+(pps*6) )); 31 | 32 | CRGBSet seg2A( leds(pps*0+(1*7*pps), pps-1+(pps*0)+(1*7*pps) )); 33 | CRGBSet seg2B( leds(pps*1+(1*7*pps), pps-1+(pps*1)+(1*7*pps) )); 34 | CRGBSet seg2C( leds(pps*2+(1*7*pps), pps-1+(pps*2)+(1*7*pps) )); 35 | CRGBSet seg2D( leds(pps*3+(1*7*pps), pps-1+(pps*3)+(1*7*pps) )); 36 | CRGBSet seg2E( leds(pps*4+(1*7*pps), pps-1+(pps*4)+(1*7*pps) )); 37 | CRGBSet seg2F( leds(pps*5+(1*7*pps), pps-1+(pps*5)+(1*7*pps) )); 38 | CRGBSet seg2G( leds(pps*6+(1*7*pps), pps-1+(pps*6)+(1*7*pps) )); 39 | 40 | CRGBSet seg3A( leds(pps*0+(2*7*pps), pps-1+(pps*0)+(2*7*pps) )); 41 | CRGBSet seg3B( leds(pps*1+(2*7*pps), pps-1+(pps*1)+(2*7*pps) )); 42 | CRGBSet seg3C( leds(pps*2+(2*7*pps), pps-1+(pps*2)+(2*7*pps) )); 43 | CRGBSet seg3D( leds(pps*3+(2*7*pps), pps-1+(pps*3)+(2*7*pps) )); 44 | CRGBSet seg3E( leds(pps*4+(2*7*pps), pps-1+(pps*4)+(2*7*pps) )); 45 | CRGBSet seg3F( leds(pps*5+(2*7*pps), pps-1+(pps*5)+(2*7*pps) )); 46 | CRGBSet seg3G( leds(pps*6+(2*7*pps), pps-1+(pps*6)+(2*7*pps) )); 47 | 48 | CRGBSet seg4A( leds(pps*0+(3*7*pps), pps-1+(pps*0)+(3*7*pps) )); 49 | CRGBSet seg4B( leds(pps*1+(3*7*pps), pps-1+(pps*1)+(3*7*pps) )); 50 | CRGBSet seg4C( leds(pps*2+(3*7*pps), pps-1+(pps*2)+(3*7*pps) )); 51 | CRGBSet seg4D( leds(pps*3+(3*7*pps), pps-1+(pps*3)+(3*7*pps) )); 52 | CRGBSet seg4E( leds(pps*4+(3*7*pps), pps-1+(pps*4)+(3*7*pps) )); 53 | CRGBSet seg4F( leds(pps*5+(3*7*pps), pps-1+(pps*5)+(3*7*pps) )); 54 | CRGBSet seg4G( leds(pps*6+(3*7*pps), pps-1+(pps*6)+(3*7*pps) )); 55 | 56 | CRGBSet col(leds(84,85)); //colon 57 | 58 | uint8_t coordsX[NUM_LEDS] = { 1, 2, 3, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 7, 8, 9, 10, 10, 10, 10, 10, 10, 9, 8, 7, 6, 6, 6, 6, 6, 6, 7, 8, 9, 15, 16, 17, 18, 18, 18, 18, 18, 18, 17, 16, 15, 14, 14, 14, 14, 14, 14, 15, 16, 17, 21, 22, 23, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 20, 20, 20, 20, 20, 21, 22, 23, 12, 12 }; 59 | uint8_t coordsY[NUM_LEDS] = { 0, 0, 0, 1, 2, 3, 5, 6, 7, 8, 8, 8, 7, 6, 5, 3, 2, 1, 4, 4, 4, 0, 0, 0, 1, 2, 3, 5, 6, 7, 8, 8, 8, 7, 6, 5, 3, 2, 1, 4, 4, 4, 0, 0, 0, 1, 2, 3, 5, 6, 7, 8, 8, 8, 7, 6, 5, 3, 2, 1, 4, 4, 4, 0, 0, 0, 1, 2, 3, 5, 6, 7, 8, 8, 8, 7, 6, 5, 3, 2, 1, 4, 4, 4, 3, 5 }; 60 | 61 | const uint8_t maxX = 24; 62 | const uint8_t maxY = 8; 63 | 64 | const uint8_t matrixWidth = maxX + 1; 65 | const uint8_t matrixHeight = maxY + 1; 66 | 67 | void xyTest() { 68 | static uint8_t x = 0; 69 | static uint8_t y = 0; 70 | 71 | EVERY_N_MILLIS(255 - speed) { 72 | x++; 73 | if(x > maxX) { 74 | x = 0; 75 | y++; 76 | if(y > maxY) { 77 | y = 0; 78 | } 79 | } 80 | 81 | FastLED.clear(); 82 | 83 | CHSV color = CHSV(gHue, 255, 255); 84 | 85 | for(uint8_t i = 0; i < NUM_LEDS; i++) { 86 | uint8_t cx = coordsX[i]; 87 | uint8_t cy = coordsY[i]; 88 | 89 | if(cx == x && cy == y) { 90 | leds[i] = color; 91 | } 92 | } 93 | } 94 | } 95 | 96 | void xPalette() { 97 | uint8_t hues = 8; 98 | 99 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 100 | uint8_t x = coordsX[i]; 101 | 102 | leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (x * hues)); 103 | } 104 | } 105 | 106 | void yPalette() { 107 | uint8_t hues = 8; 108 | 109 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 110 | uint8_t y = coordsY[i]; 111 | 112 | leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (y * hues)); 113 | } 114 | } 115 | 116 | void xyPalette() { 117 | uint8_t hues = 8; 118 | 119 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 120 | uint8_t x = coordsX[i]; 121 | uint8_t y = coordsY[i]; 122 | 123 | leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - ((x + y) * hues)); 124 | } 125 | } 126 | 127 | void xGradientPalette() { 128 | uint8_t hues = 8; 129 | 130 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 131 | uint8_t x = coordsX[i]; 132 | 133 | leds[i] = ColorFromPalette(currentPalette, beat8(speed) - (x * hues)); 134 | } 135 | } 136 | 137 | void yGradientPalette() { 138 | uint8_t hues = 8; 139 | 140 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 141 | uint8_t y = coordsY[i]; 142 | 143 | leds[i] = ColorFromPalette(currentPalette, beat8(speed) - (y * hues)); 144 | } 145 | } 146 | 147 | void xyGradientPalette() { 148 | uint8_t hues = 8; 149 | 150 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 151 | uint8_t x = coordsX[i]; 152 | uint8_t y = coordsY[i]; 153 | 154 | leds[i] = ColorFromPalette(currentPalette, beat8(speed) - ((x + y) * hues)); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /examples/ESPixelClock/Noise.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266 + FastLED: https://github.com/jasoncoon/esp8266-fastled-webserver 3 | Copyright (C) 2015-2020 Jason Coon 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #define MAX_DIMENSION ((matrixWidth > matrixHeight) ? matrixWidth : matrixHeight) 20 | 21 | // The 16 bit version of our coordinates 22 | uint16_t noisex; 23 | uint16_t noisey; 24 | uint16_t noisez; 25 | 26 | // We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll 27 | // use the z-axis for "time". speed determines how fast time moves forward. Try 28 | // 1 for a very slow moving effect, or 60 for something that ends up looking like 29 | // water. 30 | int noisespeedx = 0; 31 | int noisespeedy = 1; 32 | int noisespeedz = 0; 33 | 34 | // Scale determines how far apart the pixels in our noise matrix are. Try 35 | // changing these values around to see how it affects the motion of the display. The 36 | // higher the value of scale, the more "zoomed out" the noise will be. A value 37 | // of 1 will be so zoomed in, you'll mostly see solid colors. 38 | uint16_t noisescale = 1; // scale is set dynamically once we've started up 39 | 40 | // This is the array that we keep our computed noise values in 41 | uint8_t noise[MAX_DIMENSION][MAX_DIMENSION]; 42 | 43 | uint8_t colorLoop = 0; 44 | 45 | CRGBPalette16 blackAndWhiteStripedPalette; 46 | 47 | // This function sets up a palette of black and white stripes, 48 | // using code. Since the palette is effectively an array of 49 | // sixteen CRGB colors, the various fill_* functions can be used 50 | // to set them up. 51 | void SetupBlackAndWhiteStripedPalette() 52 | { 53 | // 'black out' all 16 palette entries... 54 | fill_solid( blackAndWhiteStripedPalette, 16, CRGB::Black); 55 | // and set every fourth one to white. 56 | blackAndWhiteStripedPalette[0] = CRGB::White; 57 | blackAndWhiteStripedPalette[4] = CRGB::White; 58 | blackAndWhiteStripedPalette[8] = CRGB::White; 59 | blackAndWhiteStripedPalette[12] = CRGB::White; 60 | 61 | } 62 | 63 | CRGBPalette16 blackAndBlueStripedPalette; 64 | 65 | // This function sets up a palette of black and blue stripes, 66 | // using code. Since the palette is effectively an array of 67 | // sixteen CRGB colors, the various fill_* functions can be used 68 | // to set them up. 69 | void SetupBlackAndBlueStripedPalette() 70 | { 71 | // 'black out' all 16 palette entries... 72 | fill_solid( blackAndBlueStripedPalette, 16, CRGB::Black); 73 | 74 | for (uint8_t i = 0; i < 6; i++) { 75 | blackAndBlueStripedPalette[i] = CRGB::Blue; 76 | } 77 | } 78 | 79 | // There are several different palettes of colors demonstrated here. 80 | // 81 | // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p, 82 | // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p. 83 | // 84 | // Additionally, you can manually define your own color palettes, or you can write 85 | // code that creates color palettes on the fly. 86 | 87 | void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) 88 | { 89 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 90 | uint8_t x = coordsX[i]; 91 | uint8_t y = coordsY[i]; 92 | 93 | int xoffset = noisescale * x; 94 | int yoffset = noisescale * y; 95 | 96 | uint8_t data = inoise8(x + xoffset + noisex, y + yoffset + noisey, noisez); 97 | 98 | // The range of the inoise8 function is roughly 16-238. 99 | // These two operations expand those values out to roughly 0..255 100 | // You can comment them out if you want the raw noise data. 101 | data = qsub8(data, 16); 102 | data = qadd8(data, scale8(data, 39)); 103 | 104 | if (hueReduce > 0 && data >= hueReduce) 105 | data -= hueReduce; 106 | 107 | leds[i] = ColorFromPalette(palette, data, 255, LINEARBLEND); 108 | } 109 | 110 | noisex += noisespeedx; 111 | noisey += noisespeedy; 112 | noisez += noisespeedz; 113 | } 114 | 115 | void rainbowNoise() { 116 | noisespeedx = 0; 117 | noisespeedy = -1; 118 | noisespeedz = 0; 119 | noisescale = 24; 120 | colorLoop = 0; 121 | drawNoise(RainbowColors_p); 122 | } 123 | 124 | void rainbowStripeNoise() { 125 | noisespeedx = 0; 126 | noisespeedy = -2; 127 | noisespeedz = 0; 128 | noisescale = 24; 129 | colorLoop = 0; 130 | drawNoise(RainbowStripeColors_p); 131 | } 132 | 133 | void partyNoise() { 134 | noisespeedx = -9; 135 | noisespeedy = 0; 136 | noisespeedz = 0; 137 | noisescale = 32; 138 | colorLoop = 0; 139 | drawNoise(PartyColors_p); 140 | } 141 | 142 | void forestNoise() { 143 | noisespeedx = -9; 144 | noisespeedy = 0; 145 | noisespeedz = 0; 146 | noisescale = 32; 147 | colorLoop = 0; 148 | drawNoise(ForestColors_p); 149 | } 150 | 151 | void cloudNoise() { 152 | noisespeedx = -2; 153 | noisespeedy = 0; 154 | noisespeedz = 0; 155 | noisescale = 24; 156 | colorLoop = 0; 157 | drawNoise(CloudColors_p); 158 | } 159 | 160 | void fireNoise() { 161 | noisespeedx = 0; // 24; 162 | noisespeedy = 32; 163 | noisespeedz = 0; 164 | noisescale = 64; 165 | colorLoop = 0; 166 | drawNoise(HeatColors_p, 60); 167 | } 168 | 169 | void fireNoise2() { 170 | noisespeedx = 0; 171 | noisespeedy = 8; 172 | noisespeedz = 3; 173 | noisescale = 32; 174 | colorLoop = 0; 175 | drawNoise(HeatColors_p); 176 | } 177 | 178 | void lavaNoise() { 179 | noisespeedx = 0; 180 | noisespeedy = -1; 181 | noisespeedz = 1; 182 | noisescale = 24; 183 | colorLoop = 0; 184 | drawNoise(LavaColors_p); 185 | } 186 | 187 | void oceanNoise() { 188 | noisespeedx = -2; 189 | noisespeedy = 0; 190 | noisespeedz = 4; 191 | noisescale = 24; 192 | colorLoop = 0; 193 | drawNoise(OceanColors_p); 194 | } 195 | 196 | void blackAndWhiteNoise() { 197 | SetupBlackAndWhiteStripedPalette(); 198 | noisespeedx = -12; 199 | noisespeedy = 0; 200 | noisespeedz = 0; 201 | noisescale = 24; 202 | colorLoop = 0; 203 | drawNoise(blackAndWhiteStripedPalette); 204 | } 205 | 206 | void blackAndBlueNoise() { 207 | SetupBlackAndBlueStripedPalette(); 208 | noisespeedx = 0; 209 | noisespeedy = 8; 210 | noisespeedz = 0; 211 | noisescale = 32; 212 | colorLoop = 0; 213 | drawNoise(blackAndBlueStripedPalette); 214 | } 215 | -------------------------------------------------------------------------------- /examples/ESPixelClock/compiled/ESPixelClock.bat: -------------------------------------------------------------------------------- 1 | C:\Users\Matt\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1\esptool.exe --chip esp32 --port COM4 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 C:\Users\Matt\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4/tools/partitions/boot_app0.bin 0x1000 C:\Users\Matt\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4/tools/sdk/bin/bootloader_qio_80m.bin 0x10000 ESPixelClock.ino.bin 0x8000 ESPixelClock.ino.partitions.bin 0x290000 ESPixelClock.spiffs.bin -------------------------------------------------------------------------------- /examples/ESPixelClock/compiled/ESPixelClock.ino.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/compiled/ESPixelClock.ino.bin -------------------------------------------------------------------------------- /examples/ESPixelClock/compiled/ESPixelClock.ino.partitions.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/compiled/ESPixelClock.ino.partitions.bin -------------------------------------------------------------------------------- /examples/ESPixelClock/compiled/ESPixelClock.spiffs.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/compiled/ESPixelClock.spiffs.bin -------------------------------------------------------------------------------- /examples/ESPixelClock/css.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/css.7z -------------------------------------------------------------------------------- /examples/ESPixelClock/data/_index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ESPixelClock 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 44 |
45 |
46 |
47 |
48 | 172 | 194 | 195 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /examples/ESPixelClock/data/css/bootstrap.min.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/css/bootstrap.min.css.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/css/jquery.minicolors.min.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/css/jquery.minicolors.min.css.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/favicon.ico -------------------------------------------------------------------------------- /examples/ESPixelClock/data/giticon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/ESPixelClock/data/index.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/index.htm.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/js/app.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/js/app.js.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/js/bootstrap.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/js/bootstrap.min.js.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/js/jquery-3.1.1.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/js/jquery-3.1.1.min.js.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/js/jquery.minicolors.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/js/jquery.minicolors.min.js.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/js/reconnecting-websocket.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/data/js/reconnecting-websocket.min.js.gz -------------------------------------------------------------------------------- /examples/ESPixelClock/data/wifi.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ESPixelClock Wifi Configuration 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 38 |
39 |

"%NAME%" Configuration

40 | Wifi SSID:
41 | Wifi Password:
42 | NTP Server1:
43 | NTP Server2:
44 | 45 |
First of many overlapping time zone codes selected by default, e.g. America/Detroit=America/New York.
472 | 473 | 474 | 475 | 476 | 477 |
Time submitted will be overridden by NTP time if WiFi and NTP servers available.
478 | 479 | 480 | 481 |
482 |
483 | Back 484 | Temp: %TEMPERATURE% Humidity:%HUMIDITY% 485 | 491 | 492 | -------------------------------------------------------------------------------- /examples/ESPixelClock/esp32fs.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/esp32fs.jar -------------------------------------------------------------------------------- /examples/ESPixelClock/field.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | typedef String (*FieldSetter)(String); 26 | typedef String (*FieldGetter)(); 27 | 28 | const String NumberFieldType = "Number"; 29 | const String BooleanFieldType = "Boolean"; 30 | const String SelectFieldType = "Select"; 31 | const String ColorFieldType = "Color"; 32 | const String SectionFieldType = "Section"; 33 | 34 | typedef struct Field { 35 | public: 36 | String name; 37 | String label; 38 | String type; 39 | int min; 40 | int max; 41 | FieldGetter getValue; 42 | FieldGetter getOptions; 43 | FieldSetter setValue; 44 | }; 45 | 46 | typedef Field FieldList[]; 47 | 48 | Field getField(String name, FieldList fields, uint8_t count) { 49 | for (uint8_t i = 0; i < count; i++) { 50 | Field field = fields[i]; 51 | if (field.name == name) { 52 | return field; 53 | } 54 | } 55 | return Field(); 56 | } 57 | 58 | String getFieldValue(String name, FieldList fields, uint8_t count) { 59 | Field field = getField(name, fields, count); 60 | if (field.getValue) { 61 | return field.getValue(); 62 | } 63 | return String(); 64 | } 65 | 66 | CRGB parseColor(String value) { 67 | uint8_t ri = value.indexOf(","); 68 | uint8_t gi = value.indexOf(",", ri + 1); 69 | 70 | String rs = value.substring(0, ri); 71 | String gs = value.substring(ri + 1, gi); 72 | String bs = value.substring(gi + 1); 73 | 74 | uint8_t r = rs.toInt(); 75 | uint8_t g = gs.toInt(); 76 | uint8_t b = bs.toInt(); 77 | 78 | return CRGB(r, g, b); 79 | } 80 | 81 | void writeFieldsToEEPROM(FieldList fields, uint8_t count) { 82 | uint8_t index = 0; 83 | 84 | EEPROM.write(index, 0); 85 | 86 | for (uint8_t i = 0; i < count; i++) { 87 | Field field = fields[i]; 88 | if (!field.getValue && !field.setValue) 89 | continue; 90 | 91 | String value = field.getValue(); 92 | 93 | if (field.type == ColorFieldType) { 94 | CRGB color = parseColor(value); 95 | EEPROM.write(index++, color.r); 96 | EEPROM.write(index++, color.g); 97 | EEPROM.write(index++, color.b); 98 | } else if (field.name == "timezoneOffset") { 99 | int i = value.toInt(); 100 | byte v = i - field.min; 101 | EEPROM.write(index++, v); 102 | } else { 103 | byte v = value.toInt(); 104 | EEPROM.write(index++, v); 105 | } 106 | 107 | Serial.print("Wrote field: "); Serial.print(i); 108 | Serial.print(", name: "); Serial.print(field.name); 109 | Serial.print(", value: "); Serial.println(field.getValue()); 110 | } 111 | 112 | EEPROM.commit(); 113 | } 114 | 115 | //String setFieldValue(String name, String value, FieldList fields, uint8_t count) { 116 | // String result; 117 | // 118 | // Field field = getField(name, fields, count); 119 | // if (field.setValue) { 120 | // if (field.type == ColorFieldType) { 121 | // String r = webServer.arg("r"); 122 | // String g = webServer.arg("g"); 123 | // String b = webServer.arg("b"); 124 | // String combinedValue = r + "," + g + "," + b; 125 | // result = field.setValue(combinedValue); 126 | // } else { 127 | // result = field.setValue(value); 128 | // } 129 | // } 130 | // 131 | // writeFieldsToEEPROM(fields, count); 132 | // 133 | // return result; 134 | //} 135 | 136 | String setFieldValueAsync(String name, String value, FieldList fields, uint8_t count) { 137 | String result; 138 | 139 | Field field = getField(name, fields, count); 140 | if (field.setValue) { 141 | result = field.setValue(value); 142 | 143 | } 144 | 145 | writeFieldsToEEPROM(fields, count); 146 | 147 | return result; 148 | } 149 | 150 | 151 | void loadFieldsFromEEPROM(FieldList fields, uint8_t count) { 152 | uint8_t byteCount = 1; 153 | 154 | for (uint8_t i = 0; i < count; i++) { 155 | Field field = fields[i]; 156 | if (!field.setValue) 157 | continue; 158 | 159 | if (field.type == ColorFieldType) { 160 | byteCount += 3; 161 | } else { 162 | byteCount++; 163 | } 164 | } 165 | 166 | if (!EEPROM.begin(count)) { 167 | Serial.println("Failed to initialize EEPROM!"); 168 | return; 169 | } 170 | 171 | if (EEPROM.read(0) == 255) { 172 | Serial.println("First run, or EEPROM erased, skipping settings load!"); 173 | return; 174 | } 175 | 176 | uint8_t index = 0; 177 | 178 | for (uint8_t i = 0; i < count; i++) { 179 | Field field = fields[i]; 180 | if (!field.setValue) 181 | continue; 182 | 183 | if (field.type == ColorFieldType) { 184 | String r = String(EEPROM.read(index++)); 185 | String g = String(EEPROM.read(index++)); 186 | String b = String(EEPROM.read(index++)); 187 | field.setValue(r + "," + g + "," + b); 188 | } else if (field.name == "timezoneOffset") { 189 | byte b = EEPROM.read(index++); 190 | int v = b + field.min; 191 | field.setValue(String(v)); 192 | } else { 193 | byte v = EEPROM.read(index++); 194 | field.setValue(String(v)); 195 | } 196 | 197 | Serial.print("Loaded field: "); Serial.print(i); 198 | Serial.print(", name: "); Serial.print(field.name); 199 | Serial.print(", value: "); Serial.println(field.getValue()); 200 | } 201 | } 202 | 203 | String getFieldsJson(FieldList fields, uint8_t count) { 204 | String json = "["; 205 | 206 | for (uint8_t i = 0; i < count; i++) { 207 | Field field = fields[i]; 208 | 209 | json += "{\"name\":\"" + field.name + "\",\"label\":\"" + field.label + "\",\"type\":\"" + field.type + "\""; 210 | 211 | if (field.getValue) { 212 | if (field.type == ColorFieldType || field.type == "String") { 213 | json += ",\"value\":\"" + field.getValue() + "\""; 214 | } 215 | else { 216 | json += ",\"value\":" + field.getValue(); 217 | } 218 | } 219 | 220 | if (field.type == NumberFieldType) { 221 | json += ",\"min\":" + String(field.min); 222 | json += ",\"max\":" + String(field.max); 223 | } 224 | 225 | if (field.getOptions) { 226 | json += ",\"options\":["; 227 | json += field.getOptions(); 228 | json += "]"; 229 | } 230 | 231 | json += "}"; 232 | 233 | if (i < count - 1) 234 | json += ","; 235 | } 236 | 237 | json += "]"; 238 | 239 | return json; 240 | } 241 | -------------------------------------------------------------------------------- /examples/ESPixelClock/fields.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | String getPower() { 26 | return String(power); 27 | } 28 | 29 | String setPower(String value) { 30 | power = value.toInt(); 31 | power = power == 0 ? 0 : 1; 32 | return String(power); 33 | } 34 | 35 | String getLeadingZero() { 36 | return String(leadingZeroEnabled); 37 | } 38 | 39 | String setLeadingZero(String value) { 40 | leadingZeroEnabled = value.toInt(); 41 | leadingZeroEnabled = leadingZeroEnabled == 0 ? 0 : 1; 42 | return String(leadingZeroEnabled); 43 | } 44 | 45 | String getBlinkingColon() { 46 | return String(blinkingColonEnabled); 47 | } 48 | 49 | String setBlinkingColon(String value) { 50 | blinkingColonEnabled = value.toInt(); 51 | blinkingColonEnabled = blinkingColonEnabled == 0 ? 0 : 1; 52 | return String(blinkingColonEnabled); 53 | } 54 | 55 | String getTime24() { 56 | return String(time24); 57 | } 58 | 59 | String setTime24(String value) { 60 | time24 = value.toInt(); 61 | time24 = time24 == 0 ? 0 : 1; 62 | return String(time24); 63 | } 64 | 65 | String getTemp() { 66 | return String(temp); 67 | } 68 | 69 | String setTemp(String value) { 70 | return String(temp); 71 | } 72 | 73 | String getHumid() { 74 | return String(rh); 75 | } 76 | 77 | String setHumid(String value) { 78 | return String(rh); 79 | } 80 | 81 | String getBrightness() { 82 | return String(brightness); 83 | } 84 | 85 | String setBrightness(String value) { 86 | brightness = value.toInt(); 87 | FastLED.setBrightness(brightness); 88 | return String(brightness); 89 | } 90 | 91 | //String getTimezoneOffset() { 92 | // return String(timezoneOffset); 93 | //} 94 | // 95 | //String setTimezoneOffset(String value) { 96 | // timezoneOffset = value.toInt(); 97 | // if (timezoneOffset < -12) timezoneOffset = -12; 98 | // else if (timezoneOffset > 14) timezoneOffset = 14; 99 | // 100 | // gmtOffset_sec = timezoneOffset * 3600; 101 | // tzChanged=true; 102 | // return String(timezoneOffset); 103 | //} 104 | 105 | String getTemperatureOffset() { 106 | return String(temperatureOffset); 107 | } 108 | 109 | String setTemperatureOffset(String value) { 110 | temperatureOffset = value.toInt(); 111 | return String(temperatureOffset); 112 | } 113 | 114 | String getPattern() { 115 | return String(currentPatternIndex); 116 | } 117 | 118 | void setPattern(uint8_t value) 119 | { 120 | if (value >= patternCount) 121 | value = patternCount - 1; 122 | 123 | currentPatternIndex = value; 124 | } 125 | 126 | String setPattern(String value) { 127 | setPattern(value.toInt()); 128 | return String(currentPatternIndex); 129 | } 130 | 131 | String getPatterns() { 132 | String json = ""; 133 | 134 | for (uint8_t i = 0; i < patternCount; i++) { 135 | json += "\"" + patterns[i].name + "\""; 136 | if (i < patternCount - 1) 137 | json += ","; 138 | } 139 | 140 | return json; 141 | } 142 | 143 | 144 | 145 | String getPalette() { 146 | return String(currentPaletteIndex); 147 | } 148 | 149 | String setPalette(String value) { 150 | currentPaletteIndex = value.toInt(); 151 | if (currentPaletteIndex < 0) currentPaletteIndex = 0; 152 | else if (currentPaletteIndex >= paletteCount) currentPaletteIndex = paletteCount - 1; 153 | targetPalette = palettes[currentPaletteIndex]; 154 | return String(currentPaletteIndex); 155 | } 156 | 157 | String getPalettes() { 158 | String json = ""; 159 | 160 | for (uint8_t i = 0; i < paletteCount; i++) { 161 | json += "\"" + paletteNames[i] + "\""; 162 | if (i < paletteCount - 1) 163 | json += ","; 164 | } 165 | 166 | return json; 167 | } 168 | 169 | String getSpeed() { 170 | return String(speed); 171 | } 172 | 173 | String setSpeed(String value) { 174 | speed = value.toInt(); 175 | return String(speed); 176 | } 177 | 178 | String getAutoplay() { 179 | return String(autoplay); 180 | } 181 | 182 | String setAutoplay(String value) { 183 | autoplay = value.toInt(); 184 | autoplay = autoplay == 0 ? 0 : 1; 185 | autoPlayTimeout = millis() + (autoplayDuration * 1000); 186 | return String(autoplay); 187 | } 188 | 189 | String getAutoplayDuration() { 190 | return String(autoplayDuration); 191 | } 192 | 193 | String setAutoplayDuration(String value) { 194 | autoplayDuration = value.toInt(); 195 | if (autoplayDuration < 1) autoplayDuration = 1; 196 | else if (autoplayDuration > 255) autoplayDuration = 255; 197 | autoPlayTimeout = millis() + (autoplayDuration * 1000); 198 | return String(autoplayDuration); 199 | } 200 | 201 | String getCyclePalettes() { 202 | return String(cyclePalettes); 203 | } 204 | 205 | String setCyclePalettes(String value) { 206 | cyclePalettes = value.toInt(); 207 | cyclePalettes = cyclePalettes == 0 ? 0 : 1; 208 | paletteTimeout = millis() + (paletteDuration * 1000); 209 | return String(cyclePalettes); 210 | } 211 | 212 | String getPaletteDuration() { 213 | return String(paletteDuration); 214 | } 215 | 216 | String setPaletteDuration(String value) { 217 | paletteDuration = value.toInt(); 218 | if (paletteDuration < 1) paletteDuration = 1; 219 | else if (paletteDuration > 255) paletteDuration = 255; 220 | paletteTimeout = millis() + (paletteDuration * 1000); 221 | return String(paletteDuration); 222 | } 223 | 224 | String getSolidColor() { 225 | return String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b); 226 | } 227 | 228 | String setSolidColor(uint8_t r, uint8_t g, uint8_t b) 229 | { 230 | solidColor = CRGB(r, g, b); 231 | 232 | return "\"" + String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b) + "\""; 233 | } 234 | 235 | String setSolidColor(CRGB color) { 236 | return setSolidColor(color.r, color.g, color.b); 237 | } 238 | 239 | String setSolidColor(String value) { 240 | CRGB color = parseColor(value); 241 | 242 | return setSolidColor(color); 243 | } 244 | 245 | String getCooling() { 246 | return String(cooling); 247 | } 248 | 249 | String setCooling(String value) { 250 | cooling = value.toInt(); 251 | return String(cooling); 252 | } 253 | 254 | String getSparking() { 255 | return String(sparking); 256 | } 257 | 258 | String setSparking(String value) { 259 | sparking = value.toInt(); 260 | return String(sparking); 261 | } 262 | 263 | String getTwinkleSpeed() { 264 | return String(twinkleSpeed); 265 | } 266 | 267 | String setTwinkleSpeed(String value) { 268 | twinkleSpeed = value.toInt(); 269 | if (twinkleSpeed < 0) twinkleSpeed = 0; 270 | else if (twinkleSpeed > 8) twinkleSpeed = 8; 271 | return String(twinkleSpeed); 272 | } 273 | 274 | String getTwinkleDensity() { 275 | return String(twinkleDensity); 276 | } 277 | 278 | String setTwinkleDensity(String value) { 279 | twinkleDensity = value.toInt(); 280 | if (twinkleDensity < 0) twinkleDensity = 0; 281 | else if (twinkleDensity > 8) twinkleDensity = 8; 282 | return String(twinkleDensity); 283 | } 284 | 285 | FieldList fields = { 286 | { "power", "Power", BooleanFieldType, 0, 1, getPower, NULL, setPower }, 287 | { "time24", "24 hour time", BooleanFieldType, 0, 1, getTime24, NULL, setTime24 }, 288 | { "leadingZeroEnabled", "Show Leading Zero", BooleanFieldType, 0, 1, getLeadingZero, NULL, setLeadingZero }, 289 | { "blinkingColonEnabled", "Blink colon", BooleanFieldType, 0, 1, getBlinkingColon, NULL, setBlinkingColon }, 290 | // { "timezoneOffset", "Timezone Offset Hours", NumberFieldType, -12, 14, getTimezoneOffset, NULL, setTimezoneOffset }, 291 | { "temperatureOffset", "Temperature offset", NumberFieldType, -20, 20, getTemperatureOffset, NULL, setTemperatureOffset}, 292 | { "temperature", "Temperature", NumberFieldType, temp-1, temp+1, getTemp, NULL, setTemp}, 293 | { "humidity", "Humidity", NumberFieldType, rh-1, rh+1, getHumid, NULL, setHumid}, 294 | 295 | { "patternSection", "Pattern", SectionFieldType }, 296 | { "brightness", "Brightness", NumberFieldType, 1, 255, getBrightness, NULL, setBrightness }, 297 | { "speed", "Speed", NumberFieldType, 1, 255, getSpeed, NULL, setSpeed }, 298 | { "pattern", "Pattern", SelectFieldType, 0, patternCount, getPattern, getPatterns, setPattern }, 299 | { "autoplay", "Cycle Patterns", BooleanFieldType, 0, 1, getAutoplay, NULL, setAutoplay }, 300 | { "autoplayDuration", "Pattern Duration", NumberFieldType, 1, 255, getAutoplayDuration, NULL, setAutoplayDuration }, 301 | 302 | { "paletteSection", "Palette", SectionFieldType }, 303 | { "palette", "Palette", SelectFieldType, 0, paletteCount, getPalette, getPalettes, setPalette }, 304 | { "cyclePalettes", "Cycle Palettes", BooleanFieldType, 0, 1, getCyclePalettes, NULL, setCyclePalettes }, 305 | { "paletteDuration", "Palette Duration", NumberFieldType, 1, 255, getPaletteDuration, NULL, setPaletteDuration }, 306 | 307 | { "solidColorSection", "Solid Color", SectionFieldType }, 308 | { "solidColor", "Color", ColorFieldType, 0, 255, getSolidColor, NULL, setSolidColor }, 309 | 310 | { "fire", "Fire & Water", SectionFieldType }, 311 | { "cooling", "Cooling", NumberFieldType, 0, 255, getCooling, NULL, setCooling }, 312 | { "sparking", "Sparking", NumberFieldType, 0, 255, getSparking, NULL, setSparking }, 313 | 314 | { "twinklesSection", "Twinkles", SectionFieldType }, 315 | { "twinkleSpeed", "Twinkle Speed", NumberFieldType, 0, 8, getTwinkleSpeed, NULL, setTwinkleSpeed }, 316 | { "twinkleDensity", "Twinkle Density", NumberFieldType, 0, 8, getTwinkleDensity, NULL, setTwinkleDensity }, 317 | }; 318 | 319 | uint8_t fieldCount = ARRAY_SIZE(fields); 320 | -------------------------------------------------------------------------------- /examples/ESPixelClock/fonts.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/fonts.7z -------------------------------------------------------------------------------- /examples/ESPixelClock/gradientPalettes.h: -------------------------------------------------------------------------------- 1 | // From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb 2 | 3 | // Gradient Color Palette definitions for 33 different cpt-city color palettes. 4 | // 956 bytes of PROGMEM for all of the palettes together, 5 | // +618 bytes of PROGMEM for gradient palette code (AVR). 6 | // 1,494 bytes total for all 34 color palettes and associated code. 7 | 8 | // Gradient palette "ib_jul01_gp", originally from 9 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html 10 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 11 | // Size: 16 bytes of program space. 12 | 13 | DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) { 14 | 0, 194, 1, 1, 15 | 94, 1, 29, 18, 16 | 132, 57,131, 28, 17 | 255, 113, 1, 1}; 18 | 19 | // Gradient palette "es_vintage_57_gp", originally from 20 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_57.png.index.html 21 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 22 | // Size: 20 bytes of program space. 23 | 24 | DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) { 25 | 0, 2, 1, 1, 26 | 53, 18, 1, 0, 27 | 104, 69, 29, 1, 28 | 153, 167,135, 10, 29 | 255, 46, 56, 4}; 30 | 31 | // Gradient palette "es_vintage_01_gp", originally from 32 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_01.png.index.html 33 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 34 | // Size: 32 bytes of program space. 35 | 36 | DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) { 37 | 0, 4, 1, 1, 38 | 51, 16, 0, 1, 39 | 76, 97,104, 3, 40 | 101, 255,131, 19, 41 | 127, 67, 9, 4, 42 | 153, 16, 0, 1, 43 | 229, 4, 1, 1, 44 | 255, 4, 1, 1}; 45 | 46 | // Gradient palette "es_rivendell_15_gp", originally from 47 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/rivendell/tn/es_rivendell_15.png.index.html 48 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 49 | // Size: 20 bytes of program space. 50 | 51 | DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) { 52 | 0, 1, 14, 5, 53 | 101, 16, 36, 14, 54 | 165, 56, 68, 30, 55 | 242, 150,156, 99, 56 | 255, 150,156, 99}; 57 | 58 | // Gradient palette "rgi_15_gp", originally from 59 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/rgi/tn/rgi_15.png.index.html 60 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 61 | // Size: 36 bytes of program space. 62 | 63 | DEFINE_GRADIENT_PALETTE( rgi_15_gp ) { 64 | 0, 4, 1, 31, 65 | 31, 55, 1, 16, 66 | 63, 197, 3, 7, 67 | 95, 59, 2, 17, 68 | 127, 6, 2, 34, 69 | 159, 39, 6, 33, 70 | 191, 112, 13, 32, 71 | 223, 56, 9, 35, 72 | 255, 22, 6, 38}; 73 | 74 | // Gradient palette "retro2_16_gp", originally from 75 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/retro2/tn/retro2_16.png.index.html 76 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 77 | // Size: 8 bytes of program space. 78 | 79 | DEFINE_GRADIENT_PALETTE( retro2_16_gp ) { 80 | 0, 188,135, 1, 81 | 255, 46, 7, 1}; 82 | 83 | // Gradient palette "Analogous_1_gp", originally from 84 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/red/tn/Analogous_1.png.index.html 85 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 86 | // Size: 20 bytes of program space. 87 | 88 | DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) { 89 | 0, 3, 0,255, 90 | 63, 23, 0,255, 91 | 127, 67, 0,255, 92 | 191, 142, 0, 45, 93 | 255, 255, 0, 0}; 94 | 95 | // Gradient palette "es_pinksplash_08_gp", originally from 96 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_08.png.index.html 97 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 98 | // Size: 20 bytes of program space. 99 | 100 | DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) { 101 | 0, 126, 11,255, 102 | 127, 197, 1, 22, 103 | 175, 210,157,172, 104 | 221, 157, 3,112, 105 | 255, 157, 3,112}; 106 | 107 | // Gradient palette "es_pinksplash_07_gp", originally from 108 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_07.png.index.html 109 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 110 | // Size: 28 bytes of program space. 111 | 112 | DEFINE_GRADIENT_PALETTE( es_pinksplash_07_gp ) { 113 | 0, 229, 1, 1, 114 | 61, 242, 4, 63, 115 | 101, 255, 12,255, 116 | 127, 249, 81,252, 117 | 153, 255, 11,235, 118 | 193, 244, 5, 68, 119 | 255, 232, 1, 5}; 120 | 121 | // Gradient palette "Coral_reef_gp", originally from 122 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/other/tn/Coral_reef.png.index.html 123 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 124 | // Size: 24 bytes of program space. 125 | 126 | DEFINE_GRADIENT_PALETTE( Coral_reef_gp ) { 127 | 0, 40,199,197, 128 | 50, 10,152,155, 129 | 96, 1,111,120, 130 | 96, 43,127,162, 131 | 139, 10, 73,111, 132 | 255, 1, 34, 71}; 133 | 134 | // Gradient palette "es_ocean_breeze_068_gp", originally from 135 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_068.png.index.html 136 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 137 | // Size: 24 bytes of program space. 138 | 139 | DEFINE_GRADIENT_PALETTE( es_ocean_breeze_068_gp ) { 140 | 0, 100,156,153, 141 | 51, 1, 99,137, 142 | 101, 1, 68, 84, 143 | 104, 35,142,168, 144 | 178, 0, 63,117, 145 | 255, 1, 10, 10}; 146 | 147 | // Gradient palette "es_ocean_breeze_036_gp", originally from 148 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_036.png.index.html 149 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 150 | // Size: 16 bytes of program space. 151 | 152 | DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) { 153 | 0, 1, 6, 7, 154 | 89, 1, 99,111, 155 | 153, 144,209,255, 156 | 255, 0, 73, 82}; 157 | 158 | // Gradient palette "departure_gp", originally from 159 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/mjf/tn/departure.png.index.html 160 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 161 | // Size: 88 bytes of program space. 162 | 163 | DEFINE_GRADIENT_PALETTE( departure_gp ) { 164 | 0, 8, 3, 0, 165 | 42, 23, 7, 0, 166 | 63, 75, 38, 6, 167 | 84, 169, 99, 38, 168 | 106, 213,169,119, 169 | 116, 255,255,255, 170 | 138, 135,255,138, 171 | 148, 22,255, 24, 172 | 170, 0,255, 0, 173 | 191, 0,136, 0, 174 | 212, 0, 55, 0, 175 | 255, 0, 55, 0}; 176 | 177 | // Gradient palette "es_landscape_64_gp", originally from 178 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_64.png.index.html 179 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 180 | // Size: 36 bytes of program space. 181 | 182 | DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) { 183 | 0, 0, 0, 0, 184 | 37, 2, 25, 1, 185 | 76, 15,115, 5, 186 | 127, 79,213, 1, 187 | 128, 126,211, 47, 188 | 130, 188,209,247, 189 | 153, 144,182,205, 190 | 204, 59,117,250, 191 | 255, 1, 37,192}; 192 | 193 | // Gradient palette "es_landscape_33_gp", originally from 194 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_33.png.index.html 195 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 196 | // Size: 24 bytes of program space. 197 | 198 | DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) { 199 | 0, 1, 5, 0, 200 | 19, 32, 23, 1, 201 | 38, 161, 55, 1, 202 | 63, 229,144, 1, 203 | 66, 39,142, 74, 204 | 255, 1, 4, 1}; 205 | 206 | // Gradient palette "rainbowsherbet_gp", originally from 207 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/icecream/tn/rainbowsherbet.png.index.html 208 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 209 | // Size: 28 bytes of program space. 210 | 211 | DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) { 212 | 0, 255, 33, 4, 213 | 43, 255, 68, 25, 214 | 86, 255, 7, 25, 215 | 127, 255, 82,103, 216 | 170, 255,255,242, 217 | 209, 42,255, 22, 218 | 255, 87,255, 65}; 219 | 220 | // Gradient palette "gr65_hult_gp", originally from 221 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr65_hult.png.index.html 222 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 223 | // Size: 24 bytes of program space. 224 | 225 | DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) { 226 | 0, 247,176,247, 227 | 48, 255,136,255, 228 | 89, 220, 29,226, 229 | 160, 7, 82,178, 230 | 216, 1,124,109, 231 | 255, 1,124,109}; 232 | 233 | // Gradient palette "gr64_hult_gp", originally from 234 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr64_hult.png.index.html 235 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 236 | // Size: 32 bytes of program space. 237 | 238 | DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) { 239 | 0, 1,124,109, 240 | 66, 1, 93, 79, 241 | 104, 52, 65, 1, 242 | 130, 115,127, 1, 243 | 150, 52, 65, 1, 244 | 201, 1, 86, 72, 245 | 239, 0, 55, 45, 246 | 255, 0, 55, 45}; 247 | 248 | // Gradient palette "GMT_drywet_gp", originally from 249 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/gmt/tn/GMT_drywet.png.index.html 250 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 251 | // Size: 28 bytes of program space. 252 | 253 | DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) { 254 | 0, 47, 30, 2, 255 | 42, 213,147, 24, 256 | 84, 103,219, 52, 257 | 127, 3,219,207, 258 | 170, 1, 48,214, 259 | 212, 1, 1,111, 260 | 255, 1, 7, 33}; 261 | 262 | // Gradient palette "ib15_gp", originally from 263 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/general/tn/ib15.png.index.html 264 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 265 | // Size: 24 bytes of program space. 266 | 267 | DEFINE_GRADIENT_PALETTE( ib15_gp ) { 268 | 0, 113, 91,147, 269 | 72, 157, 88, 78, 270 | 89, 208, 85, 33, 271 | 107, 255, 29, 11, 272 | 141, 137, 31, 39, 273 | 255, 59, 33, 89}; 274 | 275 | // Gradient palette "Fuschia_7_gp", originally from 276 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/fuschia/tn/Fuschia-7.png.index.html 277 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 278 | // Size: 20 bytes of program space. 279 | 280 | DEFINE_GRADIENT_PALETTE( Fuschia_7_gp ) { 281 | 0, 43, 3,153, 282 | 63, 100, 4,103, 283 | 127, 188, 5, 66, 284 | 191, 161, 11,115, 285 | 255, 135, 20,182}; 286 | 287 | // Gradient palette "es_emerald_dragon_08_gp", originally from 288 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/emerald_dragon/tn/es_emerald_dragon_08.png.index.html 289 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 290 | // Size: 16 bytes of program space. 291 | 292 | DEFINE_GRADIENT_PALETTE( es_emerald_dragon_08_gp ) { 293 | 0, 97,255, 1, 294 | 101, 47,133, 1, 295 | 178, 13, 43, 1, 296 | 255, 2, 10, 1}; 297 | 298 | // Gradient palette "lava_gp", originally from 299 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/lava.png.index.html 300 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 301 | // Size: 52 bytes of program space. 302 | 303 | DEFINE_GRADIENT_PALETTE( lava_gp ) { 304 | 0, 0, 0, 0, 305 | 46, 18, 0, 0, 306 | 96, 113, 0, 0, 307 | 108, 142, 3, 1, 308 | 119, 175, 17, 1, 309 | 146, 213, 44, 2, 310 | 174, 255, 82, 4, 311 | 188, 255,115, 4, 312 | 202, 255,156, 4, 313 | 218, 255,203, 4, 314 | 234, 255,255, 4, 315 | 244, 255,255, 71, 316 | 255, 255,255,255}; 317 | 318 | // Gradient palette "fire_gp", originally from 319 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/fire.png.index.html 320 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 321 | // Size: 28 bytes of program space. 322 | 323 | DEFINE_GRADIENT_PALETTE( fire_gp ) { 324 | 0, 1, 1, 0, 325 | 76, 32, 5, 0, 326 | 146, 192, 24, 0, 327 | 197, 220,105, 5, 328 | 240, 252,255, 31, 329 | 250, 252,255,111, 330 | 255, 255,255,255}; 331 | 332 | // Gradient palette "Colorfull_gp", originally from 333 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Colorfull.png.index.html 334 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 335 | // Size: 44 bytes of program space. 336 | 337 | DEFINE_GRADIENT_PALETTE( Colorfull_gp ) { 338 | 0, 10, 85, 5, 339 | 25, 29,109, 18, 340 | 60, 59,138, 42, 341 | 93, 83, 99, 52, 342 | 106, 110, 66, 64, 343 | 109, 123, 49, 65, 344 | 113, 139, 35, 66, 345 | 116, 192,117, 98, 346 | 124, 255,255,137, 347 | 168, 100,180,155, 348 | 255, 22,121,174}; 349 | 350 | // Gradient palette "Magenta_Evening_gp", originally from 351 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Magenta_Evening.png.index.html 352 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 353 | // Size: 28 bytes of program space. 354 | 355 | DEFINE_GRADIENT_PALETTE( Magenta_Evening_gp ) { 356 | 0, 71, 27, 39, 357 | 31, 130, 11, 51, 358 | 63, 213, 2, 64, 359 | 70, 232, 1, 66, 360 | 76, 252, 1, 69, 361 | 108, 123, 2, 51, 362 | 255, 46, 9, 35}; 363 | 364 | // Gradient palette "Pink_Purple_gp", originally from 365 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Pink_Purple.png.index.html 366 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 367 | // Size: 44 bytes of program space. 368 | 369 | DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) { 370 | 0, 19, 2, 39, 371 | 25, 26, 4, 45, 372 | 51, 33, 6, 52, 373 | 76, 68, 62,125, 374 | 102, 118,187,240, 375 | 109, 163,215,247, 376 | 114, 217,244,255, 377 | 122, 159,149,221, 378 | 149, 113, 78,188, 379 | 183, 128, 57,155, 380 | 255, 146, 40,123}; 381 | 382 | // Gradient palette "Sunset_Real_gp", originally from 383 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Real.png.index.html 384 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 385 | // Size: 28 bytes of program space. 386 | 387 | DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) { 388 | 0, 120, 0, 0, 389 | 22, 179, 22, 0, 390 | 51, 255,104, 0, 391 | 85, 167, 22, 18, 392 | 135, 100, 0,103, 393 | 198, 16, 0,130, 394 | 255, 0, 0,160}; 395 | 396 | // Gradient palette "es_autumn_19_gp", originally from 397 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/autumn/tn/es_autumn_19.png.index.html 398 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 399 | // Size: 52 bytes of program space. 400 | 401 | DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) { 402 | 0, 26, 1, 1, 403 | 51, 67, 4, 1, 404 | 84, 118, 14, 1, 405 | 104, 137,152, 52, 406 | 112, 113, 65, 1, 407 | 122, 133,149, 59, 408 | 124, 137,152, 52, 409 | 135, 113, 65, 1, 410 | 142, 139,154, 46, 411 | 163, 113, 13, 1, 412 | 204, 55, 3, 1, 413 | 249, 17, 1, 1, 414 | 255, 17, 1, 1}; 415 | 416 | // Gradient palette "BlacK_Blue_Magenta_White_gp", originally from 417 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Blue_Magenta_White.png.index.html 418 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 419 | // Size: 28 bytes of program space. 420 | 421 | DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) { 422 | 0, 0, 0, 0, 423 | 42, 0, 0, 45, 424 | 84, 0, 0,255, 425 | 127, 42, 0,255, 426 | 170, 255, 0,255, 427 | 212, 255, 55,255, 428 | 255, 255,255,255}; 429 | 430 | // Gradient palette "BlacK_Magenta_Red_gp", originally from 431 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Magenta_Red.png.index.html 432 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 433 | // Size: 20 bytes of program space. 434 | 435 | DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) { 436 | 0, 0, 0, 0, 437 | 63, 42, 0, 45, 438 | 127, 255, 0,255, 439 | 191, 255, 0, 45, 440 | 255, 255, 0, 0}; 441 | 442 | // Gradient palette "BlacK_Red_Magenta_Yellow_gp", originally from 443 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Red_Magenta_Yellow.png.index.html 444 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 445 | // Size: 28 bytes of program space. 446 | 447 | DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) { 448 | 0, 0, 0, 0, 449 | 42, 42, 0, 0, 450 | 84, 255, 0, 0, 451 | 127, 255, 0, 45, 452 | 170, 255, 0,255, 453 | 212, 255, 55, 45, 454 | 255, 255,255, 0}; 455 | 456 | // Gradient palette "Blue_Cyan_Yellow_gp", originally from 457 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/Blue_Cyan_Yellow.png.index.html 458 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 459 | // Size: 20 bytes of program space. 460 | 461 | DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) { 462 | 0, 0, 0,255, 463 | 63, 0, 55,255, 464 | 127, 0,255,255, 465 | 191, 42,255, 45, 466 | 255, 255,255, 0}; 467 | -------------------------------------------------------------------------------- /examples/ESPixelClock/hardware/ESPixel Clock Enclosure Bottom Drawing v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/hardware/ESPixel Clock Enclosure Bottom Drawing v1.pdf -------------------------------------------------------------------------------- /examples/ESPixelClock/hardware/ESPixel Clock Enclosure.3mf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/hardware/ESPixel Clock Enclosure.3mf -------------------------------------------------------------------------------- /examples/ESPixelClock/hardware/ESPixel Clock Enclosure.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/hardware/ESPixel Clock Enclosure.stl -------------------------------------------------------------------------------- /examples/ESPixelClock/js.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/js.7z -------------------------------------------------------------------------------- /examples/ESPixelClock/libspiffs.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/examples/ESPixelClock/libspiffs.a -------------------------------------------------------------------------------- /examples/ESPixelClock/palettes.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | // A mostly red palette with green accents and white trim. 26 | // "CRGB::Gray" is used as white to keep the brightness more uniform. 27 | const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM = 28 | { CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, 29 | CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, 30 | CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, 31 | CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green 32 | }; 33 | 34 | // A mostly (dark) green palette with red berries. 35 | #define Holly_Green 0x00580c 36 | #define Holly_Red 0xB00402 37 | const TProgmemRGBPalette16 Holly_p FL_PROGMEM = 38 | { Holly_Green, Holly_Green, Holly_Green, Holly_Green, 39 | Holly_Green, Holly_Green, Holly_Green, Holly_Green, 40 | Holly_Green, Holly_Green, Holly_Green, Holly_Green, 41 | Holly_Green, Holly_Green, Holly_Green, Holly_Red 42 | }; 43 | 44 | // A red and white striped palette 45 | // "CRGB::Gray" is used as white to keep the brightness more uniform. 46 | const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM = 47 | { CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, 48 | CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, 49 | CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, 50 | CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray 51 | }; 52 | 53 | // A mostly blue palette with white accents. 54 | // "CRGB::Gray" is used as white to keep the brightness more uniform. 55 | const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM = 56 | { CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 57 | CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 58 | CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 59 | CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray 60 | }; 61 | 62 | // A pure "fairy light" palette with some brightness variations 63 | #define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2) 64 | #define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4) 65 | const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM = 66 | { CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, 67 | HALFFAIRY, HALFFAIRY, CRGB::FairyLight, CRGB::FairyLight, 68 | QUARTERFAIRY, QUARTERFAIRY, CRGB::FairyLight, CRGB::FairyLight, 69 | CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight 70 | }; 71 | 72 | // A palette of soft snowflakes with the occasional bright one 73 | const TProgmemRGBPalette16 Snow_p FL_PROGMEM = 74 | { 0x304048, 0x304048, 0x304048, 0x304048, 75 | 0x304048, 0x304048, 0x304048, 0x304048, 76 | 0x304048, 0x304048, 0x304048, 0x304048, 77 | 0x304048, 0x304048, 0x304048, 0xE0F0FF 78 | }; 79 | 80 | // A palette reminiscent of large 'old-school' C9-size tree lights 81 | // in the five classic colors: red, orange, green, blue, and white. 82 | #define C9_Red 0xB80400 83 | #define C9_Orange 0x902C02 84 | #define C9_Green 0x046002 85 | #define C9_Blue 0x070758 86 | #define C9_White 0x606820 87 | const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM = 88 | { C9_Red, C9_Orange, C9_Red, C9_Orange, 89 | C9_Orange, C9_Red, C9_Orange, C9_Red, 90 | C9_Green, C9_Green, C9_Green, C9_Green, 91 | C9_Blue, C9_Blue, C9_Blue, 92 | C9_White 93 | }; 94 | 95 | // A cold, icy pale blue palette 96 | #define Ice_Blue1 0x0C1040 97 | #define Ice_Blue2 0x182080 98 | #define Ice_Blue3 0x5080C0 99 | const TProgmemRGBPalette16 IcyBlue_p FL_PROGMEM = 100 | { 101 | Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, 102 | Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, 103 | Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, 104 | Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3 105 | }; 106 | 107 | CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White); 108 | 109 | #include "gradientPalettes.h"; 110 | 111 | const CRGBPalette16 palettes[] = { 112 | RainbowColors_p, 113 | RainbowStripeColors_p, 114 | CloudColors_p, 115 | LavaColors_p, 116 | OceanColors_p, 117 | ForestColors_p, 118 | PartyColors_p, 119 | HeatColors_p, 120 | 121 | IceColors_p, 122 | IcyBlue_p, 123 | Snow_p, 124 | RedWhite_p, 125 | BlueWhite_p, 126 | FairyLight_p, 127 | RetroC9_p, 128 | RedGreenWhite_p, 129 | Holly_p, 130 | 131 | Sunset_Real_gp, 132 | es_rivendell_15_gp, 133 | es_ocean_breeze_036_gp, 134 | rgi_15_gp, 135 | retro2_16_gp, 136 | Analogous_1_gp, 137 | es_pinksplash_08_gp, 138 | Coral_reef_gp, 139 | es_ocean_breeze_068_gp, 140 | es_pinksplash_07_gp, 141 | es_vintage_01_gp, 142 | departure_gp, 143 | es_landscape_64_gp, 144 | es_landscape_33_gp, 145 | rainbowsherbet_gp, 146 | gr65_hult_gp, 147 | gr64_hult_gp, 148 | GMT_drywet_gp, 149 | ib_jul01_gp, 150 | es_vintage_57_gp, 151 | ib15_gp, 152 | Fuschia_7_gp, 153 | es_emerald_dragon_08_gp, 154 | lava_gp, 155 | fire_gp, 156 | Colorfull_gp, 157 | Magenta_Evening_gp, 158 | Pink_Purple_gp, 159 | es_autumn_19_gp, 160 | BlacK_Blue_Magenta_White_gp, 161 | BlacK_Magenta_Red_gp, 162 | BlacK_Red_Magenta_Yellow_gp, 163 | Blue_Cyan_Yellow_gp, 164 | }; 165 | 166 | const uint8_t paletteCount = ARRAY_SIZE(palettes); 167 | 168 | const String paletteNames[paletteCount] = { 169 | "Rainbow", 170 | "Rainbow Stripe", 171 | "Cloud", 172 | "Lava", 173 | "Ocean", 174 | "Forest", 175 | "Party", 176 | "Heat", 177 | 178 | "Ice", 179 | "Icy Blue", 180 | "Snow", 181 | "Red & White", 182 | "Blue & White", 183 | "Fairy", 184 | "Retro C9", 185 | "Red, Green & White", 186 | "Holly", 187 | 188 | "Sunset_Real", 189 | "es_rivendell_15", 190 | "es_ocean_breeze_036", 191 | "rgi_15", 192 | "retro2_16", 193 | "Analogous_1", 194 | "es_pinksplash_08", 195 | "Coral_reef", 196 | "es_ocean_breeze_068", 197 | "es_pinksplash_07", 198 | "es_vintage_01", 199 | "departure", 200 | "es_landscape_64", 201 | "es_landscape_33", 202 | "rainbowsherbet", 203 | "gr65_hult", 204 | "gr64_hult", 205 | "GMT_drywet", 206 | "ib_jul01", 207 | "es_vintage_57", 208 | "ib15", 209 | "Fuschia_7", 210 | "es_emerald_dragon_08", 211 | "lava", 212 | "fire", 213 | "Colorfull", 214 | "Magenta_Evening", 215 | "Pink_Purple", 216 | "es_autumn_19", 217 | "BlacK_Blue_Magenta_White", 218 | "BlacK_Magenta_Red", 219 | "BlacK_Red_Magenta_Yellow", 220 | "Blue_Cyan_Yellow", 221 | }; 222 | 223 | CRGBPalette16 currentPalette( CRGB::Black); 224 | CRGBPalette16 targetPalette( palettes[0] ); 225 | -------------------------------------------------------------------------------- /examples/ESPixelClock/patterns.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | #include "palettes.h"; 26 | #include "twinkleFox.h" 27 | #include "map.h" 28 | #include "noise.h" 29 | 30 | void rainbow() 31 | { 32 | // FastLED's built-in rainbow generator 33 | fill_rainbow( leds, NUM_LEDS, gHue, speed); 34 | } 35 | 36 | void addGlitter( fract8 chanceOfGlitter) 37 | { 38 | if ( random8() < chanceOfGlitter) { 39 | leds[ random16(NUM_LEDS) ] += CRGB::White; 40 | } 41 | } 42 | 43 | void rainbowWithGlitter() 44 | { 45 | // built-in FastLED rainbow, plus some random sparkly glitter 46 | rainbow(); 47 | addGlitter(80); 48 | } 49 | 50 | void confetti() 51 | { 52 | // random colored speckles that blink in and fade smoothly 53 | fadeToBlackBy( leds, NUM_LEDS, 10); 54 | int pos = random16(NUM_LEDS); 55 | leds[pos] += CHSV( gHue + random8(64), 200, 255); 56 | } 57 | 58 | void sinelon() 59 | { 60 | // a colored dot sweeping back and forth, with fading trails 61 | fadeToBlackBy( leds, NUM_LEDS, 20); 62 | int pos = beatsin16(speed, 0, NUM_LEDS - 1); 63 | static int prevpos = 0; 64 | CRGB color = ColorFromPalette(palettes[currentPaletteIndex], gHue, 255); 65 | if ( pos < prevpos ) { 66 | fill_solid( leds + pos, (prevpos - pos) + 1, color); 67 | } else { 68 | fill_solid( leds + prevpos, (pos - prevpos) + 1, color); 69 | } 70 | prevpos = pos; 71 | } 72 | 73 | void bpm() 74 | { 75 | // colored stripes pulsing at a defined Beats-Per-Minute (BPM) 76 | uint8_t beat = beatsin8( speed, 64, 255); 77 | CRGBPalette16 palette = palettes[currentPaletteIndex]; 78 | for ( int i = 0; i < NUM_LEDS; i++) { 79 | leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10)); 80 | } 81 | } 82 | 83 | void juggle() { 84 | // eight colored dots, weaving in and out of sync with each other 85 | fadeToBlackBy( leds, NUM_LEDS, 20); 86 | byte dothue = 0; 87 | for ( int i = 0; i < 8; i++) { 88 | leds[beatsin16( i + speed, 0, NUM_LEDS - 1 )] |= CHSV(dothue, 200, 255); 89 | dothue += 32; 90 | } 91 | } 92 | 93 | void showSolidColor() 94 | { 95 | fill_solid(leds, NUM_LEDS, solidColor); 96 | } 97 | 98 | // based on FastLED example Fire2012WithPalette: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino 99 | void heatMap(CRGBPalette16 palette, bool up) 100 | { 101 | fill_solid(leds, NUM_LEDS, CRGB::Black); 102 | 103 | // Add entropy to random number generator; we use a lot of it. 104 | random16_add_entropy(random(256)); 105 | 106 | // Array of temperature readings at each simulation cell 107 | static byte heat[NUM_LEDS]; 108 | 109 | byte colorindex; 110 | 111 | // Step 1. Cool down every cell a little 112 | for ( uint16_t i = 0; i < NUM_LEDS; i++) { 113 | heat[i] = qsub8( heat[i], random8(0, ((cooling * 10) / NUM_LEDS) + 2)); 114 | } 115 | 116 | // Step 2. Heat from each cell drifts 'up' and diffuses a little 117 | for ( uint16_t k = NUM_LEDS - 1; k >= 2; k--) { 118 | heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3; 119 | } 120 | 121 | // Step 3. Randomly ignite new 'sparks' of heat near the bottom 122 | if ( random8() < sparking ) { 123 | int y = random8(7); 124 | heat[y] = qadd8( heat[y], random8(160, 255) ); 125 | } 126 | 127 | // Step 4. Map from heat cells to LED colors 128 | for ( uint16_t j = 0; j < NUM_LEDS; j++) { 129 | // Scale the heat value from 0-255 down to 0-240 130 | // for best results with color palettes. 131 | colorindex = scale8(heat[j], 190); 132 | 133 | CRGB color = ColorFromPalette(palette, colorindex); 134 | 135 | if (up) { 136 | leds[j] = color; 137 | } 138 | else { 139 | leds[(NUM_LEDS - 1) - j] = color; 140 | } 141 | } 142 | } 143 | 144 | void fire() 145 | { 146 | heatMap(HeatColors_p, true); 147 | } 148 | 149 | void water() 150 | { 151 | heatMap(IceColors_p, false); 152 | } 153 | 154 | // Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5 155 | // This function draws rainbows with an ever-changing, 156 | // widely-varying set of parameters. 157 | void pride() 158 | { 159 | static uint16_t sPseudotime = 0; 160 | static uint16_t sLastMillis = 0; 161 | static uint16_t sHue16 = 0; 162 | 163 | uint8_t sat8 = beatsin88( 87, 220, 250); 164 | uint8_t brightdepth = beatsin88( 341, 96, 224); 165 | uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); 166 | uint8_t msmultiplier = beatsin88(147, 23, 60); 167 | 168 | uint16_t hue16 = sHue16;//gHue * 256; 169 | uint16_t hueinc16 = beatsin88(113, 1, 3000); 170 | 171 | uint16_t ms = millis(); 172 | uint16_t deltams = ms - sLastMillis ; 173 | sLastMillis = ms; 174 | sPseudotime += deltams * msmultiplier; 175 | sHue16 += deltams * beatsin88( 400, 5, 9); 176 | uint16_t brightnesstheta16 = sPseudotime; 177 | 178 | for ( uint16_t i = 0 ; i < NUM_LEDS; i++) { 179 | hue16 += hueinc16; 180 | uint8_t hue8 = hue16 / 256; 181 | 182 | brightnesstheta16 += brightnessthetainc16; 183 | uint16_t b16 = sin16( brightnesstheta16 ) + 32768; 184 | 185 | uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; 186 | uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; 187 | bri8 += (255 - brightdepth); 188 | 189 | CRGB newcolor = CHSV( hue8, sat8, bri8); 190 | 191 | uint16_t pixelnumber = i; 192 | pixelnumber = (NUM_LEDS - 1) - pixelnumber; 193 | 194 | nblend( leds[pixelnumber], newcolor, 64); 195 | } 196 | } 197 | 198 | // ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb 199 | // This function draws color waves with an ever-changing, 200 | // widely-varying set of parameters, using a color palette. 201 | void colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette) 202 | { 203 | static uint16_t sPseudotime = 0; 204 | static uint16_t sLastMillis = 0; 205 | static uint16_t sHue16 = 0; 206 | 207 | // uint8_t sat8 = beatsin88( 87, 220, 250); 208 | uint8_t brightdepth = beatsin88( 341, 96, 224); 209 | uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); 210 | uint8_t msmultiplier = beatsin88(147, 23, 60); 211 | 212 | uint16_t hue16 = sHue16;//gHue * 256; 213 | uint16_t hueinc16 = beatsin88(113, 300, 1500); 214 | 215 | uint16_t ms = millis(); 216 | uint16_t deltams = ms - sLastMillis ; 217 | sLastMillis = ms; 218 | sPseudotime += deltams * msmultiplier; 219 | sHue16 += deltams * beatsin88( 400, 5, 9); 220 | uint16_t brightnesstheta16 = sPseudotime; 221 | 222 | for ( uint16_t i = 0 ; i < numleds; i++) { 223 | hue16 += hueinc16; 224 | uint8_t hue8 = hue16 / 256; 225 | uint16_t h16_128 = hue16 >> 7; 226 | if ( h16_128 & 0x100) { 227 | hue8 = 255 - (h16_128 >> 1); 228 | } else { 229 | hue8 = h16_128 >> 1; 230 | } 231 | 232 | brightnesstheta16 += brightnessthetainc16; 233 | uint16_t b16 = sin16( brightnesstheta16 ) + 32768; 234 | 235 | uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; 236 | uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; 237 | bri8 += (255 - brightdepth); 238 | 239 | uint8_t index = hue8; 240 | //index = triwave8( index); 241 | index = scale8( index, 240); 242 | 243 | CRGB newcolor = ColorFromPalette( palette, index, bri8); 244 | 245 | uint16_t pixelnumber = i; 246 | pixelnumber = (numleds - 1) - pixelnumber; 247 | 248 | nblend( ledarray[pixelnumber], newcolor, 128); 249 | } 250 | } 251 | 252 | void colorWaves() 253 | { 254 | colorwaves(leds, NUM_LEDS, currentPalette); 255 | } 256 | 257 | void strandTest() 258 | { 259 | uint8_t i = speed; 260 | 261 | if (speed >= NUM_LEDS) speed = NUM_LEDS - 1; 262 | 263 | fill_solid(leds, NUM_LEDS, CRGB::Black); 264 | 265 | leds[i] = solidColor; 266 | } 267 | 268 | typedef void (*Pattern)(); 269 | typedef Pattern PatternList[]; 270 | typedef struct { 271 | Pattern pattern; 272 | String name; 273 | } PatternAndName; 274 | typedef PatternAndName PatternAndNameList[]; 275 | 276 | PatternAndNameList patterns = { 277 | { pride, "Pride" }, 278 | { colorWaves, "Color Waves" }, 279 | 280 | // matrix patterns 281 | { xyTest, "XY Test" }, 282 | { xPalette, "X Axis Palette" }, 283 | { yPalette, "Y Axis Palette" }, 284 | { xyPalette, "XY Axis Palette" }, 285 | { xGradientPalette, "X Axis Gradient Palette" }, 286 | { yGradientPalette, "Y Axis Gradient Palette" }, 287 | { xyGradientPalette, "XY Axis Gradient Palette" }, 288 | 289 | // noise patterns 290 | { fireNoise, "Fire Noise" }, 291 | { fireNoise2, "Fire Noise 2" }, 292 | { lavaNoise, "Lava Noise" }, 293 | { rainbowNoise, "Rainbow Noise" }, 294 | { rainbowStripeNoise, "Rainbow Stripe Noise" }, 295 | { partyNoise, "Party Noise" }, 296 | { forestNoise, "Forest Noise" }, 297 | { cloudNoise, "Cloud Noise" }, 298 | { oceanNoise, "Ocean Noise" }, 299 | { blackAndWhiteNoise, "Black & White Noise" }, 300 | { blackAndBlueNoise, "Black & Blue Noise" }, 301 | 302 | // TwinkleFOX patterns 303 | { drawTwinkles, "Twinkles" }, 304 | 305 | // Fire & Water 306 | { fire, "Fire" }, 307 | { water, "Water" }, 308 | 309 | // DemoReel100 patterns 310 | { rainbow, "rainbow" }, 311 | { rainbowWithGlitter, "rainbowWithGlitter" }, 312 | { confetti, "confetti" }, 313 | { sinelon, "sinelon" }, 314 | { juggle, "juggle" }, 315 | { bpm, "bpm" }, 316 | 317 | { strandTest, "Strand Test" }, 318 | 319 | { showSolidColor, "Solid Color" }, 320 | }; 321 | 322 | const uint8_t patternCount = ARRAY_SIZE(patterns); 323 | -------------------------------------------------------------------------------- /examples/ESPixelClock/temp.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/ESPixelClock/twinkleFox.h: -------------------------------------------------------------------------------- 1 | // TwinkleFOX by Mark Kriegsman: https://gist.github.com/kriegsman/756ea6dcae8e30845b5a 2 | // 3 | // TwinkleFOX: Twinkling 'holiday' lights that fade in and out. 4 | // Colors are chosen from a palette; a few palettes are provided. 5 | // 6 | // This December 2015 implementation improves on the December 2014 version 7 | // in several ways: 8 | // - smoother fading, compatible with any colors and any palettes 9 | // - easier control of twinkle speed and twinkle density 10 | // - supports an optional 'background color' 11 | // - takes even less RAM: zero RAM overhead per pixel 12 | // - illustrates a couple of interesting techniques (uh oh...) 13 | // 14 | // The idea behind this (new) implementation is that there's one 15 | // basic, repeating pattern that each pixel follows like a waveform: 16 | // The brightness rises from 0..255 and then falls back down to 0. 17 | // The brightness at any given point in time can be determined as 18 | // as a function of time, for example: 19 | // brightness = sine( time ); // a sine wave of brightness over time 20 | // 21 | // So the way this implementation works is that every pixel follows 22 | // the exact same wave function over time. In this particular case, 23 | // I chose a sawtooth triangle wave (triwave8) rather than a sine wave, 24 | // but the idea is the same: brightness = triwave8( time ). 25 | // 26 | // Of course, if all the pixels used the exact same wave form, and 27 | // if they all used the exact same 'clock' for their 'time base', all 28 | // the pixels would brighten and dim at once -- which does not look 29 | // like twinkling at all. 30 | // 31 | // So to achieve random-looking twinkling, each pixel is given a 32 | // slightly different 'clock' signal. Some of the clocks run faster, 33 | // some run slower, and each 'clock' also has a random offset from zero. 34 | // The net result is that the 'clocks' for all the pixels are always out 35 | // of sync from each other, producing a nice random distribution 36 | // of twinkles. 37 | // 38 | // The 'clock speed adjustment' and 'time offset' for each pixel 39 | // are generated randomly. One (normal) approach to implementing that 40 | // would be to randomly generate the clock parameters for each pixel 41 | // at startup, and store them in some arrays. However, that consumes 42 | // a great deal of precious RAM, and it turns out to be totally 43 | // unnessary! If the random number generate is 'seeded' with the 44 | // same starting value every time, it will generate the same sequence 45 | // of values every time. So the clock adjustment parameters for each 46 | // pixel are 'stored' in a pseudo-random number generator! The PRNG 47 | // is reset, and then the first numbers out of it are the clock 48 | // adjustment parameters for the first pixel, the second numbers out 49 | // of it are the parameters for the second pixel, and so on. 50 | // In this way, we can 'store' a stable sequence of thousands of 51 | // random clock adjustment parameters in literally two bytes of RAM. 52 | // 53 | // There's a little bit of fixed-point math involved in applying the 54 | // clock speed adjustments, which are expressed in eighths. Each pixel's 55 | // clock speed ranges from 8/8ths of the system clock (i.e. 1x) to 56 | // 23/8ths of the system clock (i.e. nearly 3x). 57 | // 58 | // On a basic Arduino Uno or Leonardo, this code can twinkle 300+ pixels 59 | // smoothly at over 50 updates per seond. 60 | // 61 | // -Mark Kriegsman, December 2015 62 | 63 | // Overall twinkle speed. 64 | // 0 (VERY slow) to 8 (VERY fast). 65 | // 4, 5, and 6 are recommended, default is 4. 66 | uint8_t twinkleSpeed = 4; 67 | 68 | // Overall twinkle density. 69 | // 0 (NONE lit) to 8 (ALL lit at once). 70 | // Default is 5. 71 | uint8_t twinkleDensity = 5; 72 | 73 | // Background color for 'unlit' pixels 74 | // Can be set to CRGB::Black if desired. 75 | CRGB gBackgroundColor = CRGB::Black; 76 | // Example of dim incandescent fairy light background color 77 | // CRGB gBackgroundColor = CRGB(CRGB::FairyLight).nscale8_video(16); 78 | 79 | // If AUTO_SELECT_BACKGROUND_COLOR is set to 1, 80 | // then for any palette where the first two entries 81 | // are the same, a dimmed version of that color will 82 | // automatically be used as the background color. 83 | #define AUTO_SELECT_BACKGROUND_COLOR 0 84 | 85 | // If COOL_LIKE_INCANDESCENT is set to 1, colors will 86 | // fade out slighted 'reddened', similar to how 87 | // incandescent bulbs change color as they get dim down. 88 | #define COOL_LIKE_INCANDESCENT 1 89 | 90 | // This function is like 'triwave8', which produces a 91 | // symmetrical up-and-down triangle sawtooth waveform, except that this 92 | // function produces a triangle wave with a faster attack and a slower decay: 93 | // 94 | // / \ 95 | // / \ 96 | // / \ 97 | // / \ 98 | // 99 | 100 | uint8_t attackDecayWave8( uint8_t i) 101 | { 102 | if( i < 86) { 103 | return i * 3; 104 | } else { 105 | i -= 86; 106 | return 255 - (i + (i/2)); 107 | } 108 | } 109 | 110 | // This function takes a pixel, and if its in the 'fading down' 111 | // part of the cycle, it adjusts the color a little bit like the 112 | // way that incandescent bulbs fade toward 'red' as they dim. 113 | void coolLikeIncandescent( CRGB& c, uint8_t phase) 114 | { 115 | if( phase < 128) return; 116 | 117 | uint8_t cooling = (phase - 128) >> 4; 118 | c.g = qsub8( c.g, cooling); 119 | c.b = qsub8( c.b, cooling * 2); 120 | } 121 | 122 | // This function takes a time in pseudo-milliseconds, 123 | // figures out brightness = f( time ), and also hue = f( time ) 124 | // The 'low digits' of the millisecond time are used as 125 | // input to the brightness wave function. 126 | // The 'high digits' are used to select a color, so that the color 127 | // does not change over the course of the fade-in, fade-out 128 | // of one cycle of the brightness wave function. 129 | // The 'high digits' are also used to determine whether this pixel 130 | // should light at all during this cycle, based on the twinkleDensity. 131 | CRGB computeOneTwinkle( uint32_t ms, uint8_t salt) 132 | { 133 | uint16_t ticks = ms >> (8-twinkleSpeed); 134 | uint8_t fastcycle8 = ticks; 135 | uint16_t slowcycle16 = (ticks >> 8) + salt; 136 | slowcycle16 += sin8( slowcycle16); 137 | slowcycle16 = (slowcycle16 * 2053) + 1384; 138 | uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8); 139 | 140 | uint8_t bright = 0; 141 | if( ((slowcycle8 & 0x0E)/2) < twinkleDensity) { 142 | bright = attackDecayWave8( fastcycle8); 143 | } 144 | 145 | uint8_t hue = slowcycle8 - salt; 146 | CRGB c; 147 | if( bright > 0) { 148 | c = ColorFromPalette( palettes[currentPaletteIndex], hue, bright, NOBLEND); 149 | if( COOL_LIKE_INCANDESCENT == 1 ) { 150 | coolLikeIncandescent( c, fastcycle8); 151 | } 152 | } else { 153 | c = CRGB::Black; 154 | } 155 | return c; 156 | } 157 | 158 | // This function loops over each pixel, calculates the 159 | // adjusted 'clock' that this pixel should use, and calls 160 | // "CalculateOneTwinkle" on each pixel. It then displays 161 | // either the twinkle color of the background color, 162 | // whichever is brighter. 163 | void drawTwinkles() 164 | { 165 | // "PRNG16" is the pseudorandom number generator 166 | // It MUST be reset to the same starting value each time 167 | // this function is called, so that the sequence of 'random' 168 | // numbers that it generates is (paradoxically) stable. 169 | uint16_t PRNG16 = 11337; 170 | 171 | uint32_t clock32 = millis(); 172 | 173 | CRGBPalette16 currentPalette = palettes[currentPaletteIndex]; 174 | 175 | // Set up the background color, "bg". 176 | // if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of 177 | // the current palette are identical, then a deeply faded version of 178 | // that color is used for the background color 179 | CRGB bg; 180 | if( (AUTO_SELECT_BACKGROUND_COLOR == 1) && 181 | (currentPalette[0] == currentPalette[1] )) { 182 | bg = currentPalette[0]; 183 | uint8_t bglight = bg.getAverageLight(); 184 | if( bglight > 64) { 185 | bg.nscale8_video( 16); // very bright, so scale to 1/16th 186 | } else if( bglight > 16) { 187 | bg.nscale8_video( 64); // not that bright, so scale to 1/4th 188 | } else { 189 | bg.nscale8_video( 86); // dim, scale to 1/3rd. 190 | } 191 | } else { 192 | bg = gBackgroundColor; // just use the explicitly defined background color 193 | } 194 | 195 | uint8_t backgroundBrightness = bg.getAverageLight(); 196 | 197 | for(uint16_t i = 0; i < NUM_LEDS; i++) { 198 | CRGB& pixel = leds[i]; 199 | 200 | PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number 201 | uint16_t myclockoffset16= PRNG16; // use that number as clock offset 202 | PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number 203 | // use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths) 204 | uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF)>>4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08; 205 | uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16; 206 | uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel 207 | 208 | // We now have the adjusted 'clock' for this pixel, now we call 209 | // the function that computes what color the pixel should be based 210 | // on the "brightness = f( time )" idea. 211 | CRGB c = computeOneTwinkle( myclock30, myunique8); 212 | 213 | uint8_t cbright = c.getAverageLight(); 214 | int16_t deltabright = cbright - backgroundBrightness; 215 | if( deltabright >= 32 || (!bg)) { 216 | // If the new pixel is significantly brighter than the background color, 217 | // use the new color. 218 | pixel = c; 219 | } else if( deltabright > 0 ) { 220 | // If the new pixel is just slightly brighter than the background color, 221 | // mix a blend of the new color and the background color 222 | pixel = blend( bg, c, deltabright * 8); 223 | } else { 224 | // if the new pixel is not at all brighter than the background color, 225 | // just use the background color. 226 | pixel = bg; 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /examples/ESPixelClock/web.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | //#include "compressed_html.h" 26 | //#include "combined_html.h" 27 | 28 | String processor(const String& var){ 29 | Serial.print(var+": "); 30 | char dateStr[13]; 31 | char timeStr[10]; 32 | sprintf(dateStr,"%04d-%02d-%02d", now.year(),now.month(), now.day()); 33 | sprintf(timeStr,"%02d:%02d:%02d",now.hour(), now.minute(), now.second()); 34 | 35 | if(var == "WIFIAP"){Serial.println(ssid);return String(ssid);} 36 | if(var == "PASSWORD"){Serial.println("*****");return String(password);} 37 | if(var == "NTPSERVER1"){Serial.println(ntpServer1);return String(ntpServer1);} 38 | if(var == "NTPSERVER2"){Serial.println(ntpServer2);return String(ntpServer2);} 39 | if(var == "TEMPERATURE"){Serial.println(temp);return String(temp);} 40 | if(var == "HUMIDITY"){Serial.println(rh);return String(rh);} 41 | if(var == "DATE"){Serial.println(dateStr);return String(dateStr);} 42 | if(var == "TIME"){Serial.println(timeStr);return String(timeStr);} 43 | if(var == "TIMEZONE"){Serial.println(tzInfo);return String(tzInfo);} 44 | if(var == "NAME"){Serial.println(clockName);return String(clockName);} 45 | return String(); //Return empty string if no matches 46 | } 47 | 48 | 49 | 50 | void setupWeb() { 51 | //ASYNC 52 | server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ 53 | request->send(200, "text/plain", String(ESP.getFreeHeap())); 54 | }); 55 | 56 | server.on("/all", HTTP_GET, [](AsyncWebServerRequest *request) { 57 | Serial.println("GET: /all"); 58 | String json = getFieldsJson(fields, fieldCount); 59 | request->send(200, "text/json", json); 60 | }); 61 | 62 | server.on("/fieldValue", HTTP_GET, [](AsyncWebServerRequest *request) { 63 | Serial.println("GET: /fieldValue"); 64 | String name = request->getParam(0)->name(); 65 | String value = getFieldValue(name, fields, fieldCount); 66 | request->send(200, "text/json", value); 67 | }); 68 | 69 | server.on("/fonts/glyphicons-halflings-regular.woff2", [](AsyncWebServerRequest *request) { 70 | request->redirect("http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.woff2"); 71 | request->send(301); 72 | }); 73 | 74 | server.on("/fonts/glyphicons-halflings-regular.woff", [](AsyncWebServerRequest *request) { 75 | request->redirect("http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.woff"); 76 | request->send(301);//, "text/html", ""); 77 | }); 78 | 79 | server.on("/fonts/glyphicons-halflings-regular.ttf", [](AsyncWebServerRequest *request) { 80 | request->redirect("http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.ttf"); 81 | request->send(301); 82 | }); 83 | 84 | server.on("/css/bootstrap.min.css.map", [](AsyncWebServerRequest *request) { 85 | request->redirect("http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css.map"); 86 | request->send(301);//, "text/html", ""); 87 | }); 88 | 89 | server.on("/css/jquery.minicolors.min.css.map", [](AsyncWebServerRequest *request) { 90 | request->redirect("https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.2.4/jquery.minicolors.min.css.map"); 91 | request->send(301); 92 | }); 93 | 94 | 95 | server.on("/fieldValue", HTTP_POST, [](AsyncWebServerRequest *request) { 96 | Serial.println("ASYNC POST: /fieldValue"); 97 | int paramsCount = request->params(); 98 | for(int i = 0; i< paramsCount; i++){ 99 | AsyncWebParameter* p = request->getParam(i); 100 | if(p->isFile()){ //p->isPost() is also true 101 | Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); 102 | } else if(p->isPost()){ 103 | Serial.printf("POST %d[%s]: %s\n", i,p->name().c_str(), p->value().c_str()); 104 | } else { 105 | Serial.printf("GET %d [%s]: %s\n", i,p->name().c_str(), p->value().c_str()); 106 | } 107 | } 108 | String name = request->getParam(0)->value(); 109 | String params,newValue; 110 | 111 | if (name == "solidColor"){ 112 | String r,g,b; 113 | r = request->getParam(2)->value(); 114 | g = request->getParam(3)->value(); 115 | b = request->getParam(4)->value(); 116 | Serial.println("RGB:" + r +" "+ g +" "+ b); 117 | params=r+","+g+","+b; //sprintf("%s,%s,%s",r,g,b); 118 | newValue = setFieldValueAsync(name, params, fields, fieldCount); 119 | } 120 | else { 121 | params = request->getParam(1)->value(); 122 | newValue = setFieldValueAsync(name, params, fields, fieldCount); 123 | } 124 | 125 | request->send(200, "text/json", newValue); 126 | }); 127 | 128 | server.on("/wifi.htm", HTTP_GET, [](AsyncWebServerRequest *request){ 129 | Serial.println("/wifi.htm"); 130 | request->send(SPIFFS, "/wifi.htm", String(), false, processor); 131 | }); 132 | 133 | server.on("/WIFIsubmit", HTTP_POST, [](AsyncWebServerRequest *request){ 134 | request->send(200, "text/plain", "Saved! Rebooting..."); 135 | preferences.begin("ESPixelClock",false); 136 | String recvDate, recvTime; 137 | for (int i = 0; i < request->params(); i++) { 138 | String name = request->getParam(i)->name(); 139 | String params = request->getParam(i)->value(); 140 | Serial.println(name + " : " + params); 141 | if (name == "WIFI_AP") { 142 | Serial.println("Saving Wifi creds"); 143 | ssid = params; 144 | preferences.putString("ssid",ssid); 145 | 146 | } else if (name == "WIFI_PASS") { 147 | password = params; 148 | preferences.putString("password",password); 149 | } else if (name == "NTP_SERVER1") { 150 | preferences.putString("ntpServer1",params); 151 | } else if (name == "NTP_SERVER2") { 152 | preferences.putString("ntpServer2",params); 153 | } else if (name == "TIMEZONE") { 154 | tzInfo = params; 155 | struct tm recvTime; 156 | preferences.putString("timezone",tzInfo); 157 | Serial.print("Tz selected: ");Serial.println(params); 158 | } else if (name == "DATE") { 159 | recvDate=params; 160 | } else if (name == "TIME") { 161 | recvTime=params; 162 | } else if (name == "NAME") { 163 | clockName=params; 164 | preferences.putString("clockName",params); 165 | } 166 | } 167 | preferences.end(); 168 | char buf[20]; 169 | strcpy(buf,(recvDate + " " + recvTime).c_str()); 170 | Serial.println(buf); 171 | struct tm timeinfo; 172 | 173 | if (strptime(buf, "%Y-%m-%d %T",&timeinfo) == NULL) 174 | Serial.printf("\nstrptime failed\n"); 175 | else 176 | { 177 | Serial.println(&timeinfo, "Submitted time: %A, %B %d %Y %H:%M:%S"); 178 | int hour = timeinfo.tm_hour; 179 | int minute = timeinfo.tm_min; 180 | int second = timeinfo.tm_sec; 181 | int day = timeinfo.tm_mday; 182 | int month = timeinfo.tm_mon + 1; 183 | int year = timeinfo.tm_year +1900; 184 | DS3231M.adjust(DateTime(year,month,day,hour,minute,second)); // Adjust the RTC date/time 185 | Serial.print(F("RTC time/date has been set.\n")); 186 | } 187 | Serial.print(F("Preferences updated, rebooting...\n\n\n\n\n")); 188 | delay(1000); 189 | ESP.restart(); 190 | }); 191 | 192 | 193 | // server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setTemplateProcessor(processor).setCacheControl("max-age=86400"); 194 | server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setCacheControl("max-age=86400"); 195 | 196 | server.onNotFound([](AsyncWebServerRequest *request){ 197 | Serial.printf("NOT_FOUND: "); 198 | if(request->method() == HTTP_GET) 199 | Serial.printf("GET"); 200 | else if(request->method() == HTTP_POST) 201 | Serial.printf("POST"); 202 | else if(request->method() == HTTP_DELETE) 203 | Serial.printf("DELETE"); 204 | else if(request->method() == HTTP_PUT) 205 | Serial.printf("PUT"); 206 | else if(request->method() == HTTP_PATCH) 207 | Serial.printf("PATCH"); 208 | else if(request->method() == HTTP_HEAD) 209 | Serial.printf("HEAD"); 210 | else if(request->method() == HTTP_OPTIONS) 211 | Serial.printf("OPTIONS"); 212 | else 213 | Serial.printf("UNKNOWN"); 214 | Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); 215 | 216 | if(request->contentLength()){ 217 | Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); 218 | Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); 219 | } 220 | 221 | int headers = request->headers(); 222 | int i; 223 | for(i=0;igetHeader(i); 225 | Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); 226 | } 227 | 228 | int params = request->params(); 229 | for(i=0;igetParam(i); 231 | if(p->isFile()){ 232 | Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); 233 | } else if(p->isPost()){ 234 | Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); 235 | } else { 236 | Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); 237 | } 238 | } 239 | 240 | request->send(404); 241 | }); 242 | 243 | server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ 244 | if(!index) 245 | Serial.printf("BodyStart: %u\n", total); 246 | Serial.printf("%s", (const char*)data); 247 | if(index + len == total) 248 | Serial.printf("BodyEnd: %u\n", total); 249 | }); 250 | server.begin(); 251 | 252 | } 253 | 254 | //void handleWeb() { 255 | // static bool webServerStarted = false; 256 | // esp_wifi_ap_get_sta_list(&stationList); 257 | // // check for connection 258 | // if ( WiFi.status() == WL_CONNECTED || stationList.num > 0) { 259 | // if (!webServerStarted) { 260 | // // turn off the board's LED when connected to wifi 261 | // 262 | // webServerStarted = true; 263 | // setupWeb(); 264 | // 265 | // //init and get the time 266 | //// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2); 267 | // } 268 | // 269 | // } else { 270 | // // blink the board's LED while connecting to wifi 271 | // 272 | // } 273 | //} 274 | -------------------------------------------------------------------------------- /examples/ESPixelClock/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 FastLED WebServer: https://github.com/jasoncoon/esp32-fastled-webserver 3 | Copyright (C) 2017 Jason Coon 4 | 5 | Built upon the amazing FastLED work of Daniel Garcia and Mark Kriegsman: 6 | https://github.com/FastLED/FastLED 7 | 8 | ESP32 support provided by the hard work of Sam Guyer: 9 | https://github.com/samguyer/FastLED 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | #define HOSTNAME "ESPixelClock " ///< Hostname. The setup function adds the Chip ID at the end. 26 | 27 | const bool apMode = true; 28 | 29 | // AP mode password 30 | const char WiFiAPPSK[] = "espixelclock"; 31 | 32 | void setupWifi() { 33 | // Set Hostname. 34 | String hostname(HOSTNAME); 35 | 36 | uint64_t chipid = ESP.getEfuseMac(); 37 | uint8_t mac = (uint8_t)(chipid>>40); 38 | String hex = String(mac, HEX); // six octets 39 | hostname += hex; 40 | 41 | char hostnameChar[hostname.length() + 1]; 42 | memset(hostnameChar, 0, hostname.length() + 1); 43 | 44 | for (uint8_t i = 0; i < hostname.length(); i++) 45 | hostnameChar[i] = hostname.charAt(i); 46 | 47 | WiFi.setHostname(hostnameChar); 48 | // Print hostname. 49 | Serial.println("Hostname: " + hostname); 50 | IPAddress Ip(192, 168, 1, 1); 51 | IPAddress NMask(255, 255, 255, 0); 52 | // WiFi.softAPConfig(Ip, Ip, NMask); 53 | 54 | 55 | Serial.println ("Trying SSID " + ssid + ": *******");// + password); 56 | WiFi.mode(WIFI_AP_STA); 57 | WiFi.begin(ssid.c_str(), password.c_str()); 58 | uint32_t timer=millis(); 59 | while (WiFi.status() != WL_CONNECTED) { 60 | delay(1000); 61 | Serial.println("Connecting to WiFi.."); 62 | if(millis()-timer>8000){ 63 | Serial.println("Giving up on " + String(ssid) + " after 8 seconds of trying."); 64 | WiFi.mode(WIFI_OFF); 65 | delay(100); 66 | WiFi.mode(WIFI_AP); 67 | int a=WiFi.softAP(hostnameChar, WiFiAPPSK); 68 | WiFi.softAPConfig(Ip, Ip, NMask); 69 | Serial.print("softap returned: ");Serial.println(a); 70 | Serial.printf("Connect to Wi-Fi access point: %s\n", hostnameChar); 71 | Serial.print("and open http://"); 72 | Serial.print(WiFi.softAPIP()); 73 | Serial.println("/ in your browser"); 74 | break; 75 | } 76 | } 77 | if (WiFi.status() == WL_CONNECTED){ 78 | Serial.print(" CONNECTED TO: " + String(ssid) + ", IP: "); 79 | Serial.println(WiFi.localIP()); 80 | 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /examples/matrix_test/Neo7SegmentClock_matrixtest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define PIN 18 6 | #define BRIGHTNESS 10 7 | 8 | #define mw 25 9 | #define mh 9 10 | #define NUMMATRIX (mw*mh) 11 | CRGB leds[NUMMATRIX]; 12 | // Define matrix width and height. 13 | FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, mw, mh, 14 | NEO_MATRIX_TOP + NEO_MATRIX_LEFT + 15 | NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE); 16 | 17 | // This could also be defined as matrix->color(255,0,0) but those defines 18 | // are meant to work for adafruit_gfx backends that are lacking color() 19 | #define LED_BLACK 0 20 | 21 | #define LED_RED_VERYLOW (3 << 11) 22 | #define LED_RED_LOW (7 << 11) 23 | #define LED_RED_MEDIUM (15 << 11) 24 | #define LED_RED_HIGH (31 << 11) 25 | 26 | #define LED_GREEN_VERYLOW (1 << 5) 27 | #define LED_GREEN_LOW (15 << 5) 28 | #define LED_GREEN_MEDIUM (31 << 5) 29 | #define LED_GREEN_HIGH (63 << 5) 30 | 31 | //PCB Layout: 32 | // .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 10 11.12 13 14 15 16 17 18 19 20 21 22 23 24 33 | // 0 .. .0 .1 .2 .. .. .. 21 22 23 .. .. .. .. .. 42 43 44 .. .. .. 63 64 65 .. 34 | // 1 17 .. .. .. .3 .. 38 .. .. .. 24 .. .. .. 59 .. .. .. 45 .. 80 .. .. .. 66 35 | // 2 16 .. .. .. .4 .. 37 .. .. .. 25 .. 84 .. 58 .. .. .. 46 .. 79 .. .. .. 67 36 | // 3 15 .. .. .. .5 .. 36 .. .. .. 26 .. .. .. 57 .. .. .. 47 .. 78 .. .. .. 68 37 | // 4 .. 18 19 20 .. .. .. 39 40 41 .. .. .. .. .. 60 61 62 .. .. .. 81 82 83 .. 38 | // 5 14 .. .. .. .6 .. 35 .. .. .. 27 .. .. .. 56 .. .. .. 48 .. 77 .. .. .. 69 39 | // 6 13 .. .. .. .7 .. 34 .. .. .. 28 .. 85 .. 55 .. .. .. 49 .. 76 .. .. .. 70 40 | // 7 12 .. .. .. .8 .. 33 .. .. .. 29 .. .. .. 54 .. .. .. 50 .. 75 .. .. .. 71 41 | // 8 .. 11 10 .9 .. .. .. 32 31 30 .. .. .. .. .. 53 52 51 .. .. .. 74 73 72 .. 42 | 43 | 44 | uint16_t myRemapFn(uint16_t x, uint16_t y) { 45 | switch(y){ 46 | case 0: 47 | switch(x){ 48 | case 1: return 0; 49 | case 2: return 1; 50 | case 3: return 2; 51 | case 7: return 21; 52 | case 8: return 22; 53 | case 9: return 23; 54 | case 15: return 42; 55 | case 16: return 43; 56 | case 17: return 44; 57 | case 21: return 63; 58 | case 22: return 64; 59 | case 23: return 65; 60 | default: return 86; 61 | } 62 | 63 | case 1: 64 | switch(x){ 65 | case 0: return 17; 66 | case 4: return 3; 67 | case 6: return 38; 68 | case 10: return 24; 69 | case 14: return 59; 70 | case 18: return 45; 71 | case 20: return 80; 72 | case 24: return 66; 73 | default: return 86; 74 | } 75 | case 2: 76 | switch(x){ 77 | case 0: return 16; 78 | case 4: return 4; 79 | case 6: return 37; 80 | case 10: return 25; 81 | case 12: return 84; 82 | case 14: return 58; 83 | case 18: return 46; 84 | case 20: return 79; 85 | case 24: return 67; 86 | default: return 86; 87 | } 88 | case 3: 89 | switch(x){ 90 | case 0: return 15; 91 | case 4: return 5; 92 | case 6: return 36; 93 | case 10: return 26; 94 | case 14: return 57; 95 | case 18: return 47; 96 | case 20: return 78; 97 | case 24: return 68; 98 | default: return 86; 99 | } 100 | case 4: 101 | switch(x){ 102 | case 1: return 18; 103 | case 2: return 19; 104 | case 3: return 20; 105 | case 7: return 39; 106 | case 8: return 40; 107 | case 9: return 41; 108 | case 15: return 60; 109 | case 16: return 61; 110 | case 17: return 62; 111 | case 21: return 81; 112 | case 22: return 82; 113 | case 23: return 83; 114 | default: return 86; 115 | } 116 | case 5: 117 | switch(x){ 118 | case 0: return 14; 119 | case 4: return 6; 120 | case 6: return 35; 121 | case 10: return 27; 122 | case 14: return 56; 123 | case 18: return 48; 124 | case 20: return 77; 125 | case 24: return 69; 126 | default: return 86; 127 | } 128 | case 6: 129 | switch(x){ 130 | case 0: return 13; 131 | case 4: return 7; 132 | case 6: return 34; 133 | case 10: return 28; 134 | case 12: return 85; 135 | case 14: return 55; 136 | case 18: return 49; 137 | case 20: return 76; 138 | case 24: return 70; 139 | default: return 86; 140 | } 141 | case 7: 142 | switch(x){ 143 | case 0: return 12; 144 | case 4: return 8; 145 | case 6: return 33; 146 | case 10: return 29; 147 | case 14: return 54; 148 | case 18: return 50; 149 | case 20: return 75; 150 | case 24: return 71; 151 | default: return 86; 152 | } 153 | case 8: 154 | switch(x){ 155 | case 1: return 11; 156 | case 2: return 10; 157 | case 3: return 9; 158 | case 7: return 32; 159 | case 8: return 31; 160 | case 9: return 30; 161 | case 15: return 53; 162 | case 16: return 52; 163 | case 17: return 51; 164 | case 21: return 74; 165 | case 22: return 73; 166 | case 23: return 72; 167 | default: return 86; 168 | } 169 | } 170 | } 171 | 172 | void scrolling_line(){ 173 | 174 | for (uint8_t i = 0;iclear(); 176 | matrix->drawLine(i,0,i,mh,LED_RED_HIGH); 177 | matrix->show(); 178 | delay(100); 179 | } 180 | for (uint8_t i = 0;iclear(); 182 | matrix->drawLine(0,i,mw,i,LED_GREEN_HIGH); 183 | matrix->show(); 184 | delay(100); 185 | } 186 | } 187 | 188 | void setup() { 189 | // put your setup code here, to run once: 190 | // Time for serial port to work? 191 | delay(1000); 192 | Serial.begin(115200); 193 | Serial.print("Init on pin: "); 194 | Serial.println(PIN); 195 | Serial.print("Matrix Size: "); 196 | Serial.print(mw); 197 | Serial.print(" "); 198 | Serial.print(mh); 199 | Serial.print(" "); 200 | Serial.println(NUMMATRIX); 201 | FastLED.addLeds( leds, NUMMATRIX ).setCorrection(TypicalLEDStrip); 202 | Serial.print("Setup serial: "); 203 | Serial.println(NUMMATRIX); 204 | matrix->begin(); 205 | matrix->setTextWrap(false); 206 | matrix->setBrightness(BRIGHTNESS); 207 | matrix->setRemapFunction(myRemapFn); 208 | } 209 | 210 | void loop() { 211 | // put your main code here, to run repeatedly: 212 | scrolling_line(); 213 | } 214 | -------------------------------------------------------------------------------- /examples/simple/Neo7SegmentClock.ino: -------------------------------------------------------------------------------- 1 | //*************************************************************** 2 | // A clock using pixels arranged in a 4-digit 7-segment display 3 | // 4 | // This example uses 3 Pixels Per Segment (pps). 5 | // 3pps x 7segments x 4digits + 2 digit colon = 86 pixels total 6 | // 7 | // 8 | // Based on 7Segment code by Marc Miller, (https://github.com/marmilicious/FastLED_examples/) 9 | // and ESP32 Simpletime example 10 | // 11 | // 12 | //*************************************************************** 13 | 14 | #include 15 | #include "secrets.h" //defines ssid, password, and ntpServer as const char* 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | CRGBPalette16 currentPalette; 23 | TBlendType currentBlending; 24 | 25 | const long gmtOffset_sec = -18000; //Eastern Time 26 | const int daylightOffset_sec = 3600; 27 | 28 | #define DATA_PIN 18 29 | #define CLK_PIN 13 30 | #define LED_TYPE WS2812 31 | #define COLOR_ORDER GRB 32 | #define NUM_LEDS 86 33 | #define BRIGHTNESS 10 34 | #define FRAMES_PER_SECOND 100 35 | #define LED_PIN 14 36 | #define BTN_PIN 15 37 | 38 | uint8_t pps = 3; // number of Pixels Per Segment 39 | CHSV segBlack(0,0,0); //black 40 | 41 | CRGBArray leds; 42 | 43 | // Name segments and define pixel ranges. 44 | // 1....2....3....4 45 | // AAA 46 | // F B 47 | // GGG 48 | // E C 49 | // DDD 50 | 51 | CRGBSet seg1A( leds(pps*0, pps-1+(pps*0) )); 52 | CRGBSet seg1B( leds(pps*1, pps-1+(pps*1) )); 53 | CRGBSet seg1C( leds(pps*2, pps-1+(pps*2) )); 54 | CRGBSet seg1D( leds(pps*3, pps-1+(pps*3) )); 55 | CRGBSet seg1E( leds(pps*4, pps-1+(pps*4) )); 56 | CRGBSet seg1F( leds(pps*5, pps-1+(pps*5) )); 57 | CRGBSet seg1G( leds(pps*6, pps-1+(pps*6) )); 58 | 59 | CRGBSet seg2A( leds(pps*0+(1*7*pps), pps-1+(pps*0)+(1*7*pps) )); 60 | CRGBSet seg2B( leds(pps*1+(1*7*pps), pps-1+(pps*1)+(1*7*pps) )); 61 | CRGBSet seg2C( leds(pps*2+(1*7*pps), pps-1+(pps*2)+(1*7*pps) )); 62 | CRGBSet seg2D( leds(pps*3+(1*7*pps), pps-1+(pps*3)+(1*7*pps) )); 63 | CRGBSet seg2E( leds(pps*4+(1*7*pps), pps-1+(pps*4)+(1*7*pps) )); 64 | CRGBSet seg2F( leds(pps*5+(1*7*pps), pps-1+(pps*5)+(1*7*pps) )); 65 | CRGBSet seg2G( leds(pps*6+(1*7*pps), pps-1+(pps*6)+(1*7*pps) )); 66 | 67 | CRGBSet seg3A( leds(pps*0+(2*7*pps), pps-1+(pps*0)+(2*7*pps) )); 68 | CRGBSet seg3B( leds(pps*1+(2*7*pps), pps-1+(pps*1)+(2*7*pps) )); 69 | CRGBSet seg3C( leds(pps*2+(2*7*pps), pps-1+(pps*2)+(2*7*pps) )); 70 | CRGBSet seg3D( leds(pps*3+(2*7*pps), pps-1+(pps*3)+(2*7*pps) )); 71 | CRGBSet seg3E( leds(pps*4+(2*7*pps), pps-1+(pps*4)+(2*7*pps) )); 72 | CRGBSet seg3F( leds(pps*5+(2*7*pps), pps-1+(pps*5)+(2*7*pps) )); 73 | CRGBSet seg3G( leds(pps*6+(2*7*pps), pps-1+(pps*6)+(2*7*pps) )); 74 | 75 | CRGBSet seg4A( leds(pps*0+(3*7*pps), pps-1+(pps*0)+(3*7*pps) )); 76 | CRGBSet seg4B( leds(pps*1+(3*7*pps), pps-1+(pps*1)+(3*7*pps) )); 77 | CRGBSet seg4C( leds(pps*2+(3*7*pps), pps-1+(pps*2)+(3*7*pps) )); 78 | CRGBSet seg4D( leds(pps*3+(3*7*pps), pps-1+(pps*3)+(3*7*pps) )); 79 | CRGBSet seg4E( leds(pps*4+(3*7*pps), pps-1+(pps*4)+(3*7*pps) )); 80 | CRGBSet seg4F( leds(pps*5+(3*7*pps), pps-1+(pps*5)+(3*7*pps) )); 81 | CRGBSet seg4G( leds(pps*6+(3*7*pps), pps-1+(pps*6)+(3*7*pps) )); 82 | 83 | CRGBSet col(leds(84,85)); //colon 84 | 85 | int count = 8888; // keeps track of what number to display 86 | 87 | 88 | //--------------------------------------------------------------- 89 | 90 | void printLocalTime() 91 | { 92 | struct tm timeinfo; 93 | if(!getLocalTime(&timeinfo)){ 94 | Serial.println("Failed to obtain time"); 95 | return; 96 | } 97 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 98 | count=(timeinfo.tm_hour*100+timeinfo.tm_min); 99 | } 100 | 101 | void setup() { 102 | Serial.begin(115200); // Allows serial monitor output 103 | pinMode(BTN_PIN,INPUT_PULLUP); 104 | pinMode(LED_PIN,OUTPUT); 105 | //connect to WiFi 106 | Serial.printf("Connecting to %s ", ssid); 107 | WiFi.mode(WIFI_STA); 108 | WiFi.begin(ssid, password); 109 | while (WiFi.status() != WL_CONNECTED) { 110 | delay(500); 111 | Serial.print("."); 112 | } 113 | Serial.println(" CONNECTED"); 114 | 115 | // Port defaults to 3232 116 | // ArduinoOTA.setPort(3232); 117 | 118 | // Hostname defaults to esp3232-[MAC] 119 | ArduinoOTA.setHostname("ESPixelClock1"); 120 | 121 | // No authentication by default 122 | ArduinoOTA.setPassword("admin123"); 123 | 124 | // Password can be set with it's md5 value as well 125 | // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 126 | // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); 127 | 128 | ArduinoOTA 129 | .onStart([]() { 130 | String type; 131 | if (ArduinoOTA.getCommand() == U_FLASH) 132 | type = "sketch"; 133 | else // U_SPIFFS 134 | type = "filesystem"; 135 | 136 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() 137 | Serial.println("Start updating " + type); 138 | }) 139 | .onEnd([]() { 140 | Serial.println("\nEnd"); 141 | }) 142 | .onProgress([](unsigned int progress, unsigned int total) { 143 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 144 | }) 145 | .onError([](ota_error_t error) { 146 | Serial.printf("Error[%u]: ", error); 147 | if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); 148 | else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); 149 | else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); 150 | else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); 151 | else if (error == OTA_END_ERROR) Serial.println("End Failed"); 152 | }); 153 | 154 | ArduinoOTA.begin(); 155 | 156 | //init and get the time 157 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 158 | printLocalTime(); 159 | 160 | 161 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalSMD5050); 162 | FastLED.setBrightness(BRIGHTNESS); 163 | currentPalette = RainbowColors_p; 164 | // currentPalette = CloudColors_p; 165 | // currentPalette = PartyColors_p; 166 | // currentPalette = ForestColors_p; 167 | // currentPalette = OceanColors_p; 168 | currentBlending = LINEARBLEND; 169 | FastLED.clear(); // Initially clear all pixels 170 | } 171 | 172 | bool colon; 173 | 174 | //--------------------------------------------------------------- 175 | void loop() 176 | { 177 | ArduinoOTA.handle(); 178 | 179 | static uint8_t startIndex = 0; 180 | EVERY_N_MILLISECONDS(50){ //motion speed: increase delay to slow down 181 | startIndex = startIndex + 1; 182 | } 183 | setSegments(count,startIndex); // Determine which segments are ON or OFF 184 | 185 | EVERY_N_MILLISECONDS(1000){ 186 | colon = !colon; //flash the colon 187 | 188 | } 189 | EVERY_N_MILLISECONDS(5000){ 190 | printLocalTime(); 191 | } 192 | EVERY_N_MINUTES(5){ 193 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); //get fresh NTP time 194 | } 195 | FastLED.delay(1000/FRAMES_PER_SECOND); 196 | // if(digitalRead(BTN_PIN)){ 197 | // digitalWrite(LED_PIN,HIGH); 198 | // Serial.println("BTN PRESSED"); 199 | // 200 | // } else { 201 | // digitalWrite(LED_PIN,LOW); 202 | // 203 | // } 204 | } 205 | 206 | //--------------------------------------------------------------- 207 | void setSegments(int count, uint8_t colorIndex){ 208 | // Based on the current count set number segments on or off 209 | uint8_t c1 = 0; // Variable to store 1s digit 210 | uint8_t c10 = 0; // Variable to store 10s digit 211 | uint8_t c100 = 0; // Variable to store 100s digit 212 | uint8_t c1000 = 0; // Variable to store 100s digit 213 | int c; 214 | CHSV segCOLOR(0,0,0); 215 | 216 | c1 = count % 10; 217 | c10 = (count / 10) % 10; 218 | c100 = (count / 100) % 10; 219 | c1000 = (count / 1000) % 10; 220 | 221 | // Serial.print("count = "); Serial.print(count); // Print to serial monitor current count 222 | // Serial.print("\t 1000s: "); Serial.print(c1000); // Print 1000s digit 223 | // Serial.print(" 100s: "); Serial.print(c100); // Print 100s digit 224 | // Serial.print(" 10s: "); Serial.print(c10); // Print 10s digit 225 | // Serial.print(" 1s: "); Serial.println(c1); // Print 1s digit 226 | 227 | uint8_t brightness = 255; 228 | 229 | for( int i = 0; i < NUM_LEDS; i++) { 230 | leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending); 231 | colorIndex += 3; 232 | } 233 | //next block of if statements sets segments to black to form digits 234 | segCOLOR = segBlack; //unused segment color 235 | if (c1000 == 0) { seg1G = segCOLOR; } 236 | if (c1000 == 1) { seg1A = seg1D = seg1E = seg1F = seg1G = segCOLOR; } 237 | if (c1000 == 2) { seg1C = seg1F = segCOLOR; } 238 | if (c1000 == 3) { seg1E = seg1F = segCOLOR; } 239 | if (c1000 == 4) { seg1A = seg1D = seg1E = segCOLOR; } 240 | if (c1000 == 5) { seg1B = seg1E = segCOLOR; } 241 | if (c1000 == 6) { seg1B = segCOLOR; } //B 242 | if (c1000 == 7) { seg1D = seg1E = seg1F = seg1G = segCOLOR; } 243 | if (c1000 == 8) { } 244 | if (c1000 == 9) { seg1D = seg1E = segCOLOR; } 245 | 246 | if (c100 == 0) { seg2G = segCOLOR; } 247 | if (c100 == 1) { seg2A = seg2D = seg2E = seg2F = seg2G = segCOLOR; } 248 | if (c100 == 2) { seg2C = seg2F = segCOLOR; } 249 | if (c100 == 3) { seg2E = seg2F = segCOLOR; } 250 | if (c100 == 4) { seg2A = seg2D = seg2E = segCOLOR; } 251 | if (c100 == 5) { seg2B = seg2E = segCOLOR; } 252 | if (c100 == 6) { seg2B = segCOLOR; } //B 253 | if (c100 == 7) { seg2D = seg2E = seg2F = seg2G = segCOLOR; } 254 | if (c100 == 8) { } 255 | if (c100 == 9) { seg2D = seg2E = segCOLOR; } 256 | 257 | if (c10 == 0) { seg3G = segCOLOR; } 258 | if (c10 == 1) { seg3A = seg3D = seg3E = seg3F = seg3G = segCOLOR; } 259 | if (c10 == 2) { seg3C = seg3F = segCOLOR; } 260 | if (c10 == 3) { seg3E = seg3F = segCOLOR; } 261 | if (c10 == 4) { seg3A = seg3D = seg3E = segCOLOR; } 262 | if (c10 == 5) { seg3B = seg3E = segCOLOR; } 263 | if (c10 == 6) { seg3B = segCOLOR; } //B 264 | if (c10 == 7) { seg3D = seg3E = seg3F = seg3G = segCOLOR; } 265 | if (c10 == 8) { } 266 | if (c10 == 9) { seg3D = seg3E = segCOLOR; } 267 | 268 | if (c1 == 0) { seg4G = segCOLOR; } 269 | if (c1 == 1) { seg4A = seg4D = seg4E = seg4F = seg4G = segCOLOR; } 270 | if (c1 == 2) { seg4C = seg4F = segCOLOR; } 271 | if (c1 == 3) { seg4E = seg4F = segCOLOR; } 272 | if (c1 == 4) { seg4A = seg4D = seg4E = segCOLOR; } 273 | if (c1 == 5) { seg4B = seg4E = segCOLOR; } 274 | if (c1 == 6) { seg4B = segCOLOR; } //B 275 | if (c1 == 7) { seg4D = seg4E = seg4F = seg4G = segCOLOR; } 276 | if (c1 == 8) { } 277 | if (c1 == 9) { seg4D = seg4E = segCOLOR; } 278 | 279 | if (colon){ 280 | // col = colON; //comment out to use palette color 281 | } else { 282 | col = CRGB::Black; //turns off colon to make it blink 283 | } 284 | 285 | 286 | // for (uint8_t p=0; p < NUM_LEDS;p++) { //prints the status of all LEDs for troubleshooting 287 | // Serial.print(leds[p]); 288 | // if((p+1) % (7*pps) == 0){ 289 | // Serial.print(" "); 290 | // } 291 | //} 292 | //Serial.println(); 293 | }//end setSegments 294 | -------------------------------------------------------------------------------- /examples/simple/Neo7SegmentCount.ino: -------------------------------------------------------------------------------- 1 | //*************************************************************** 2 | // Two digit seven segment number display example using CRGBArray and CRGBSet. 3 | // A number from 0-99 can be displayed. This demo repeats counting from 0 to 25. 4 | // 5 | // For this example the number segments are wired in the following layout: 6 | // http://imgur.com/cgabMfK 7 | // It also assumes that each segment has the same number of pixels. There is 8 | // a variable below which allows the number of pixels per segment to be changed. 9 | // 10 | // This example uses 5 Pixels Per Segment (pps). 11 | // 5pps x 7segments x 2digits = 70 pixels total 12 | // 13 | // 14 | // Marc Miller, Oct 2016 15 | // (There is also a 3digit version of this sketch now, added Feb 2019.) 16 | //*************************************************************** 17 | 18 | #include "FastLED.h" 19 | 20 | #define DATA_PIN 18 21 | #define CLK_PIN 13 22 | #define LED_TYPE WS2812 23 | #define COLOR_ORDER BGR 24 | #define NUM_LEDS 86 25 | #define BRIGHTNESS 10 26 | #define FRAMES_PER_SECOND 100 27 | 28 | uint8_t pps = 3; // number of Pixels Per Segment 29 | CHSV segON1000(10,200,255); // color of 1000s digit segments 30 | CHSV segON100(96,200,255); // color of 100s digit segments 31 | CHSV segON10(142,200,255); // color of 10s digit segments 32 | CHSV segON(42,255,255); // color of 1s digit segments 33 | 34 | /* CRGB leds[NUM_LEDS]; <--not using this. Using CRGBArray instead. */ 35 | CRGBArray leds; 36 | 37 | // Name segments (based on layout in link above) and define pixel ranges. 38 | CRGBSet segA( leds(pps*0, pps-1+(pps*0) )); 39 | CRGBSet segB( leds(pps*1, pps-1+(pps*1) )); 40 | CRGBSet segC( leds(pps*2, pps-1+(pps*2) )); 41 | CRGBSet segD( leds(pps*3, pps-1+(pps*3) )); 42 | CRGBSet segE( leds(pps*4, pps-1+(pps*4) )); 43 | CRGBSet segF( leds(pps*5, pps-1+(pps*5) )); 44 | CRGBSet segG( leds(pps*6, pps-1+(pps*6) )); 45 | 46 | int count = 950; // keeps track of what number to display 47 | 48 | 49 | //--------------------------------------------------------------- 50 | void setup() { 51 | Serial.begin(115200); // Allows serial monitor output (check baud rate) 52 | delay(3000); // 3 second delay for recovery 53 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 54 | // FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 55 | FastLED.setBrightness(BRIGHTNESS); 56 | FastLED.clear(); // Initially clear all pixels 57 | } 58 | 59 | 60 | //--------------------------------------------------------------- 61 | void loop() 62 | { 63 | EVERY_N_MILLISECONDS(100){ 64 | setSegments(count); // Determine which segments are ON or OFF 65 | count++; // Advance the count by one 66 | // if (count > 9999) { count = 0; } // Reset count back to zero 67 | } 68 | FastLED.delay(1000/FRAMES_PER_SECOND); 69 | } 70 | 71 | 72 | 73 | //--------------------------------------------------------------- 74 | void setSegments(int count){ 75 | // Based on the current count set number segments on or off 76 | uint8_t c1 = 0; // Variable to store 1s digit 77 | uint8_t c10 = 0; // Variable to store 10s digit 78 | uint8_t c100 = 0; // Variable to store 100s digit 79 | uint8_t c1000 = 0; // Variable to store 100s digit 80 | int c; 81 | CHSV segCOLOR(0,0,0); 82 | 83 | c1 = count % 10; 84 | c10 = (count / 10) % 10; 85 | c100 = (count / 100) % 10; 86 | c1000 = (count / 1000) % 10; 87 | 88 | Serial.print("count = "); Serial.print(count); // Print to serial monitor current count 89 | Serial.print("\t 1000s: "); Serial.print(c1000); // Print 1000s digit 90 | Serial.print(" 100s: "); Serial.print(c100); // Print 100s digit 91 | Serial.print(" 10s: "); Serial.print(c10); // Print 10s digit 92 | Serial.print(" 1s: "); Serial.println(c1); // Print 1s digit 93 | 94 | // Operate on 1s digit segments first, shift them over, 95 | // then 10's digit, and then do the 100s digit segments. 96 | for (uint8_t i=0; i < 4 ; i++) { 97 | if (i == 0) { 98 | c = c1; 99 | segCOLOR = segON; 100 | } 101 | if (i == 1) { 102 | c = c10; 103 | segCOLOR = segON10; 104 | } 105 | if (i == 2) { 106 | c = c100; 107 | segCOLOR = segON100; 108 | } 109 | if (i == 3) { 110 | c = c1000; 111 | segCOLOR = segON1000; 112 | } 113 | // Serial.print("i="); Serial.print(i); Serial.print(" c=");Serial.println(c); 114 | segA = segB = segC = segD = segE = segF = segG = CRGB::Black; // Initially set segments off 115 | 116 | if (c == 0) { segA = segB = segC = segD = segE = segF = segCOLOR; } 117 | if (c == 1) { segB = segC = segCOLOR; } 118 | if (c == 2) { segA = segB = segD = segE = segG = segCOLOR; } 119 | if (c == 3) { segA = segB = segC = segD = segG = segCOLOR; } 120 | if (c == 4) { segB = segC = segF = segG = segCOLOR; } 121 | if (c == 5) { segA = segC = segD = segF = segG = segCOLOR; } 122 | if (c == 6) { segA = segC = segD = segE = segF = segG = segCOLOR; } 123 | if (c == 7) { segA = segB = segC = segCOLOR; } 124 | if (c == 8) { segA = segB = segC = segD = segE = segF = segG = segCOLOR; } 125 | if (c == 9) { segA = segB = segC = segF = segG = segCOLOR; } 126 | 127 | if (i == 0) { // Shift segments over to 1s digit display area 128 | for (uint8_t p=0; p < (7*pps); p++) { 129 | leds[p+(3*7*pps)] = leds[p]; 130 | } 131 | } 132 | 133 | if (i == 1) { // Shift segments over to 10s digit display area 134 | for (uint8_t p=0; p < (7*pps); p++) { 135 | leds[p+(2*7*pps)] = leds[p]; 136 | } 137 | } 138 | 139 | if (i == 2) { // Shift segments over to 100s digit display area 140 | for (uint8_t p=0; p < (7*pps); p++) { 141 | leds[p+(1*7*pps)] = leds[p]; 142 | } 143 | } 144 | 145 | } 146 | for (uint8_t p=0; p < NUM_LEDS;p++) { 147 | Serial.print(leds[p]); 148 | if((p+1) % (7*pps) == 0){ 149 | Serial.print(" "); 150 | } 151 | } 152 | Serial.println(); 153 | }//end setSegments 154 | -------------------------------------------------------------------------------- /examples/simple/secrets.h: -------------------------------------------------------------------------------- 1 | const char* ssid = "xxx"; 2 | const char* password = "xxx"; 3 | const char* ntpServer = "192.168.1.100"; -------------------------------------------------------------------------------- /examples/simple/temp.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /hardware/ESPixelClock_Board.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/hardware/ESPixelClock_Board.stl -------------------------------------------------------------------------------- /hardware/Neo7Segment3535-bot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/hardware/Neo7Segment3535-bot.pdf -------------------------------------------------------------------------------- /hardware/Neo7Segment3535-sch2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/hardware/Neo7Segment3535-sch2.pdf -------------------------------------------------------------------------------- /hardware/Neo7Segment3535-top.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/hardware/Neo7Segment3535-top.pdf -------------------------------------------------------------------------------- /hardware/PixelMap.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattncsu/ESPixelClock/39e51f99fc57f5ac9512337b024f0ccb278cb591/hardware/PixelMap.xlsx -------------------------------------------------------------------------------- /hardware/temp.txt: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------