terrag42

Untitled

Apr 10th, 2017
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 33.07 KB | None | 0 0
  1. /*
  2. Spaceship Menorah Project https://hackaday.io/project/10148-spaceship-menorah  
  3.  Tree v2: https://github.com/evilgeniuslabs/tree-v2
  4.    Copyright (C) 2016 Jason Coon
  5.  
  6.    This program is free software: you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation, either version 3 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18. */
  19.  
  20. #include <FastLED.h>
  21. FASTLED_USING_NAMESPACE
  22.  
  23. extern "C" {
  24. #include "user_interface.h"
  25. }
  26.  
  27. #include <ESP8266WiFi.h>
  28. #include <ESP8266mDNS.h>
  29. #include <ESP8266WebServer.h>
  30. #include <ESP8266HTTPUpdateServer.h>
  31. #include <WebSocketsServer.h>
  32. #include <FS.h>
  33. #include <EEPROM.h>
  34. #include <IRremoteESP8266.h>
  35. #include "GradientPalettes.h"
  36.  
  37. #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
  38.  
  39. #include "Field.h"
  40.  
  41. #define HOSTNAME "ESP8266-" ///< Hostname. The setup function adds the Chip ID at the end.
  42.  
  43. #define RECV_PIN D0
  44. IRrecv irReceiver(RECV_PIN);
  45.  
  46. #include "Commands.h"
  47. #include "elapsedMillis.h"
  48.  
  49. const bool apMode = false;
  50.  
  51. // AP mode password
  52. const char WiFiAPPSK[] = "";
  53.  
  54. // Wi-Fi network to connect to (if not in AP mode)
  55. const char* ssid = "";
  56. const char* password = "";
  57.  
  58. ESP8266WebServer webServer(80);
  59. WebSocketsServer webSocketsServer = WebSocketsServer(81);
  60. ESP8266HTTPUpdateServer httpUpdateServer;
  61.  
  62. #include "FSBrowser.h"
  63.  
  64.  
  65. #define DATA_PIN      D6
  66. #define CLK_PIN       D7
  67. #define msg7RESET     D8   //digital pin (no PWM)
  68. #define msg7Strobe    D5 //digital pin (no PWM)
  69. #define LED_TYPE      P9813
  70. #define COLOR_ORDER   RGB
  71. #define NUM_LEDS      7
  72.  
  73. #define MILLI_AMPS         5000     // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
  74. #define FRAMES_PER_SECOND  240 // here you can control the speed. With the Access Point / Web Server the animations run a bit slower.
  75.  
  76. CRGB leds[NUM_LEDS];
  77.  
  78. uint8_t patternIndex = 0;
  79.  
  80. const uint8_t brightnessCount = 5;
  81. uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
  82. uint8_t brightnessIndex = 0;
  83.  
  84. // ten seconds per color palette makes a good demo
  85. // 20-120 is better for deployment
  86. uint8_t secondsPerPalette = 10;
  87.  
  88. // COOLING: How much does the air cool as it rises?
  89. // Less cooling = taller flames.  More cooling = shorter flames.
  90. // Default 50, suggested range 20-100
  91. uint8_t cooling = 49;
  92.  
  93. // SPARKING: What chance (out of 255) is there that a new spark will be lit?
  94. // Higher chance = more roaring fire.  Lower chance = more flickery fire.
  95. // Default 120, suggested range 50-200.
  96. uint8_t sparking = 60;
  97.  
  98. uint8_t speed = 30;
  99.  
  100. ///////////////////////////////////////////////////////////////////////
  101.  
  102. // Forward declarations of an array of cpt-city gradient palettes, and
  103. // a count of how many there are.  The actual color palette definitions
  104. // are at the bottom of this file.
  105. extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
  106.  
  107. uint8_t gCurrentPaletteNumber = 0;
  108.  
  109. CRGBPalette16 gCurrentPalette( CRGB::Black);
  110. CRGBPalette16 gTargetPalette( gGradientPalettes[0] );
  111.  
  112. CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);
  113.  
  114. uint8_t currentPatternIndex = 0; // Index number of which pattern is current
  115. uint8_t autoplay = 0;
  116.  
  117. uint8_t autoplayDuration = 10;
  118. unsigned long autoPlayTimeout = 0;
  119.  
  120. uint8_t gHue = 0; // rotating "base color" used by many of the patterns
  121.  
  122. CRGB solidColor = CRGB::Blue;
  123.  
  124. //uint8_t paletteIndex = 0;
  125. //
  126. //// List of palettes to cycle through.
  127. //CRGBPalette16 palettes[] =
  128. //{
  129. //  RainbowColors_p,
  130. //  /*RainbowStripeColors_p,*/
  131. //  CloudColors_p,
  132. //  OceanColors_p,
  133. //  ForestColors_p,
  134. //  HeatColors_p,
  135. //  LavaColors_p,
  136. //  PartyColors_p,
  137. //  IceColors_p,
  138. //};
  139. //
  140. //uint8_t paletteCount = ARRAY_SIZE(palettes);
  141. //
  142. //CRGBPalette16 currentPalette(CRGB::Black);
  143. //CRGBPalette16 targetPalette = palettes[paletteIndex];
  144.  
  145. // scale the brightness of all pixels down
  146. void dimAll(byte value)
  147. {
  148.   for (int i = 0; i < NUM_LEDS; i++) {
  149.     leds[i].nscale8(value);
  150.   }
  151. }
  152.  
  153. typedef void (*Pattern)();
  154. typedef Pattern PatternList[];
  155. typedef struct {
  156.   Pattern pattern;
  157.   String name;
  158. } PatternAndName;
  159. typedef PatternAndName PatternAndNameList[];
  160.  
  161. #include "Twinkles.h"
  162. #include "TwinkleFOX.h"
  163. //#include "Noise.h"
  164.  
  165. // List of patterns to cycle through.  Each is defined as a separate function below.
  166.  
  167. PatternAndNameList patterns = {
  168.   { pride,                  "Pride" },
  169.   { colorWaves,             "Color Waves" },
  170.    // twinkle patterns
  171.   { rainbowTwinkles,        "Rainbow Twinkles" },
  172.   { snowTwinkles,           "Snow Twinkles" },
  173.   { cloudTwinkles,          "Cloud Twinkles" },
  174.   { incandescentTwinkles,   "Incandescent Twinkles" },
  175.  
  176.   // TwinkleFOX patterns
  177.   { retroC9Twinkles,        "Retro C9 Twinkles" },
  178.   { redWhiteTwinkles,       "Red & White Twinkles" },
  179.   { blueWhiteTwinkles,      "Blue & White Twinkles" },
  180.   { redGreenWhiteTwinkles,  "Red, Green & White Twinkles" },
  181.   { fairyLightTwinkles,     "Fairy Light Twinkles" },
  182.   { snow2Twinkles,          "Snow 2 Twinkles" },
  183.   { hollyTwinkles,          "Holly Twinkles" },
  184.   { iceTwinkles,            "Ice Twinkles" },
  185.   { partyTwinkles,          "Party Twinkles" },
  186.   { forestTwinkles,         "Forest Twinkles" },
  187.   { lavaTwinkles,           "Lava Twinkles" },
  188.   { fireTwinkles,           "Fire Twinkles" },
  189.   { cloud2Twinkles,         "Cloud 2 Twinkles" },
  190.   { oceanTwinkles,          "Ocean Twinkles" },
  191.  
  192.   /* noise patterns
  193.   { fireNoise, "Fire Noise" },
  194.   { fireNoise2, "Fire Noise 2" },
  195.   { lavaNoise, "Lava Noise" },
  196.   { rainbowNoise, "Rainbow Noise" },
  197.   { rainbowStripeNoise, "Rainbow Stripe Noise" },
  198.   { partyNoise, "Party Noise" },
  199.   { forestNoise, "Forest Noise" },
  200.   { cloudNoise, "Cloud Noise" },
  201.   { oceanNoise, "Ocean Noise" },
  202.   { blackAndWhiteNoise, "Black & White Noise" },
  203.   { blackAndBlueNoise, "Black & Blue Noise" },
  204.   */
  205.   { rainbow,                "Rainbow" },
  206.   { rainbowWithGlitter,     "Rainbow With Glitter" },
  207.   { rainbowSolid,           "Solid Rainbow" },
  208.   { confetti,               "Confetti" },
  209.   { sinelon,                "Sinelon" },
  210.   { bpm,                    "Beat" },
  211.   { juggle,                 "Juggle" },
  212.   { fire,                   "Fire" },
  213.   { water,                  "Water" },
  214.   //  { draw,                   "Draw" },
  215.   { showSolidColor,         "Solid Color" }
  216. };
  217.  
  218. const uint8_t patternCount = ARRAY_SIZE(patterns);
  219.  
  220. #include "Fields.h"
  221.  
  222. void setup() {
  223.   Serial.begin(115200);
  224.   delay(100);
  225.   Serial.setDebugOutput(true);
  226.  
  227.  // FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);         // for WS2812 (Neopixel)
  228.   FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS); // for APA102 (Dotstar)
  229.   FastLED.setDither(false);
  230.   FastLED.setCorrection(TypicalLEDStrip);
  231.   FastLED.setBrightness(brightness);
  232.   FastLED.setMaxPowerInVoltsAndMilliamps(5, MILLI_AMPS);
  233.   fill_solid(leds, NUM_LEDS, CRGB::Black);
  234.   FastLED.show();
  235.  
  236.   EEPROM.begin(512);
  237.   loadSettings();
  238.  
  239.   FastLED.setBrightness(brightness);
  240.  
  241.   irReceiver.enableIRIn(); // Start the receiver
  242.  
  243.   Serial.println();
  244.   Serial.print( F("Heap: ") ); Serial.println(system_get_free_heap_size());
  245.   Serial.print( F("Boot Vers: ") ); Serial.println(system_get_boot_version());
  246.   Serial.print( F("CPU: ") ); Serial.println(system_get_cpu_freq());
  247.   Serial.print( F("SDK: ") ); Serial.println(system_get_sdk_version());
  248.   Serial.print( F("Chip ID: ") ); Serial.println(system_get_chip_id());
  249.   Serial.print( F("Flash ID: ") ); Serial.println(spi_flash_get_id());
  250.   Serial.print( F("Flash Size: ") ); Serial.println(ESP.getFlashChipRealSize());
  251.   Serial.print( F("Vcc: ") ); Serial.println(ESP.getVcc());
  252.   Serial.println();
  253.  
  254.   SPIFFS.begin();
  255.   {
  256.     Dir dir = SPIFFS.openDir("/");
  257.     while (dir.next()) {
  258.       String fileName = dir.fileName();
  259.       size_t fileSize = dir.fileSize();
  260.       Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), String(fileSize).c_str());
  261.     }
  262.     Serial.printf("\n");
  263.   }
  264.  
  265.   // Set Hostname.
  266.   String hostname(HOSTNAME);
  267.   hostname += String(ESP.getChipId(), HEX);
  268.   WiFi.hostname(hostname);
  269.  
  270.   char hostnameChar[hostname.length() + 1];
  271.   memset(hostnameChar, 0, hostname.length() + 1);
  272.  
  273.   for (uint8_t i = 0; i < hostname.length(); i++)
  274.     hostnameChar[i] = hostname.charAt(i);
  275.  
  276.   MDNS.begin(hostnameChar);
  277.  
  278.   // Add service to MDNS-SD
  279.   MDNS.addService("http", "tcp", 80);
  280.  
  281.   // Print hostname.
  282.   Serial.println("Hostname: " + hostname);
  283.  
  284.   if (apMode)
  285.   {
  286.     WiFi.mode(WIFI_AP);
  287.  
  288.     // Do a little work to get a unique-ish name. Append the
  289.     // last two bytes of the MAC (HEX'd) to "Thing-":
  290.     uint8_t mac[WL_MAC_ADDR_LENGTH];
  291.     WiFi.softAPmacAddress(mac);
  292.     String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
  293.                    String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
  294.     macID.toUpperCase();
  295.     String AP_NameString = "ESP8266-" + macID;
  296.  
  297.     char AP_NameChar[AP_NameString.length() + 1];
  298.     memset(AP_NameChar, 0, AP_NameString.length() + 1);
  299.  
  300.     for (int i = 0; i < AP_NameString.length(); i++)
  301.       AP_NameChar[i] = AP_NameString.charAt(i);
  302.  
  303.     WiFi.softAP(AP_NameChar, WiFiAPPSK);
  304.  
  305.     Serial.printf("Connect to Wi-Fi access point: %s\n", AP_NameChar);
  306.     Serial.println("and open http://192.168.4.1 in your browser");
  307.   }
  308.   else
  309.   {
  310.     Serial.printf("Connecting to %s\n", ssid);
  311.     if (String(WiFi.SSID()) != String(ssid)) {
  312.       WiFi.begin(ssid, password);
  313.     }
  314.   }
  315.  
  316.   httpUpdateServer.setup(&webServer);
  317.  
  318.   webServer.on("/all", HTTP_GET, []() {
  319.     String json = getFieldsJson(fields, fieldCount);
  320.     webServer.send(200, "text/json", json);
  321.   });
  322.  
  323.   webServer.on("/fieldValue", HTTP_GET, []() {
  324.     String name = webServer.arg("name");
  325.     String value = getFieldValue(name, fields, fieldCount);
  326.     webServer.send(200, "text/json", value);
  327.   });
  328.  
  329.   webServer.on("/fieldValue", HTTP_POST, []() {
  330.     String name = webServer.arg("name");
  331.     String value = webServer.arg("value");
  332.     String newValue = setFieldValue(name, value, fields, fieldCount);
  333.     webServer.send(200, "text/json", newValue);
  334.   });
  335.  
  336.   webServer.on("/power", HTTP_POST, []() {
  337.     String value = webServer.arg("value");
  338.     setPower(value.toInt());
  339.     sendInt(power);
  340.   });
  341.  
  342.   webServer.on("/cooling", HTTP_POST, []() {
  343.     String value = webServer.arg("value");
  344.     cooling = value.toInt();
  345.     broadcastInt("cooling", cooling);
  346.     sendInt(cooling);
  347.   });
  348.  
  349.   webServer.on("/sparking", HTTP_POST, []() {
  350.     String value = webServer.arg("value");
  351.     sparking = value.toInt();
  352.     broadcastInt("sparking", sparking);
  353.     sendInt(sparking);
  354.   });
  355.  
  356.   webServer.on("/speed", HTTP_POST, []() {
  357.     String value = webServer.arg("value");
  358.     speed = value.toInt();
  359.     broadcastInt("speed", speed);
  360.     sendInt(speed);
  361.   });
  362.  
  363.   webServer.on("/solidColor", HTTP_POST, []() {
  364.     String r = webServer.arg("r");
  365.     String g = webServer.arg("g");
  366.     String b = webServer.arg("b");
  367.     setSolidColor(r.toInt(), g.toInt(), b.toInt());
  368.     sendString(String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
  369.   });
  370.  
  371.   webServer.on("/pattern", HTTP_POST, []() {
  372.     String value = webServer.arg("value");
  373.     setPattern(value.toInt());
  374.     sendInt(currentPatternIndex);
  375.   });
  376.  
  377.   webServer.on("/brightness", HTTP_POST, []() {
  378.     String value = webServer.arg("value");
  379.     setBrightness(value.toInt());
  380.     sendInt(brightness);
  381.   });
  382.  
  383.   webServer.on("/autoplay", HTTP_POST, []() {
  384.     String value = webServer.arg("value");
  385.     setAutoplay(value.toInt());
  386.     sendInt(autoplay);
  387.   });
  388.  
  389.   webServer.on("/autoplayDuration", HTTP_POST, []() {
  390.     String value = webServer.arg("value");
  391.     setAutoplayDuration(value.toInt());
  392.     sendInt(autoplayDuration);
  393.   });
  394.  
  395.   //list directory
  396.   webServer.on("/list", HTTP_GET, handleFileList);
  397.   //load editor
  398.   webServer.on("/edit", HTTP_GET, []() {
  399.     if (!handleFileRead("/edit.htm")) webServer.send(404, "text/plain", "FileNotFound");
  400.   });
  401.   //create file
  402.   webServer.on("/edit", HTTP_PUT, handleFileCreate);
  403.   //delete file
  404.   webServer.on("/edit", HTTP_DELETE, handleFileDelete);
  405.   //first callback is called after the request has ended with all parsed arguments
  406.   //second callback handles file uploads at that location
  407.   webServer.on("/edit", HTTP_POST, []() {
  408.     webServer.send(200, "text/plain", "");
  409.   }, handleFileUpload);
  410.  
  411.   webServer.serveStatic("/", SPIFFS, "/", "max-age=86400");
  412.  
  413.   webServer.begin();
  414.   Serial.println("HTTP web server started");
  415.  
  416.   webSocketsServer.begin();
  417.   webSocketsServer.onEvent(webSocketEvent);
  418.   Serial.println("Web socket server started");
  419.  
  420.   autoPlayTimeout = millis() + (autoplayDuration * 1000);
  421. }
  422.  
  423. void sendInt(uint8_t value)
  424. {
  425.   sendString(String(value));
  426. }
  427.  
  428. void sendString(String value)
  429. {
  430.   webServer.send(200, "text/plain", value);
  431. }
  432.  
  433. void broadcastInt(String name, uint8_t value)
  434. {
  435.   String json = "{\"name\":\"" + name + "\",\"value\":" + String(value) + "}";
  436.   webSocketsServer.broadcastTXT(json);
  437. }
  438.  
  439. void broadcastString(String name, String value)
  440. {
  441.   String json = "{\"name\":\"" + name + "\",\"value\":\"" + String(value) + "\"}";
  442.   webSocketsServer.broadcastTXT(json);
  443. }
  444.  
  445. void loop() {
  446.   // Add entropy to random number generator; we use a lot of it.
  447.   random16_add_entropy(random(65535));
  448.  
  449.   webSocketsServer.loop();
  450.   webServer.handleClient();
  451.  
  452.   handleIrInput();
  453.  
  454.   if (power == 0) {
  455.     fill_solid(leds, NUM_LEDS, CRGB::Black);
  456.     FastLED.show();
  457.     FastLED.delay(15);
  458.     return;
  459.   }
  460.  
  461. //   EVERY_N_SECONDS(10) {
  462. //     Serial.print( F("Heap: ") ); Serial.println(system_get_free_heap_size());
  463. //   }
  464.  
  465.   // change to a new cpt-city gradient palette
  466.   EVERY_N_SECONDS( secondsPerPalette ) {
  467.     gCurrentPaletteNumber = addmod8( gCurrentPaletteNumber, 1, gGradientPaletteCount);
  468. //    gTargetPalette = gGradientPalettes[ gCurrentPaletteNumber ];
  469.  
  470. //    paletteIndex = addmod8( paletteIndex, 1, paletteCount);
  471. //    targetPalette = palettes[paletteIndex];
  472.   }
  473.  
  474.   EVERY_N_MILLISECONDS(40) {
  475.     // slowly blend the current palette to the next
  476.     nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 16);
  477. //    nblendPaletteTowardPalette(currentPalette, targetPalette, 16);
  478.     gHue++;  // slowly cycle the "base color" through the rainbow
  479.   }
  480.  
  481.   if (autoplay && (millis() > autoPlayTimeout)) {
  482.     adjustPattern(true);
  483.     autoPlayTimeout = millis() + (autoplayDuration * 1000);
  484.   }
  485.  
  486.   // Call the current pattern function once, updating the 'leds' array
  487.   patterns[currentPatternIndex].pattern();
  488.  
  489.   FastLED.show();
  490.  
  491.   // insert a delay to keep the framerate modest
  492.   FastLED.delay(1000 / FRAMES_PER_SECOND);
  493. }
  494.  
  495. void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
  496.  
  497.   switch (type) {
  498.     case WStype_DISCONNECTED:
  499.       Serial.printf("[%u] Disconnected!\n", num);
  500.       break;
  501.      
  502.     case WStype_CONNECTED:
  503.       {
  504.         IPAddress ip = webSocketsServer.remoteIP(num);
  505.         Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
  506.  
  507.         // send message to client
  508.         // webSocketsServer.sendTXT(num, "Connected");
  509.       }
  510.       break;
  511.      
  512.     case WStype_TEXT:
  513.       Serial.printf("[%u] get Text: %s\n", num, payload);
  514.  
  515.       // send message to client
  516.       // webSocketsServer.sendTXT(num, "message here");
  517.  
  518.       // send data to all connected clients
  519.       // webSocketsServer.broadcastTXT("message here");
  520.       break;
  521.      
  522.     case WStype_BIN:
  523.       Serial.printf("[%u] get binary length: %u\n", num, length);
  524.       hexdump(payload, length);
  525.  
  526.       // send message to client
  527.       // webSocketsServer.sendBIN(num, payload, lenght);
  528.       break;
  529.   }
  530. }
  531.  
  532. void handleIrInput()
  533. {
  534.   InputCommand command = readCommand(defaultHoldDelay);
  535.  
  536.   if (command != InputCommand::None) {
  537.     Serial.print("command: ");
  538.     Serial.println((int) command);
  539.   }
  540.  
  541.   switch (command) {
  542.     case InputCommand::Up: {
  543.         adjustPattern(true);
  544.         break;
  545.       }
  546.     case InputCommand::Down: {
  547.         adjustPattern(false);
  548.         break;
  549.       }
  550.     case InputCommand::Power: {
  551.         setPower(power == 0 ? 1 : 0);
  552.         break;
  553.       }
  554.     case InputCommand::BrightnessUp: {
  555.         adjustBrightness(true);
  556.         break;
  557.       }
  558.     case InputCommand::BrightnessDown: {
  559.         adjustBrightness(false);
  560.         break;
  561.       }
  562.     case InputCommand::PlayMode: { // toggle pause/play
  563.         setAutoplay(!autoplay);
  564.         break;
  565.       }
  566.  
  567.     // pattern buttons
  568.  
  569.     case InputCommand::Pattern1: {
  570.         setPattern(0);
  571.         break;
  572.       }
  573.     case InputCommand::Pattern2: {
  574.         setPattern(1);
  575.         break;
  576.       }
  577.     case InputCommand::Pattern3: {
  578.         setPattern(2);
  579.         break;
  580.       }
  581.     case InputCommand::Pattern4: {
  582.         setPattern(3);
  583.         break;
  584.       }
  585.     case InputCommand::Pattern5: {
  586.         setPattern(4);
  587.         break;
  588.       }
  589.     case InputCommand::Pattern6: {
  590.         setPattern(5);
  591.         break;
  592.       }
  593.     case InputCommand::Pattern7: {
  594.         setPattern(6);
  595.         break;
  596.       }
  597.     case InputCommand::Pattern8: {
  598.         setPattern(7);
  599.         break;
  600.       }
  601.     case InputCommand::Pattern9: {
  602.         setPattern(8);
  603.         break;
  604.       }
  605.     case InputCommand::Pattern10: {
  606.         setPattern(9);
  607.         break;
  608.       }
  609.     case InputCommand::Pattern11: {
  610.         setPattern(10);
  611.         break;
  612.       }
  613.     case InputCommand::Pattern12: {
  614.         setPattern(11);
  615.         break;
  616.       }
  617.  
  618.     // custom color adjustment buttons
  619.  
  620.     case InputCommand::RedUp: {
  621.         solidColor.red += 8;
  622.         setSolidColor(solidColor);
  623.         break;
  624.       }
  625.     case InputCommand::RedDown: {
  626.         solidColor.red -= 8;
  627.         setSolidColor(solidColor);
  628.         break;
  629.       }
  630.     case InputCommand::GreenUp: {
  631.         solidColor.green += 8;
  632.         setSolidColor(solidColor);
  633.         break;
  634.       }
  635.     case InputCommand::GreenDown: {
  636.         solidColor.green -= 8;
  637.         setSolidColor(solidColor);
  638.         break;
  639.       }
  640.     case InputCommand::BlueUp: {
  641.         solidColor.blue += 8;
  642.         setSolidColor(solidColor);
  643.         break;
  644.       }
  645.     case InputCommand::BlueDown: {
  646.         solidColor.blue -= 8;
  647.         setSolidColor(solidColor);
  648.         break;
  649.       }
  650.  
  651.     // color buttons
  652.  
  653.     case InputCommand::Red: {
  654.         setSolidColor(CRGB::Red);
  655.         break;
  656.       }
  657.     case InputCommand::RedOrange: {
  658.         setSolidColor(CRGB::OrangeRed);
  659.         break;
  660.       }
  661.     case InputCommand::Orange: {
  662.         setSolidColor(CRGB::Orange);
  663.         break;
  664.       }
  665.     case InputCommand::YellowOrange: {
  666.         setSolidColor(CRGB::Goldenrod);
  667.         break;
  668.       }
  669.     case InputCommand::Yellow: {
  670.         setSolidColor(CRGB::Yellow);
  671.         break;
  672.       }
  673.  
  674.     case InputCommand::Green: {
  675.         setSolidColor(CRGB::Green);
  676.         break;
  677.       }
  678.     case InputCommand::Lime: {
  679.         setSolidColor(CRGB::Lime);
  680.         break;
  681.       }
  682.     case InputCommand::Aqua: {
  683.         setSolidColor(CRGB::Aqua);
  684.         break;
  685.       }
  686.     case InputCommand::Teal: {
  687.         setSolidColor(CRGB::Teal);
  688.         break;
  689.       }
  690.     case InputCommand::Navy: {
  691.         setSolidColor(CRGB::Navy);
  692.         break;
  693.       }
  694.  
  695.     case InputCommand::Blue: {
  696.         setSolidColor(CRGB::Blue);
  697.         break;
  698.       }
  699.     case InputCommand::RoyalBlue: {
  700.         setSolidColor(CRGB::RoyalBlue);
  701.         break;
  702.       }
  703.     case InputCommand::Purple: {
  704.         setSolidColor(CRGB::Purple);
  705.         break;
  706.       }
  707.     case InputCommand::Indigo: {
  708.         setSolidColor(CRGB::Indigo);
  709.         break;
  710.       }
  711.     case InputCommand::Magenta: {
  712.         setSolidColor(CRGB::Magenta);
  713.         break;
  714.       }
  715.  
  716.     case InputCommand::White: {
  717.         setSolidColor(CRGB::White);
  718.         break;
  719.       }
  720.     case InputCommand::Pink: {
  721.         setSolidColor(CRGB::Pink);
  722.         break;
  723.       }
  724.     case InputCommand::LightPink: {
  725.         setSolidColor(CRGB::LightPink);
  726.         break;
  727.       }
  728.     case InputCommand::BabyBlue: {
  729.         setSolidColor(CRGB::CornflowerBlue);
  730.         break;
  731.       }
  732.     case InputCommand::LightBlue: {
  733.         setSolidColor(CRGB::LightBlue);
  734.         break;
  735.       }
  736.   }
  737. }
  738.  
  739. void loadSettings()
  740. {
  741.   brightness = EEPROM.read(0);
  742.  
  743.   currentPatternIndex = EEPROM.read(1);
  744.   if (currentPatternIndex < 0)
  745.     currentPatternIndex = 0;
  746.   else if (currentPatternIndex >= patternCount)
  747.     currentPatternIndex = patternCount - 1;
  748.  
  749.   byte r = EEPROM.read(2);
  750.   byte g = EEPROM.read(3);
  751.   byte b = EEPROM.read(4);
  752.  
  753.   if (r == 0 && g == 0 && b == 0)
  754.   {
  755.   }
  756.   else
  757.   {
  758.     solidColor = CRGB(r, g, b);
  759.   }
  760.  
  761.   power = EEPROM.read(5);
  762.  
  763.   autoplay = EEPROM.read(6);
  764.   autoplayDuration = EEPROM.read(7);
  765. }
  766.  
  767. void setPower(uint8_t value)
  768. {
  769.   power = value == 0 ? 0 : 1;
  770.  
  771.   EEPROM.write(5, power);
  772.   EEPROM.commit();
  773.  
  774.   broadcastInt("power", power);
  775. }
  776.  
  777. void setAutoplay(uint8_t value)
  778. {
  779.   autoplay = value == 0 ? 0 : 1;
  780.  
  781.   EEPROM.write(6, autoplay);
  782.   EEPROM.commit();
  783.  
  784.   broadcastInt("autoplay", autoplay);
  785. }
  786.  
  787. void setAutoplayDuration(uint8_t value)
  788. {
  789.   autoplayDuration = value;
  790.  
  791.   EEPROM.write(7, autoplayDuration);
  792.   EEPROM.commit();
  793.  
  794.   autoPlayTimeout = millis() + (autoplayDuration * 1000);
  795.  
  796.   broadcastInt("autoplayDuration", autoplayDuration);
  797. }
  798.  
  799. void setSolidColor(CRGB color)
  800. {
  801.   setSolidColor(color.r, color.g, color.b);
  802. }
  803.  
  804. void setSolidColor(uint8_t r, uint8_t g, uint8_t b)
  805. {
  806.   solidColor = CRGB(r, g, b);
  807.  
  808.   EEPROM.write(2, r);
  809.   EEPROM.write(3, g);
  810.   EEPROM.write(4, b);
  811.   EEPROM.commit();
  812.  
  813.   setPattern(patternCount - 1);
  814.  
  815.   broadcastString("color", String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
  816. }
  817.  
  818. // increase or decrease the current pattern number, and wrap around at the ends
  819. void adjustPattern(bool up)
  820. {
  821.   if (up)
  822.     currentPatternIndex++;
  823.   else
  824.     currentPatternIndex--;
  825.  
  826.   // wrap around at the ends
  827.   if (currentPatternIndex < 0)
  828.     currentPatternIndex = patternCount - 1;
  829.   if (currentPatternIndex >= patternCount)
  830.     currentPatternIndex = 0;
  831.  
  832.   EEPROM.write(1, currentPatternIndex);
  833.   EEPROM.commit();
  834.  
  835.   broadcastInt("pattern", currentPatternIndex);
  836. }
  837.  
  838. void setPattern(uint8_t value)
  839. {
  840.   if (value >= patternCount)
  841.     value = patternCount - 1;
  842.  
  843.   currentPatternIndex = value;
  844.  
  845.   EEPROM.write(1, currentPatternIndex);
  846.   EEPROM.commit();
  847.  
  848.   broadcastInt("pattern", currentPatternIndex);
  849. }
  850.  
  851. void adjustBrightness(bool up)
  852. {
  853.   if (up && brightnessIndex < brightnessCount - 1)
  854.     brightnessIndex++;
  855.   else if (!up && brightnessIndex > 0)
  856.     brightnessIndex--;
  857.  
  858.   brightness = brightnessMap[brightnessIndex];
  859.  
  860.   FastLED.setBrightness(brightness);
  861.  
  862.   EEPROM.write(0, brightness);
  863.   EEPROM.commit();
  864.  
  865.   broadcastInt("brightness", brightness);
  866. }
  867.  
  868. void setBrightness(uint8_t value)
  869. {
  870.   if (value > 255)
  871.     value = 255;
  872.   else if (value < 0) value = 0;
  873.  
  874.   brightness = value;
  875.  
  876.   FastLED.setBrightness(brightness);
  877.  
  878.   EEPROM.write(0, brightness);
  879.   EEPROM.commit();
  880.  
  881.   broadcastInt("brightness", brightness);
  882. }
  883.  
  884. void strandTest()
  885. {
  886.   static uint8_t i = 0;
  887.  
  888.   EVERY_N_SECONDS(1)
  889.   {
  890.     i++;
  891.     if (i >= NUM_LEDS)
  892.       i = 0;
  893.   }
  894.  
  895.   fill_solid(leds, NUM_LEDS, CRGB::Black);
  896.  
  897.   leds[i] = solidColor;
  898. }
  899.  
  900. void showSolidColor()
  901. {
  902.   fill_solid(leds, NUM_LEDS, solidColor);
  903. }
  904.  
  905. // Patterns from FastLED example DemoReel100: https://github.com/FastLED/FastLED/blob/master/examples/DemoReel100/DemoReel100.ino
  906.  
  907. void rainbow()
  908. {
  909.   // FastLED's built-in rainbow generator
  910.   fill_rainbow( leds, NUM_LEDS, gHue, 255 / NUM_LEDS);
  911. }
  912.  
  913. void rainbowWithGlitter()
  914. {
  915.   // built-in FastLED rainbow, plus some random sparkly glitter
  916.   rainbow();
  917.   addGlitter(80);
  918. }
  919.  
  920. void rainbowSolid()
  921. {
  922.   fill_solid(leds, NUM_LEDS, CHSV(gHue, 255, 255));
  923. }
  924.  
  925. void confetti()
  926. {
  927.   // random colored speckles that blink in and fade smoothly
  928.   fadeToBlackBy( leds, NUM_LEDS, 10);
  929.   int pos = random16(NUM_LEDS);
  930.   leds[pos] += CHSV( gHue + random8(64), 200, 255);
  931. }
  932.  
  933. void sinelon()
  934. {
  935.   // a colored dot sweeping back and forth, with fading trails
  936.   fadeToBlackBy( leds, NUM_LEDS, 20);
  937.   int pos = beatsin16(speed, 0, NUM_LEDS);
  938.   static int prevpos = 0;
  939.   if( pos < prevpos ) {
  940.     fill_solid( leds+pos, (prevpos-pos)+1, CHSV(gHue,220,255));
  941.   } else {
  942.     fill_solid( leds+prevpos, (pos-prevpos)+1, CHSV( gHue,220,255));
  943.   }
  944.   prevpos = pos;
  945. }
  946.  
  947. void bpm()
  948. {
  949.   // colored stripes pulsing at a defined Beats-Per-Minute (BPM)  
  950.   uint8_t beat = beatsin8( speed, 64, 255);
  951.   for ( int i = 0; i < NUM_LEDS; i++) {
  952.     leds[i] = ColorFromPalette(gCurrentPalette, gHue + (i * 2), beat - gHue + (i * 10));
  953.   }
  954. }
  955.  
  956. void juggle()
  957. {
  958.   static uint8_t    numdots =   4; // Number of dots in use.
  959.   static uint8_t   faderate =   2; // How long should the trails be. Very low value = longer trails.
  960.   static uint8_t     hueinc =  255 / numdots - 1; // Incremental change in hue between each dot.
  961.   static uint8_t    thishue =   0; // Starting hue.
  962.   static uint8_t     curhue =   0; // The current hue
  963.   static uint8_t    thissat = 255; // Saturation of the colour.
  964.   static uint8_t thisbright = 255; // How bright should the LED/display be.
  965.   static uint8_t   basebeat =   5; // Higher = faster movement.
  966.  
  967.   static uint8_t lastSecond =  99;  // Static variable, means it's only defined once. This is our 'debounce' variable.
  968.   uint8_t secondHand = (millis() / 1000) % 30; // IMPORTANT!!! Change '30' to a different value to change duration of the loop.
  969.  
  970.   if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment.
  971.     lastSecond = secondHand;
  972.     switch (secondHand) {
  973.       case  0: numdots = 1; basebeat = 20; hueinc = 16; faderate = 2; thishue = 0; break; // You can change values here, one at a time , or altogether.
  974.       case 10: numdots = 4; basebeat = 10; hueinc = 16; faderate = 8; thishue = 128; break;
  975.       case 20: numdots = 8; basebeat =  3; hueinc =  0; faderate = 8; thishue = random8(); break; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows.
  976.       case 30: break;
  977.     }
  978.   }
  979.  
  980.   // Several colored dots, weaving in and out of sync with each other
  981.   curhue = thishue; // Reset the hue values.
  982.   fadeToBlackBy(leds, NUM_LEDS, faderate);
  983.   for ( int i = 0; i < numdots; i++) {
  984.     //beat16 is a FastLED 3.1 function
  985.     leds[beatsin16(basebeat + i + numdots, 0, NUM_LEDS)] += CHSV(gHue + curhue, thissat, thisbright);
  986.     curhue += hueinc;
  987.   }
  988. }
  989.  
  990. void fire()
  991. {
  992.   heatMap(HeatColors_p, true);
  993. }
  994.  
  995. void water()
  996. {
  997.   heatMap(IceColors_p, false);
  998. }
  999.  
  1000. void draw()
  1001. {
  1002. }
  1003.  
  1004. // Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5
  1005. // This function draws rainbows with an ever-changing,
  1006. // widely-varying set of parameters.
  1007. void pride()
  1008. {
  1009.   static uint16_t sPseudotime = 0;
  1010.   static uint16_t sLastMillis = 0;
  1011.   static uint16_t sHue16 = 0;
  1012.  
  1013.   uint8_t sat8 = beatsin88( 87, 220, 250);
  1014.   uint8_t brightdepth = beatsin88( 341, 96, 224);
  1015.   uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  1016.   uint8_t msmultiplier = beatsin88(147, 23, 60);
  1017.  
  1018.   uint16_t hue16 = sHue16;//gHue * 256;
  1019.   uint16_t hueinc16 = beatsin88(113, 1, 3000);
  1020.  
  1021.   uint16_t ms = millis();
  1022.   uint16_t deltams = ms - sLastMillis ;
  1023.   sLastMillis  = ms;
  1024.   sPseudotime += deltams * msmultiplier;
  1025.   sHue16 += deltams * beatsin88( 400, 5, 9);
  1026.   uint16_t brightnesstheta16 = sPseudotime;
  1027.  
  1028.   for ( uint16_t i = 0 ; i < NUM_LEDS; i++) {
  1029.     hue16 += hueinc16;
  1030.     uint8_t hue8 = hue16 / 256;
  1031.  
  1032.     brightnesstheta16  += brightnessthetainc16;
  1033.     uint16_t b16 = sin16( brightnesstheta16  ) + 32768;
  1034.  
  1035.     uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
  1036.     uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
  1037.     bri8 += (255 - brightdepth);
  1038.  
  1039.     CRGB newcolor = CHSV( hue8, sat8, bri8);
  1040.  
  1041.     uint16_t pixelnumber = i;
  1042.     pixelnumber = (NUM_LEDS - 1) - pixelnumber;
  1043.  
  1044.     nblend( leds[pixelnumber], newcolor, 64);
  1045.   }
  1046. }
  1047.  
  1048. void radialPaletteShift()
  1049. {
  1050.   for (uint8_t i = 0; i < NUM_LEDS; i++) {
  1051.     // leds[i] = ColorFromPalette( gCurrentPalette, gHue + sin8(i*16), brightness);
  1052.     leds[i] = ColorFromPalette(gCurrentPalette, i + gHue, 255, LINEARBLEND);
  1053.   }
  1054. }
  1055.  
  1056. // based on FastLED example Fire2012WithPalette: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino
  1057. void heatMap(CRGBPalette16 palette, bool up)
  1058. {
  1059.   fill_solid(leds, NUM_LEDS, CRGB::Black);
  1060.  
  1061.   // Add entropy to random number generator; we use a lot of it.
  1062.   random16_add_entropy(random(256));
  1063.  
  1064.   // Array of temperature readings at each simulation cell
  1065.   static byte heat[256];
  1066.  
  1067.   byte colorindex;
  1068.  
  1069.   // Step 1.  Cool down every cell a little
  1070.   for ( uint16_t i = 0; i < NUM_LEDS; i++) {
  1071.     heat[i] = qsub8( heat[i],  random8(0, ((cooling * 10) / NUM_LEDS) + 2));
  1072.   }
  1073.  
  1074.   // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  1075.   for ( uint16_t k = NUM_LEDS - 1; k >= 2; k--) {
  1076.     heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
  1077.   }
  1078.  
  1079.   // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  1080.   if ( random8() < sparking ) {
  1081.     int y = random8(7);
  1082.     heat[y] = qadd8( heat[y], random8(160, 255) );
  1083.   }
  1084.  
  1085.   // Step 4.  Map from heat cells to LED colors
  1086.   for ( uint16_t j = 0; j < NUM_LEDS; j++) {
  1087.     // Scale the heat value from 0-255 down to 0-240
  1088.     // for best results with color palettes.
  1089.     colorindex = scale8(heat[j], 190);
  1090.  
  1091.     CRGB color = ColorFromPalette(palette, colorindex);
  1092.  
  1093.     if (up) {
  1094.       leds[j] = color;
  1095.     }
  1096.     else {
  1097.       leds[(NUM_LEDS - 1) - j] = color;
  1098.     }
  1099.   }
  1100. }
  1101.  
  1102. void addGlitter( uint8_t chanceOfGlitter)
  1103. {
  1104.   if ( random8() < chanceOfGlitter) {
  1105.     leds[ random16(NUM_LEDS) ] += CRGB::White;
  1106.   }
  1107. }
  1108.  
  1109. ///////////////////////////////////////////////////////////////////////
  1110.  
  1111. // Forward declarations of an array of cpt-city gradient palettes, and
  1112. // a count of how many there are.  The actual color palette definitions
  1113. // are at the bottom of this file.
  1114. extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
  1115. extern const uint8_t gGradientPaletteCount;
  1116.  
  1117. uint8_t beatsaw8( accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
  1118.                   uint32_t timebase = 0, uint8_t phase_offset = 0)
  1119. {
  1120.   uint8_t beat = beat8( beats_per_minute, timebase);
  1121.   uint8_t beatsaw = beat + phase_offset;
  1122.   uint8_t rangewidth = highest - lowest;
  1123.   uint8_t scaledbeat = scale8( beatsaw, rangewidth);
  1124.   uint8_t result = lowest + scaledbeat;
  1125.   return result;
  1126. }
  1127.  
  1128. void colorWaves()
  1129. {
  1130.   colorwaves( leds, NUM_LEDS, gCurrentPalette);
  1131. }
  1132.  
  1133. // ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
  1134. // This function draws color waves with an ever-changing,
  1135. // widely-varying set of parameters, using a color palette.
  1136. void colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette)
  1137. {
  1138.   static uint16_t sPseudotime = 0;
  1139.   static uint16_t sLastMillis = 0;
  1140.   static uint16_t sHue16 = 0;
  1141.  
  1142.   // uint8_t sat8 = beatsin88( 87, 220, 250);
  1143.   uint8_t brightdepth = beatsin88( 341, 96, 224);
  1144.   uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  1145.   uint8_t msmultiplier = beatsin88(147, 23, 60);
  1146.  
  1147.   uint16_t hue16 = sHue16;//gHue * 256;
  1148.   uint16_t hueinc16 = beatsin88(113, 300, 1500);
  1149.  
  1150.   uint16_t ms = millis();
  1151.   uint16_t deltams = ms - sLastMillis ;
  1152.   sLastMillis  = ms;
  1153.   sPseudotime += deltams * msmultiplier;
  1154.   sHue16 += deltams * beatsin88( 400, 5, 9);
  1155.   uint16_t brightnesstheta16 = sPseudotime;
  1156.  
  1157.   for ( uint16_t i = 0 ; i < numleds; i++) {
  1158.     hue16 += hueinc16;
  1159.     uint8_t hue8 = hue16 / 256;
  1160.     uint16_t h16_128 = hue16 >> 7;
  1161.     if ( h16_128 & 0x100) {
  1162.       hue8 = 255 - (h16_128 >> 1);
  1163.     } else {
  1164.       hue8 = h16_128 >> 1;
  1165.     }
  1166.  
  1167.     brightnesstheta16  += brightnessthetainc16;
  1168.     uint16_t b16 = sin16( brightnesstheta16  ) + 32768;
  1169.  
  1170.     uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
  1171.     uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
  1172.     bri8 += (255 - brightdepth);
  1173.  
  1174.     uint8_t index = hue8;
  1175.     //index = triwave8( index);
  1176.     index = scale8( index, 240);
  1177.  
  1178.     CRGB newcolor = ColorFromPalette( palette, index, bri8);
  1179.  
  1180.     uint16_t pixelnumber = i;
  1181.     pixelnumber = (numleds - 1) - pixelnumber;
  1182.  
  1183.     nblend( ledarray[pixelnumber], newcolor, 128);
  1184.   }
  1185. }
  1186.  
  1187. // Alternate rendering function just scrolls the current palette
  1188. // across the defined LED strip.
  1189. void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette)
  1190. {
  1191.   static uint8_t startindex = 0;
  1192.   startindex--;
  1193.   fill_palette( ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND);
  1194. }
Advertisement
Add Comment
Please, Sign In to add comment