Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* File: mqtt-firexy.ino
- *
- * Originally Fire2012withPalette by: Mark Kriegsman
- *
- * Asynchronous MQTT modifications by: Andrew Tuline
- *
- * Modified date: October, 2019
- *
- * Here's Mark Kriegsman's Fire2012withpalette configured with asynchronous MQTT based messaging. This routine is different from the standard ethernet and MQTT programming
- * in that it is non-blocking for both ethernet and MQTT broker connectivity.
- *
- * Setting: Down a winding ravine, I have lanterns spread along the banks of a river over the length of a football field. There is no power, WiFi or data that I can rely on.
- * I've plugged a small router into a portable inverter and have setup a couple of WiFi extenders down the ravine. On my Android phone, I've installed an MQTT broker as well as
- * an MQTT Control Panel for several ESP8266 based (and 18650 powered) lanterns.
- *
- * The lanterns are configured with asynchronous MQTT clients that receive commands from my Android phone. Those commands are translated to parameters that modify the fire2012 animation. Reception will be
- * sporadic for the lanterns as I walk in and out of the ravine, and the asynchonous client on the ESP8266 ensures smooth animation whether or not the lanterns have access to WiFi or the MQTT broker.
- *
- *
- * Topic Prefix: fire/
- *
- * Topic Function Widget Topic Value(s) Description
- * -------------- ------ ----- ------- ---------------------------
- *
- * Device Combo box device 0,1-9 Select All or a single device in the family.
- * Brightness Slider bri 0-255 Decrease/Increase brightness.
- * Hue Slider hue 0-255 Select palette base hue.
- * Speed Slider speed 10-100 Change speed of animation.
- * Cooling Slider cool 20-100 Change rate of cooling of flame.
- * Sparking Slider spark 50-100 Change rate of sparking of new flames.
- *
- *
- * Sample Topic and Payload: fire/bri 245
- *
- *
- * The Android phone MQTT client is called 'IoT MQTT Panel Pro'.
- * The Android phone MQTT broker is called 'MQTT Broker App'.
- *
- * Warning: The ESP8266 may require you to unplug and re-plug it in again after programming it before the wifi will work.
- *
- *
- * To Add:
- *
- * Rotate/fixed hue
- * Rotate hue speed
- * Direction
- * Reboot
- * Optional sine wave of hue speed
- *
- *
- * For more information, see: http://tuline.com/getting-started-with-esp8266-and-mqtt/
- *
- * Update:
- *
- * I am no longer using the PubSubclient library as mentioned in the above article. That library had 'blocking' issues which caused the loop to delay in the event
- * of a disconnection from the MQTT broker. I am now using the async-mqtt-client library from:
- *
- * https://github.com/marvinroger/async-mqtt-client
- *
- */
- #include <ESP8266WiFi.h> // Should be included when you install the ESP8266.
- #include <Ticker.h>
- #include <AsyncMqttClient.h> // https://github.com/marvinroger/async-mqtt-client
- #include "FastLED.h" // https://github.com/FastLED/FastLED
- #if FASTLED_VERSION < 3001000
- #error "Requires FastLED 3.1 or later; check github for latest code."
- #endif
- // WiFi Authentication -------------------------------------------------------------------------
- // #define WIFI_SSID "arduinoled" // Extended field network
- // #define WIFI_PASSWORD "afng2036"
- #define WIFI_SSID "dlink-9843" // Central field network
- #define WIFI_PASSWORD "cwrgz86646"
- // #define WIFI_SSID "WiFiPlus5041-2.4G" // Home office network
- // #define WIFI_PASSWORD "t84uw5hc29"
- // MQTT Authentication -------------------------------------------------------------------------
- #define MQTT_HOST IPAddress(192, 168, 0, 101)
- #define MQTT_PORT 1883
- #define MQTT_USR "wmabzsy"
- #define MQTT_PWD "GT8Do3vkgWP5"
- #define STRANDID 30
- // MQTT Information
- const char *prefixtopic = "fire30/";
- const char* subscribetopic[] = {"device", "bri", "hue", "speed", "cool", "spark"};
- char theVal[100]; // Used to reset our topic/payload comparison string.
- char message_buff[100]; // Used to convert raw payload characters to a string.
- AsyncMqttClient mqttClient;
- Ticker mqttReconnectTimer;
- WiFiEventHandler wifiConnectHandler;
- WiFiEventHandler wifiDisconnectHandler;
- Ticker wifiReconnectTimer;
- const uint8_t kMatrixWidth = 6; // Number of lengths.
- const uint8_t kMatrixHeight = 5; // How long each length is.
- const bool kMatrixSerpentineLayout = true; // Using a serpentine layout.
- #define NUM_LEDS (kMatrixWidth * kMatrixHeight)
- // Fixed definitions cannot change on the fly.
- #define LED_DT D5 // Data pin to connect to the strip.
- #define COLOR_ORDER GRB // It's GRB for WS2812 and BGR for APA102.
- #define LED_TYPE WS2812 // Using APA102, WS2812, WS2801. Don't forget to modify LEDS.addLeds to suit.
- uint8_t max_bright = 255; // Overall brightness.
- struct CRGB leds[NUM_LEDS]; // Initialize our LED array.
- CRGBPalette16 currentPalette;
- CRGBPalette16 targetPalette;
- TBlendType currentBlending = LINEARBLEND; // NOBLEND or LINEARBLEND
- uint8_t mydevice = STRANDID; // This is our STRANDID
- uint8_t mybri = 255;
- uint8_t myhue = 0;
- uint8_t myspeed = 40;
- uint8_t mypayload = 0;
- uint8_t mycool = 40; // Default 55, suggested range 20-100
- uint8_t myspark = 60; // Default 120, suggested range 50-200.
- // -------------------- Start of Code ----------------------------------------
- void connectToWifi() {
- Serial.println("Connecting to Wi-Fi...");
- WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
- } // connectToWifi()
- void onWifiConnect(const WiFiEventStationModeGotIP& event) {
- Serial.println("Connected to Wi-Fi.");
- connectToMqtt();
- } // onWifiConnect()
- void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
- Serial.println("Disconnected from Wi-Fi.");
- mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
- wifiReconnectTimer.once(2, connectToWifi);
- } // onWifiDisconnect()
- void connectToMqtt() {
- Serial.println("Connecting to MQTT...");
- mqttClient.setCredentials(MQTT_USR, MQTT_PWD);
- mqttClient.setServer(MQTT_HOST, MQTT_PORT);
- mqttClient.connect();
- } // connectToMqtt()
- void onMqttConnect(bool sessionPresent) {
- Serial.println("Connected to MQTT.");
- Serial.print("Session present: ");
- Serial.println(sessionPresent);
- // Here is where we subscribe to the list of topics. . prepended by the prefix of course.
- for (int i = 0; i < (sizeof(subscribetopic)/sizeof(int)); i++) { // Subscribes to list of topics from the MQTT broker. This whole loop is well above my pay grade.
- String mypref = prefixtopic; // But first, we need to get our prefix.
- mypref.concat(subscribetopic[i]); // Concatenate prefix and the topic together with a little bit of pfm.
- uint16_t packetIdSub = mqttClient.subscribe((char *) mypref.c_str(), 2);
- Serial.print("Subscribing at QoS 2, packetId: ");
- Serial.println(packetIdSub); // Let's print out each subscribed topic, just to be safe.
- }
- } // onMqttConnect()
- void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
- Serial.println("Disconnected from MQTT.");
- if (WiFi.isConnected()) {
- mqttReconnectTimer.once(2, connectToMqtt);
- }
- } // onMqttDisconnect()
- void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
- Serial.println("Subscribe acknowledged.");
- Serial.print(" packetId: ");
- Serial.println(packetId);
- Serial.print(" qos: ");
- Serial.println(qos);
- } // onMqttSubscribe()
- void onMqttUnsubscribe(uint16_t packetId) {
- Serial.println("Unsubscribe acknowledged.");
- Serial.print(" packetId: ");
- Serial.println(packetId);
- } // onMqttUnsubscribe()
- void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
- int i; for (i = 0; i < len; i++) message_buff[i] = payload[i]; message_buff[i] = '\0'; // We copy payload to message_buff because we can't make a string out of payload.
- String msgString = String(message_buff);
- uint8_t msgVal = msgString.toInt();
- Serial.println("Publish received.");
- Serial.print(" topic: ");
- Serial.println(topic);
- Serial.print(" msvVal: ");
- Serial.println(msgVal);
- Serial.print(" qos: ");
- Serial.println(properties.qos);
- Serial.print(" len: ");
- Serial.println(len);
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal, "device"))== 0) { // Device selector
- mydevice = msgString.toInt();
- Serial.print("device: "); Serial.println(mydevice);
- }
- if (mydevice == 0 || mydevice == STRANDID) {
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal,"bri")) == 0) { // Brightness
- mybri = msgString.toInt();
- Serial.print("mybri: "); Serial.println(mybri);
- }
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal,"hue"))== 0) { // Hue.
- myhue = msgString.toInt();
- Serial.print("myhue: "); Serial.println(myhue);
- targetPalette = CRGBPalette16(CHSV(myhue, 255, 16), CHSV(myhue+8, 248, 64), CHSV(myhue+32, 224, 128), CHSV(myhue+64, 192, 255));
- }
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal,"speed"))== 0) { // Speed
- myspeed = msgString.toInt();
- Serial.print("myspeed: "); Serial.println(myspeed);
- }
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal,"cool"))== 0) { // Cooling
- mycool = msgString.toInt();
- Serial.print("mycool: "); Serial.println(mycool);
- }
- strcpy(theVal, prefixtopic);
- if (strcmp(topic, strcat(theVal,"spark"))== 0) { // Sparking
- myspark = msgString.toInt();
- Serial.print("myspark: "); Serial.println(myspark);
- }
- } // if mydevice
- } // onMqttMessage()
- void onMqttPublish(uint16_t packetId) {
- Serial.println("Publish acknowledged.");
- Serial.print(" packetId: ");
- Serial.println(packetId);
- } // onMqttPublish()
- void setup() {
- Serial.begin(115200);
- delay(1000);
- LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS); // Use this for WS2812
- // LEDS.addLeds<LED_TYPE, LED_DT, LED_CK, COLOR_ORDER>(leds, NUM_LEDS); // Use this for APA102
- FastLED.setBrightness(max_bright);
- set_max_power_in_volts_and_milliamps(5, 500); // FastLED Power management set at 5V, 500mA.
- currentPalette = CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Orange, CRGB::Yellow);
- targetPalette = CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Orange, CRGB::Yellow);
- wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
- wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
- mqttClient.onConnect(onMqttConnect);
- mqttClient.onDisconnect(onMqttDisconnect);
- mqttClient.onSubscribe(onMqttSubscribe);
- mqttClient.onUnsubscribe(onMqttUnsubscribe);
- mqttClient.onMessage(onMqttMessage);
- mqttClient.onPublish(onMqttPublish);
- connectToWifi();
- } // setup()
- void Fire2012WithPalettexy() {
- static byte heat[kMatrixWidth][kMatrixHeight]; // Array of temperature readings at each simulation cell
- for (int mw = 0; mw < kMatrixWidth; mw++) { // Move along the width of the flame
- for (int mh = 0; mh < kMatrixHeight; mh++) { // Step 1. Cool down every cell a little
- heat[mw][mh] = qsub8( heat[mw][mh], random16(0, ((mycool * 10) / kMatrixHeight) + 2));
- }
- for (int mh = kMatrixHeight - 1; mh >= 2; mh--) { // Step 2. Heat from each cell drifts 'up' and diffuses a little
- heat[mw][mh] = (heat[mw][mh - 1] + heat[mw][mh - 2] + heat[mw][mh - 2] ) / 3;
- }
- if (random8(0,255) < myspark ) { // Step 3. Randomly ignite new 'sparks' of heat near the bottom
- int mh = random8(3);
- heat[mw][mh] = qadd8( heat[mw][mh], random8(160,255) );
- }
- for (int mh = 0; mh < kMatrixHeight; mh++) { // Step 4. Map from heat cells to LED colors
- byte colorindex = scale8( heat[mw][mh], 240);
- leds[ XY(mh, mw)] = ColorFromPalette( targetPalette, colorindex, mybri, currentBlending);
- }
- } // for mw
- } // Fire2012WithPalettexy()
- uint16_t XY( uint8_t x, uint8_t y) { // x is height, y is width. Allows us to have 2 sided display.
- uint16_t i;
- if( kMatrixSerpentineLayout == false) {
- i = (y * kMatrixHeight) + x;
- }
- if( kMatrixSerpentineLayout == true) {
- if( y & 0x01) {
- // Odd rows run backwards
- uint8_t reverseX = (kMatrixHeight - 1) - x;
- i = (y * kMatrixHeight) + reverseX;
- } else {
- // Even rows run forwards
- i = (y * kMatrixHeight) + x;
- }
- }
- return i;
- } // XY()
- void loop() {
- EVERY_N_MILLISECONDS(100) { // FastLED based non-blocking FIXED delay.
- uint8_t maxChanges = 24;
- nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // Awesome palette blending capability.
- }
- EVERY_N_MILLIS_I(thisTimer,50) { // This only sets the Initial timer delay. To change this value, you need to use thisTimer.setPeriod(); You could also call it thatTimer and so on.
- thisTimer.setPeriod(myspeed); // Use that as our update timer value.
- Fire2012WithPalettexy();
- }
- FastLED.show();
- } // loop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement