From 0a9e8eaf35679fd1e1f21c0e2c530cce09b23473 Mon Sep 17 00:00:00 2001 From: BigDi Date: Fri, 2 Aug 2019 10:20:58 +0200 Subject: [PATCH] Add basic FASTLED function initated by Joen (#433) * merge FastLED part of Joen Co-Authored-By: Leon Kiefer --- main/User_config.h | 1 + main/ZactuatorFASTLED.ino | 293 ++++++++++++++++++++++++++++++++++++++ main/config_FASTLED.h | 94 ++++++++++++ main/main.ino | 26 ++++ platformio.ini | 5 + test/Test_config.h | 6 +- 6 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 main/ZactuatorFASTLED.ino create mode 100644 main/config_FASTLED.h diff --git a/main/User_config.h b/main/User_config.h index d0a72d6..57714e9 100644 --- a/main/User_config.h +++ b/main/User_config.h @@ -101,6 +101,7 @@ char mqtt_port[6] = "1883"; //#define ZsensorGPIOKeyCode "GPIOKeyCode" //ESP8266, Arduino, ESP32 //#define ZsensorGPIOInput "GPIOInput" //ESP8266, Arduino, ESP32 //#define ZmqttDiscovery "HADiscovery"//ESP8266, Arduino, ESP32, Sonoff RF Bridge +//#define ZactuatorFASTLED "FASTLED" //ESP8266, Arduino, ESP32, Sonoff RF Bridge /*-------------DEFINE YOUR ADVANCED NETWORK PARAMETERS BELOW----------------*/ //#define MDNS_SD //uncomment if you want to use mdns for discovering automatically your ip server, please note that MDNS with ESP32 can cause the BLE to not work diff --git a/main/ZactuatorFASTLED.ino b/main/ZactuatorFASTLED.ino new file mode 100644 index 0000000..001923b --- /dev/null +++ b/main/ZactuatorFASTLED.ino @@ -0,0 +1,293 @@ +/* + OpenMQTTGateway - ESP8266 or Arduino program for home automation + + This gateway enables to use RGBLED strips like WS2812 + + Copyright: (c) + + This file is part of OpenMQTTGateway. + + OpenMQTTGateway is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenMQTTGateway is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "User_config.h" + +#ifdef ZactuatorFASTLED + +#ifdef ESP8266 +#include +#else +#include +#endif +#include +enum LEDState +{ + OFF, + FIRE, + GENERAL +}; +LEDState currentLEDState; +long lastUpdate = 0; +long currentUpdate = 0; +CRGB leds[FASTLED_NUM_LEDS]; +CRGB ledColorBlink[FASTLED_NUM_LEDS]; +bool blinkLED[FASTLED_NUM_LEDS]; +const long blinkInterval = 300; +const long fireUpdate = 10; +CRGBPalette16 gPal; + +void setupFASTLED() +{ + trc(F("FASTLED_DATA_PIN ")); + trc(String(FASTLED_DATA_PIN)); + trc(F("FASTLED_NUM_LEDS ")); + trc(String(FASTLED_NUM_LEDS)); + trc(F("ZactuatorFASTLED setup done ")); + FastLED.addLeds(leds, FASTLED_NUM_LEDS); +} + +//returns the current step of the animation +int animation_step(int duration, int steps) +{ + int currentStep = ((currentUpdate % duration) / ((float)duration)) * steps; + return currentStep; +} + +//returns the number of steps since the last update +int animation_step_count(int duration, int steps) +{ + long lastAnimationNumber = lastUpdate / duration; + long currentAnimationNumber = currentUpdate / duration; + int lastStep = ((lastUpdate % duration) / ((float)duration)) * steps; + int currentStep = ((currentUpdate % duration) / ((float)duration)) * steps; + + return currentStep - lastStep + (currentAnimationNumber - lastAnimationNumber) * steps; +} + +void FASTLEDLoop() +{ + + lastUpdate = currentUpdate; + currentUpdate = millis(); + + if (currentLEDState == GENERAL) + { + + for (int i = 0; i < FASTLED_NUM_LEDS; i++) + { + + int count = animation_step_count(blinkInterval, 2); + int step = animation_step(blinkInterval, 2); + + if (count > 0) + { + if (blinkLED[i]) + { + + if (step == 0) + { + leds[i] = ledColorBlink[i]; + } + else + { + ledColorBlink[i] = leds[i]; + leds[i] = CRGB::Black; + } + } + } + } + } + else if (currentLEDState == FIRE) + { + int count = animation_step_count(fireUpdate, 1); + if (count > 0) + { + //random16_add_entropy( random(0)); //random() don't exists in ESP framework - workaround? + Fire2012WithPalette(); + } + } + FastLED.show(); +} + +boolean FASTLEDtoMQTT() +{ + return false; +} +void MQTTtoFASTLEDJSON(char *topicOri, JsonObject& jsonData) +{ + trc(F("MQTTtoFASTLEDJSON: ")); + currentLEDState = GENERAL; + String topic = topicOri; + + trc(topic); + //number = (long)strtol(&datacallback[1], NULL, 16); + + + + if (topic == subjectMQTTtoFASTLEDsetled) + { + trc(F("JSON parsed")); + int ledNr = jsonData["led"]; + trc(F("led")); + trc(ledNr); + const char *color = jsonData["hex"]; + trc(F("hex")); + + long number = (long)strtol(color, NULL, 16); + trc(number); + bool blink = jsonData["blink"]; + if (ledNr <= FASTLED_NUM_LEDS) + { + trc(F("blink")); + trc(blink); + blinkLED[ledNr] = blink; + leds[ledNr] = number; + } + + } +} +void MQTTtoFASTLED(char *topicOri, char *datacallback) +{ + trc(F("MQTTtoFASTLED: ")); + currentLEDState = GENERAL; + String topic = topicOri; + long number = 0; + trc(topic); + if (topic == subjectMQTTtoFASTLED) + { + number = (long)strtol(&datacallback[1], NULL, 16); + trc(number); + for (int i = 0; i < FASTLED_NUM_LEDS; i++) + { + leds[i] = number; + } + FastLED.show(); + } + else if (topic == subjectMQTTtoFASTLEDsetbrightness) + { + number = (long)strtol(&datacallback[1], NULL, 16); + trc(number); + FastLED.setBrightness(number); + FastLED.show(); + } + else if (topic == subjectMQTTtoFASTLEDsetanimation) + { + String payload = datacallback; + trc(payload); + if (payload.equals("fire")) + { + currentLEDState = FIRE; + gPal = HeatColors_p; + } + else + { + currentLEDState = OFF; + } + } + else + { + currentLEDState = OFF; + } + if (currentLEDState==OFF) + { + for (int i = 0; i < FASTLED_NUM_LEDS; i++) + { + leds[i] = CRGB::Black; + } + } +} + +// Fire2012 by Mark Kriegsman, July 2012 +// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY +//// +// This basic one-dimensional 'fire' simulation works roughly as follows: +// There's a underlying array of 'heat' cells, that model the temperature +// at each point along the line. Every cycle through the simulation, +// four steps are performed: +// 1) All cells cool down a little bit, losing heat to the air +// 2) The heat from each cell drifts 'up' and diffuses a little +// 3) Sometimes randomly new 'sparks' of heat are added at the bottom +// 4) The heat from each cell is rendered as a color into the leds array +// The heat-to-color mapping uses a black-body radiation approximation. +// +// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). +// +// This simulation scales it self a bit depending on NUM_LEDS; it should look +// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. +// +// I recommend running this simulation at anywhere from 30-100 frames per second, +// meaning an interframe delay of about 10-35 milliseconds. +// +// Looks best on a high-density LED setup (60+ pixels/meter). +// +// +// There are two main parameters you can play with to control the look and +// feel of your fire: COOLING (used in step 1 above), and SPARKING (used +// in step 3 above). +// +// COOLING: How much does the air cool as it rises? +// Less cooling = taller flames. More cooling = shorter flames. +// Default 55, suggested range 20-100 +#define COOLING 55 + +// SPARKING: What chance (out of 255) is there that a new spark will be lit? +// Higher chance = more roaring fire. Lower chance = more flickery fire. +// Default 120, suggested range 50-200. +#define SPARKING 120 +bool gReverseDirection = false; + +void Fire2012WithPalette() +{ + // Array of temperature readings at each simulation cell + static byte heat[FASTLED_NUM_LEDS]; + + // Step 1. Cool down every cell a little + for (int i = 0; i < FASTLED_NUM_LEDS; i++) + { + heat[i] = qsub8(heat[i], random8(0, ((COOLING * 10) / FASTLED_NUM_LEDS) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = FASTLED_NUM_LEDS - 1; k >= 2; k--) + { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' of heat near the bottom + if (random8() < SPARKING) + { + int y = random8(7); + heat[y] = qadd8(heat[y], random8(160, 255)); + } + + // Step 4. Map from heat cells to LED colors + for (int j = 0; j < FASTLED_NUM_LEDS; j++) + { + // Scale the heat value from 0-255 down to 0-240 + // for best results with color palettes. + byte colorindex = scale8(heat[j], 240); + CRGB color = ColorFromPalette(gPal, colorindex); + int pixelnumber; + if (gReverseDirection) + { + pixelnumber = (FASTLED_NUM_LEDS - 1) - j; + } + else + { + pixelnumber = j; + } + leds[pixelnumber] = color; + } +} + +#endif diff --git a/main/config_FASTLED.h b/main/config_FASTLED.h new file mode 100644 index 0000000..724f6a7 --- /dev/null +++ b/main/config_FASTLED.h @@ -0,0 +1,94 @@ +/* + OpenMQTTGateway - ESP8266 or Arduino program for home automation + + This files enables you to set your parameters for the FASTLED actuator + + Copyright: (c) + + This file is part of OpenMQTTGateway. + + OpenMQTTGateway is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenMQTTGateway is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/*-------------------FASTLED topics & parameters----------------------*/ +//FASTLED MQTT Subjects +#define subjectMQTTtoFASTLED Base_Topic Gateway_Name "/commands/MQTTtoFASTLED" +#define subjectMQTTtoFASTLEDsetled Base_Topic Gateway_Name "/commands/MQTTtoFASTLED/setled" //set only one LED with JSON struct {"led":0-x,"hex":"#000000","blink":true/false} +#define subjectMQTTtoFASTLEDsetbrightness Base_Topic Gateway_Name "/commands/MQTTtoFASTLED/setbrightness" //set the brightness 0-255 +#define subjectMQTTtoFASTLEDsetanimation Base_Topic Gateway_Name "/commands/MQTTtoFASTLED/setanimation" //Animation Fire2012 by Mark Kriegsman +#define subjectGTWFASTLEDtoMQTT Base_Topic Gateway_Name "/FASTLEDtoMQTT" //same color on all LEDs in #RRGGBB + + + + + + +// How many leds in your strip? +#define FASTLED_NUM_LEDS 16 + +// Uncomment/edit one of the following lines for your leds arrangement. + +//#define FASTLED_TYPE TM1803 +//#define FASTLED_TYPE TM1804 +//#define FASTLED_TYPE TM1809 +//#define FASTLED_TYPE WS2811 +//#define FASTLED_TYPE WS2812 +//#define FASTLED_TYPE WS2812B +#define FASTLED_TYPE NEOPIXEL +//#define FASTLED_TYPE APA104 +//#define FASTLED_TYPE UCS1903 +//#define FASTLED_TYPE UCS1903B +//#define FASTLED_TYPE GW6205 + +//#define FASTLED_TYPE WS2801, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE SM16716, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE LPD8806, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE P9813, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE APA102, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE DOTSTAR, RGB>(leds, NUM_LEDS); + +//#define FASTLED_TYPE WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE SM16716, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE LPD8806, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE P9813, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); +//#define FASTLED_TYPE DOTSTAR, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); + +// For led chips like Neopixels, which have a data line, ground, and power, you just +// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock, +// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN +//#define DATA_PIN 3 +//#define CLOCK_PIN 13 + +#ifdef ESP8266 + +#elif ESP32 + +#else + +#endif + +#ifdef ESP8266 +//#define FASTLED_ESP8266_RAW_PIN_ORDER +//#define FASTLED_ESP8266_NODEMCU_PIN_ORDER +#define FASTLED_ESP8266_D1_PIN_ORDER +#define FASTLED_DATA_PIN D2 // only D2 works by me +//#define FASTLED_CLOCK_PIN 13 +#elif ESP32 +#define FASTLED_DATA_PIN 16 +#define FASTLED_CLOCK_PIN 13 +#else +#define FASTLED_DATA_PIN 10 +#define FASTLED_CLOCK_PIN 13 +#endif diff --git a/main/main.ino b/main/main.ino index 9dbba18..a9fe09c 100644 --- a/main/main.ino +++ b/main/main.ino @@ -99,6 +99,9 @@ #ifdef ZmqttDiscovery #include "config_mqttDiscovery.h" #endif +#ifdef ZactuatorFASTLED + #include "config_FASTLED.h" +#endif /*------------------------------------------------------------------------*/ @@ -608,6 +611,10 @@ void setup() #ifdef ZsensorGPIOKeyCode setupGPIOKeyCode(); #endif + #ifdef ZactuatorFASTLED + setupFASTLED(); + #endif + trc(F("MQTT_MAX_PACKET_SIZE")); trc(MQTT_MAX_PACKET_SIZE); @@ -943,6 +950,10 @@ void loop() #if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) stateMeasures(); #endif + #ifdef ZactuatorFASTLED + FASTLEDLoop(); + #endif + } } @@ -1033,6 +1044,10 @@ void stateMeasures(){ modules = modules + ZmqttDiscovery; pubMqttDiscovery(); #endif + #ifdef ZactuatorFASTLED + modules = modules + ZactuatorFASTLED; + #endif + SYSdata["modules"] = modules; trc(SYSdata); char JSONmessageBuffer[JSON_MSG_BUFFER]; @@ -1148,6 +1163,12 @@ void receivingMQTT(char * topicOri, char * datacallback) { MQTTtoONOFF(topicOri, jsondata); #endif digitalWrite(led_send, HIGH); + + #ifdef ZactuatorFASTLED + MQTTtoFASTLEDJSON(topicOri, jsondata); + #endif + + } else { // not a json object --> simple decoding #ifdef simpleReceiving #ifdef ZgatewayLORA @@ -1179,6 +1200,11 @@ void receivingMQTT(char * topicOri, char * datacallback) { MQTTtoONOFF(topicOri, datacallback); #endif digitalWrite(led_send, HIGH); + + #ifdef ZactuatorFASTLED + MQTTtoFASTLED(topicOri, datacallback); + #endif + } //YELLOW OFF digitalWrite(led_send, HIGH); diff --git a/platformio.ini b/platformio.ini index 01ad742..da88fdd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ lib_deps = Wire jarzebski/Arduino-INA226 1technophile/NewRemoteSwitch + FastLED build_flags = -w ; supress all warnings @@ -42,6 +43,7 @@ lib_deps = IRremoteESP8266 https://github.com/tzapu/WiFiManager.git#c3ff582374e677f76d14de013966df0888b5b38e esp8266_mdns + FastLED lib_ignore = Ethernet build_flags = @@ -62,6 +64,7 @@ lib_deps = https://github.com/tzapu/WiFiManager.git#c3ff582374e677f76d14de013966df0888b5b38e https://github.com/eos1d3/ESP32_BLE.git https://github.com/sandeepmistry/arduino-LoRa.git + FastLED lib_ignore = esp8266_mdns Ethernet @@ -76,6 +79,7 @@ lib_deps = ${common.lib_deps} IRremote Ethernet + FastLED build_flags = ${common.build_flags} @@ -87,5 +91,6 @@ lib_deps = ${common.lib_deps} IRremote Ethernet + FastLED build_flags = ${common.build_flags} diff --git a/test/Test_config.h b/test/Test_config.h index 3072cd3..0875520 100644 --- a/test/Test_config.h +++ b/test/Test_config.h @@ -151,6 +151,7 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define jsonReceiving true #define simplePublishing true #define simpleReceiving true + #define ZactuatorFASTLED "FASTLED" //ESP8266, Arduino, ESP32, Sonoff RF Bridge #define TRACE 1 // commented = trace off, uncommented = trace on #elif ESP32 #define ZgatewayRF "RF" @@ -176,6 +177,7 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define jsonReceiving true #define simplePublishing true #define simpleReceiving true + #define ZactuatorFASTLED "FASTLED" //ESP8266, Arduino, ESP32, Sonoff RF Bridge #define TRACE 1 // commented = trace off, uncommented = trace on #elif defined(__AVR_ATmega1280__) #define ZgatewayRF "RF" @@ -202,9 +204,10 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define jsonReceiving true #define simplePublishing true #define simpleReceiving true + #define ZactuatorFASTLED "FASTLED" //ESP8266, Arduino, ESP32, Sonoff RF Bridge #define TRACE 1 // commented = trace off, uncommented = trace on #else // for arduino Uno - #define ZgatewayRF "RF" + //#define ZgatewayRF "RF" //#define ZgatewayLORA "LORA" (not tested yet) //#define Zgateway2G (not tested yet) //#define ZgatewayRF2 // too big for UNO @@ -224,6 +227,7 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define jsonReceiving true //#define simplePublishing true //#define simpleReceiving true + #define ZactuatorFASTLED "FASTLED" //ESP8266, Arduino, ESP32, Sonoff RF Bridge //#define TRACE 1 // commented = trace off, uncommented = trace on #endif /*----------------------------OTHER PARAMETERS-----------------------------*/