From 3b22f0d99722d03308bd30480eb63f46da1c6e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:24:54 -0400 Subject: [PATCH 01/24] Reorganize files, add .gitignore --- .gitignore | 1 + Sunrise_CONFIGURE.ino => Sunrise/Sunrise.ino | 0 2 files changed, 1 insertion(+) create mode 100644 .gitignore rename Sunrise_CONFIGURE.ino => Sunrise/Sunrise.ino (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d74e21 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode/ diff --git a/Sunrise_CONFIGURE.ino b/Sunrise/Sunrise.ino similarity index 100% rename from Sunrise_CONFIGURE.ino rename to Sunrise/Sunrise.ino From 4909b0f653244c4c681b443401b4dbf5c5eb4079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:35:24 -0400 Subject: [PATCH 02/24] Moving the user configuration into config.h --- .gitignore | 1 + Sunrise/Sunrise.ino | 23 +---------------------- Sunrise/config_template.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 Sunrise/config_template.h diff --git a/.gitignore b/.gitignore index 1d74e21..11b4961 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .vscode/ +Sunrise/config.h diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 0d3b332..4f82e9c 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -6,28 +6,7 @@ #include //if you get an error here you need to install the ESP8266 board manager #include //ArduinoOTA is now included with the ArduinoIDE -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ - -#define USER_SSID "YOUR_WIFI_SSID" -#define USER_PASSWORD "YOUR_WIFI_PASSWORD" -#define USER_MQTT_SERVER "YOUR MQTT SERVER" -#define USER_MQTT_PORT 1883 -#define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" -#define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" -#define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA -#define LED_PIN 5 //pin where the led strip is hooked up -#define NUM_LEDS 136 //number of LEDs in the strip -#define BRIGHTNESS 255 //strip brightness 255 max -#define SUNSIZE 30 //percentage of the strip that is the "sun" - -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ +#include "config.h" /*********************** WIFI AND MQTT SETUP *****************************/ /*********************** DON'T CHANGE THIS INFO *****************************/ diff --git a/Sunrise/config_template.h b/Sunrise/config_template.h new file mode 100644 index 0000000..60308de --- /dev/null +++ b/Sunrise/config_template.h @@ -0,0 +1,31 @@ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ + +#define USER_SSID "YOUR_WIFI_SSID" +#define USER_PASSWORD "YOUR_WIFI_PASSWORD" +#define USER_MQTT_SERVER "YOUR MQTT SERVER" +#define USER_MQTT_PORT 1883 +#define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" +#define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" +#define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA +#if defined(ESP32) + #define LED_PIN 23 //pin where the led strip is hooked up +#else + #define LED_PIN 5 //pin where the led strip is hooked up +#endif +#define NUM_LEDS 150 //number of LEDs in the strip +#define BRIGHTNESS 255 //strip brightness 255 max +#define SUNSIZE 30 //percentage of the strip that is the "sun" + + +#define ENABLE_OTA 1 + +//#define DEBUG 1 + +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ From 8be85c1b8e9bb931252ec48fcc8410832df54ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:53:57 -0400 Subject: [PATCH 03/24] Exclude the ./build folder from git. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 11b4961..a1e74d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ +build/ Sunrise/config.h From f14938dc182c65d25381b4ef7b81e0d0588a3bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:54:54 -0400 Subject: [PATCH 04/24] Add ESP32 support --- Sunrise/Sunrise.ino | 99 +++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 4f82e9c..30476de 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -1,23 +1,45 @@ +/***************** USER CONFIG SECTION ***************************************/ +#include "config.h" + /****************** LIBRARY SECTION *************************************/ #include //https://github.com/adafruit/Adafruit_NeoPixel #include //https://github.com/thehookup/Simple-Timer-Library #include //https://github.com/knolleary/pubsubclient -#include //if you get an error here you need to install the ESP8266 board manager -#include //if you get an error here you need to install the ESP8266 board manager -#include //ArduinoOTA is now included with the ArduinoIDE - -#include "config.h" +#ifdef ESP32 + #include + #include +#elif defined(ESP8266) + #include + #include +#endif +#ifdef ENABLE_OTA + #include //ArduinoOTA is now included with the ArduinoIDE +#endif + +#ifdef ESP32 + #define LED_ON HIGH + #define LED_OFF LOW +#else + #define LED_ON LOW + #define LED_OFF HIGH +#endif + +// Function definitions +void increaseSunFadeStep(); +void increaseFadeStep(); +void increaseWhiteLevel(); +void increaseSunPhase(); /*********************** WIFI AND MQTT SETUP *****************************/ /*********************** DON'T CHANGE THIS INFO *****************************/ -const char* ssid = USER_SSID ; +const char* ssid = USER_SSID ; const char* password = USER_PASSWORD ; const char* mqtt_server = USER_MQTT_SERVER ; const int mqtt_port = USER_MQTT_PORT ; const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; -const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; /***************** DECLARATIONS ****************************************/ WiFiClient espClient; @@ -33,7 +55,7 @@ int aurora = NUM_LEDS; //int aurora = (SUNSIZE+40 * NUM_LEDS)/100; int sunPhase = 0; int whiteLevel = 0; -byte red = 127; +byte red = 127; byte green = 127; byte blue = 127; byte white = 127; @@ -48,8 +70,22 @@ int currentSun = 0; int oldSun = 0; int sunFadeStep = 0; -void setup_wifi() +void setup_wifi() { + #ifdef ESP32 + WiFi.setSleep(false); + #else + WiFi.setSleepMode(WIFI_NONE_SLEEP); + #endif + + WiFi.mode(WIFI_STA); + + #ifdef ESP32 + WiFi.setHostname(USER_MQTT_CLIENT_NAME); + #else + WiFi.hostname(USER_MQTT_CLIENT_NAME); + #endif + // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); @@ -68,7 +104,7 @@ void setup_wifi() Serial.println(WiFi.localIP()); } -void reconnect() +void reconnect() { // Loop until we're reconnected int retries = 0; @@ -77,7 +113,7 @@ void reconnect() { Serial.print("Attempting MQTT connection..."); // Attempt to connect - if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) + if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) { Serial.println("connected"); // Once connected, publish an announcement... @@ -88,15 +124,15 @@ void reconnect() } if(boot == false) { - client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Reconnected"); + client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Reconnected"); } client.subscribe(USER_MQTT_CLIENT_NAME"/command"); client.subscribe(USER_MQTT_CLIENT_NAME"/effect"); client.subscribe(USER_MQTT_CLIENT_NAME"/color"); client.subscribe(USER_MQTT_CLIENT_NAME"/white"); client.subscribe(USER_MQTT_CLIENT_NAME"/wakeAlarm"); - } - else + } + else { Serial.print("failed, rc="); Serial.print(client.state()); @@ -120,7 +156,7 @@ void reconnect() /************************** MQTT CALLBACK ***********************/ -void callback(char* topic, byte* payload, unsigned int length) +void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); String newTopic = topic; @@ -159,7 +195,7 @@ void callback(char* topic, byte* payload, unsigned int length) } if (newTopic == USER_MQTT_CLIENT_NAME "/color") { - client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); + client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); // get the position of the first and second commas uint8_t firstIndex = newPayload.indexOf(','); uint8_t lastIndex = newPayload.lastIndexOf(','); @@ -254,7 +290,7 @@ void drawSun() { sunFadeStep = 0; } - + int sunStart = (NUM_LEDS/2)-(currentSun/2); int newSunLeft = sunStart-1; int newSunRight = sunStart+currentSun; @@ -267,7 +303,7 @@ void drawSun() } for(int i = sunStart; i < sunStart+currentSun; i++) { - strip.setPixelColor(i, 255, 64,0,whiteLevel); + strip.setPixelColor(i, 255, 64,0,whiteLevel); } oldSun = currentSun; } @@ -296,7 +332,7 @@ void drawAurora() } for(int i = sunStart; i < sunStart+currentAurora; i++) { - strip.setPixelColor(i, 127, 25,0,0); + strip.setPixelColor(i, 127, 25,0,0); } oldFadeStep = fadeStep; oldAurora = currentAurora; @@ -306,7 +342,7 @@ void drawAmbient() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, whiteLevel, 0,0,0); + strip.setPixelColor(i, whiteLevel, 0,0,0); } } @@ -338,42 +374,53 @@ void selectEffect() if(effect == "sunrise") { sunRise(); + digitalWrite(LED_BUILTIN, LED_ON); } if(effect == "mqttRGB") { mqttRGB(); + digitalWrite(LED_BUILTIN, LED_ON); } if(effect == "off") { off(); + digitalWrite(LED_BUILTIN, LED_OFF); } } -void setup() +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + digitalWrite(LED_BUILTIN, LED_OFF); // Turn the LED off by making the voltage HIGH Serial.begin(115200); - WiFi.setSleepMode(WIFI_NONE_SLEEP); - WiFi.mode(WIFI_STA); +#if defined(DEBUG) && defined(ESP8266) + gdbstub_init(); +#endif setup_wifi(); + client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); + #ifdef ENABLE_OTA ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); - ArduinoOTA.begin(); + ArduinoOTA.begin(); + #endif strip.setBrightness(BRIGHTNESS); strip.begin(); } void loop() { - if (!client.connected()) + if (!client.connected()) { reconnect(); } client.loop(); + #ifdef ENABLE_OTA ArduinoOTA.handle(); + #endif timer.run(); selectEffect(); - strip.show(); + strip.show(); } From 9b4698e8641ed1daeb00c8872955aa7182f6fa7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:16:19 -0400 Subject: [PATCH 05/24] Remove unnecessary checks. uint8_t is always between 0 and 255 --- Sunrise/Sunrise.ino | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 30476de..4295b98 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -100,7 +100,7 @@ void setup_wifi() Serial.println(""); Serial.println("WiFi connected"); - Serial.println("IP address: "); + Serial.print("IP address: "); Serial.println(WiFi.localIP()); } @@ -201,33 +201,13 @@ void callback(char* topic, byte* payload, unsigned int length) uint8_t lastIndex = newPayload.lastIndexOf(','); uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); - if (rgb_red < 0 || rgb_red > 255) - { - return; - } - else - { - red = rgb_red; - } - + red = rgb_red; + uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); - if (rgb_green < 0 || rgb_green > 255) - { - return; - } - else - { - green = rgb_green; - } + green = rgb_green; uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); - if (rgb_blue < 0 || rgb_blue > 255) - { - return; - } - else - { - blue = rgb_blue; + blue = rgb_blue; } } } From d45a77ef63c008a40226c83670b1e7d3017f71f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:25:32 -0400 Subject: [PATCH 06/24] Add some debug code to see the memory usage --- Sunrise/Sunrise.ino | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 4295b98..a2802d2 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -70,6 +70,10 @@ int currentSun = 0; int oldSun = 0; int sunFadeStep = 0; +#ifdef DEBUG + unsigned int debugTime; +#endif + void setup_wifi() { #ifdef ESP32 @@ -208,7 +212,6 @@ void callback(char* topic, byte* payload, unsigned int length) uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); blue = rgb_blue; - } } } @@ -401,6 +404,23 @@ void loop() timer.run(); selectEffect(); strip.show(); + + #ifdef DEBUG + if ( millis() - debugTime > 5000 ) { + Serial.print("FreeHeap: "); + Serial.print(ESP.getFreeHeap()); + #if defined(ESP8266) + Serial.print(" HeapFragmentation: "); + Serial.print(ESP.getHeapFragmentation()); + Serial.print(" MaxFreeBlockSize: "); + Serial.println(ESP.getMaxFreeBlockSize()); + #elif defined(ESP32) + Serial.print(" MaxAllocHeap: "); + Serial.println(ESP.getMaxAllocHeap()); + #endif + debugTime = millis(); + } + #endif } From 9e41791a7b9eec76ccf1ff98b850954d336a7e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:39:43 -0400 Subject: [PATCH 07/24] Use enum as effect instead of string comparison. --- Sunrise/Sunrise.ino | 79 +++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index a2802d2..0d8c9a6 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -41,6 +41,9 @@ const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +/***************** ENUMS ****************************************/ +enum Effects { eOff, eSunrise, eMqttRGB }; + /***************** DECLARATIONS ****************************************/ WiFiClient espClient; PubSubClient client(espClient); @@ -59,7 +62,7 @@ byte red = 127; byte green = 127; byte blue = 127; byte white = 127; -String effect = "off"; +Effects effect = eOff; char charPayload[50]; int wakeDelay = 1000; int fadeStep = 0; @@ -166,16 +169,25 @@ void callback(char* topic, byte* payload, unsigned int length) String newTopic = topic; Serial.print(topic); Serial.print("] "); - payload[length] = '\0'; - String newPayload = String((char *)payload); + memset(&charPayload,0,sizeof(charPayload)); + memcpy(charPayload, payload, min(sizeof(charPayload),length)); + charPayload[length] = '\0'; + String newPayload = String(charPayload); int intPayload = newPayload.toInt(); Serial.println(newPayload); Serial.println(); - newPayload.toCharArray(charPayload, newPayload.length() + 1); - - if (newTopic == USER_MQTT_CLIENT_NAME"/command") + newPayload.toCharArray(charPayload, newPayload.length() + 1); + + if (newTopic == USER_MQTT_CLIENT_NAME"/command") { - effect = newPayload; + //effect = newPayload; + if ( strcmp(charPayload, "off") == 0 ) + { + effect = eOff; + } else if ( strcmp(charPayload, "mqttRGB") == 0 ) + { + effect = eMqttRGB; + } client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload); } if (newTopic == USER_MQTT_CLIENT_NAME"/wakeAlarm") @@ -184,7 +196,7 @@ void callback(char* topic, byte* payload, unsigned int length) sunPhase = 0; fadeStep = 0; sunFadeStep = 0; - effect = "sunrise"; + effect = eSunrise; wakeDelay = intPayload*10; timer.setTimeout(wakeDelay, increaseSunPhase); timer.setTimeout(wakeDelay, increaseWhiteLevel); @@ -201,17 +213,20 @@ void callback(char* topic, byte* payload, unsigned int length) { client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); // get the position of the first and second commas - uint8_t firstIndex = newPayload.indexOf(','); - uint8_t lastIndex = newPayload.lastIndexOf(','); - - uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); - red = rgb_red; - - uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); - green = rgb_green; - - uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); - blue = rgb_blue; + int firstIndex = newPayload.indexOf(','); + int lastIndex = newPayload.lastIndexOf(','); + + if ( ( firstIndex > -1) && (lastIndex > -1) && (firstIndex != lastIndex) ) + { + uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); + red = rgb_red; + + uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); + green = rgb_green; + + uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); + blue = rgb_blue; + } } } @@ -354,20 +369,20 @@ void mqttRGB() void selectEffect() { - if(effect == "sunrise") - { - sunRise(); - digitalWrite(LED_BUILTIN, LED_ON); - } - if(effect == "mqttRGB") - { - mqttRGB(); - digitalWrite(LED_BUILTIN, LED_ON); - } - if(effect == "off") + switch(effect) { - off(); - digitalWrite(LED_BUILTIN, LED_OFF); + case eSunrise: + sunRise(); + digitalWrite(LED_BUILTIN, LED_ON); + break; + case eMqttRGB: + mqttRGB(); + digitalWrite(LED_BUILTIN, LED_ON); + break; + default: + off(); + digitalWrite(LED_BUILTIN, LED_OFF); + break; } } From edd45aea5d7542f127f212336bd86668836108d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:47:11 -0400 Subject: [PATCH 08/24] Adding additional OTA code. --- Sunrise/Sunrise.ino | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 0d8c9a6..9d6c217 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -399,8 +399,38 @@ void setup() client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); #ifdef ENABLE_OTA - ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); - ArduinoOTA.begin(); + ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); + ArduinoOTA.onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) { + type = "sketch"; + } else { // U_SPIFFS + type = "filesystem"; + } + Serial.println("Start updating " + type); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) { + Serial.println("Auth Failed"); + } else if (error == OTA_BEGIN_ERROR) { + Serial.println("Begin Failed"); + } else if (error == OTA_CONNECT_ERROR) { + Serial.println("Connect Failed"); + } else if (error == OTA_RECEIVE_ERROR) { + Serial.println("Receive Failed"); + } else if (error == OTA_END_ERROR) { + Serial.println("End Failed"); + } + }); + + ArduinoOTA.begin(); #endif strip.setBrightness(BRIGHTNESS); strip.begin(); @@ -414,7 +444,7 @@ void loop() } client.loop(); #ifdef ENABLE_OTA - ArduinoOTA.handle(); + ArduinoOTA.handle(); #endif timer.run(); selectEffect(); From 1f82fac8b6fe16beaf6424aad2f330603e907d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 22:07:22 -0400 Subject: [PATCH 09/24] Swap out the Adafruit_Neopixel library with NeoPixelBus library --- Sunrise/Sunrise.ino | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 9d6c217..bb7f04b 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -2,7 +2,7 @@ #include "config.h" /****************** LIBRARY SECTION *************************************/ -#include //https://github.com/adafruit/Adafruit_NeoPixel +#include //https://github.com/Makuna/NeoPixelBus #include //https://github.com/thehookup/Simple-Timer-Library #include //https://github.com/knolleary/pubsubclient #ifdef ESP32 @@ -48,7 +48,7 @@ enum Effects { eOff, eSunrise, eMqttRGB }; WiFiClient espClient; PubSubClient client(espClient); SimpleTimer timer; -Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRBW + NEO_KHZ800); +NeoPixelBus strip(NUM_LEDS, LED_PIN); /***************** GENERAL VARIABLES *************************************/ @@ -296,12 +296,12 @@ void drawSun() { int redValue = map(sunFadeStep, 0, 100, 127, 255); int whiteValue = map(sunFadeStep, 0, 100, 0, whiteLevel); - strip.setPixelColor(newSunLeft, redValue, 25,0,whiteValue); - strip.setPixelColor(newSunRight, redValue, 25,0,whiteValue); + strip.SetPixelColor(newSunLeft, RgbwColor(redValue, 25,0,whiteValue)); + strip.SetPixelColor(newSunRight, RgbwColor(redValue, 25,0,whiteValue)); } for(int i = sunStart; i < sunStart+currentSun; i++) { - strip.setPixelColor(i, 255, 64,0,whiteLevel); + strip.SetPixelColor(i, RgbwColor(255, 64,0,whiteLevel)); } oldSun = currentSun; } @@ -325,12 +325,12 @@ void drawAurora() { int redValue = map(fadeStep, 0, 100, whiteLevel, 127); int greenValue = map(fadeStep, 0, 100, 0, 25); - strip.setPixelColor(newAuroraRight, redValue, greenValue,0,0); - strip.setPixelColor(newAuroraLeft, redValue, greenValue,0,0); + strip.SetPixelColor(newAuroraRight, RgbwColor(redValue, greenValue,0,0)); + strip.SetPixelColor(newAuroraLeft, RgbwColor(redValue, greenValue,0,0)); } for(int i = sunStart; i < sunStart+currentAurora; i++) { - strip.setPixelColor(i, 127, 25,0,0); + strip.SetPixelColor(i, RgbwColor(127, 25,0,0)); } oldFadeStep = fadeStep; oldAurora = currentAurora; @@ -340,7 +340,7 @@ void drawAmbient() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, whiteLevel, 0,0,0); + strip.SetPixelColor(i, RgbwColor(whiteLevel,0,0,0)); } } @@ -355,7 +355,7 @@ void off() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, 0,0,0,0); + strip.SetPixelColor(i, RgbwColor(0,0,0,0)); } } @@ -363,7 +363,7 @@ void mqttRGB() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, red,green,blue,white); + strip.SetPixelColor(i, RgbwColor(red,green,blue,white)); } } @@ -432,8 +432,10 @@ void setup() ArduinoOTA.begin(); #endif - strip.setBrightness(BRIGHTNESS); - strip.begin(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); } void loop() @@ -448,7 +450,7 @@ void loop() #endif timer.run(); selectEffect(); - strip.show(); + strip.Show(); #ifdef DEBUG if ( millis() - debugTime > 5000 ) { From 6a8e412ed1690b2c36102c2d52307e8352675b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Wed, 16 Oct 2019 06:43:22 -0400 Subject: [PATCH 10/24] MQTT tweaks, adding last will and making the state retain. --- Sunrise/Sunrise.ino | 6 ++++-- Sunrise/config_template.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index bb7f04b..0d3f6d1 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -40,6 +40,7 @@ const int mqtt_port = USER_MQTT_PORT ; const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +const char *mqtt_lwt_topic = LWTTOPIC ; /***************** ENUMS ****************************************/ enum Effects { eOff, eSunrise, eMqttRGB }; @@ -120,9 +121,10 @@ void reconnect() { Serial.print("Attempting MQTT connection..."); // Attempt to connect - if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) + if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass, mqtt_lwt_topic, 0, true, "Offline")) { Serial.println("connected"); + client.publish(mqtt_lwt_topic, "Online", true); // Once connected, publish an announcement... if(boot == true) { @@ -188,7 +190,7 @@ void callback(char* topic, byte* payload, unsigned int length) { effect = eMqttRGB; } - client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload); + client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload, true); } if (newTopic == USER_MQTT_CLIENT_NAME"/wakeAlarm") { diff --git a/Sunrise/config_template.h b/Sunrise/config_template.h index 60308de..729b5a8 100644 --- a/Sunrise/config_template.h +++ b/Sunrise/config_template.h @@ -10,6 +10,8 @@ #define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" #define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" #define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA +#define LWTTOPIC "LWT/" USER_MQTT_CLIENT_NAME + #if defined(ESP32) #define LED_PIN 23 //pin where the led strip is hooked up #else From 67d8c9eb0b0661857baa992bd332c2d0bcf110d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 20 Oct 2019 12:07:00 -0400 Subject: [PATCH 11/24] Add availability to the example --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 423b1a6..bdb9696 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,9 @@ light: rgb_state_topic: "SunriseMCU/colorState" white_value_command_topic: "SunriseMCU/white" white_value_state_topic: "SunriseMCU/whiteState" + availability_topic: "LWT/SunriseMCU" + payload_available: "Online" + payload_not_available: "Offline" white_value_scale: 255 retain: true ``` From 2502631bdc393c5bf45d9395fc6ceaf9d344e315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:24:54 -0400 Subject: [PATCH 12/24] Reorganize files, add .gitignore --- .gitignore | 1 + Sunrise_CONFIGURE.ino => Sunrise/Sunrise.ino | 0 2 files changed, 1 insertion(+) create mode 100644 .gitignore rename Sunrise_CONFIGURE.ino => Sunrise/Sunrise.ino (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d74e21 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode/ diff --git a/Sunrise_CONFIGURE.ino b/Sunrise/Sunrise.ino similarity index 100% rename from Sunrise_CONFIGURE.ino rename to Sunrise/Sunrise.ino From 4b81bb2b526ff51309760ccfad2ffd135e960b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:35:24 -0400 Subject: [PATCH 13/24] Moving the user configuration into config.h --- .gitignore | 1 + Sunrise/Sunrise.ino | 23 +---------------------- Sunrise/config_template.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 Sunrise/config_template.h diff --git a/.gitignore b/.gitignore index 1d74e21..11b4961 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .vscode/ +Sunrise/config.h diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 6111bf4..f17802a 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -6,28 +6,7 @@ #include //if you get an error here you need to install the ESP8266 board manager #include //ArduinoOTA is now included with the ArduinoIDE -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ -/***************** START USER CONFIG SECTION *********************************/ - -#define USER_SSID "YOUR_WIFI_SSID" -#define USER_PASSWORD "YOUR_WIFI_PASSWORD" -#define USER_MQTT_SERVER "YOUR MQTT SERVER" -#define USER_MQTT_PORT 1883 -#define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" -#define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" -#define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA -#define LED_PIN 5 //pin where the led strip is hooked up -#define NUM_LEDS 136 //number of LEDs in the strip -#define BRIGHTNESS 255 //strip brightness 255 max -#define SUNSIZE 30 //percentage of the strip that is the "sun" - -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ -/***************** END USER CONFIG SECTION *********************************/ +#include "config.h" /*********************** WIFI AND MQTT SETUP *****************************/ /*********************** DON'T CHANGE THIS INFO *****************************/ diff --git a/Sunrise/config_template.h b/Sunrise/config_template.h new file mode 100644 index 0000000..60308de --- /dev/null +++ b/Sunrise/config_template.h @@ -0,0 +1,31 @@ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ +/***************** START USER CONFIG SECTION *********************************/ + +#define USER_SSID "YOUR_WIFI_SSID" +#define USER_PASSWORD "YOUR_WIFI_PASSWORD" +#define USER_MQTT_SERVER "YOUR MQTT SERVER" +#define USER_MQTT_PORT 1883 +#define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" +#define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" +#define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA +#if defined(ESP32) + #define LED_PIN 23 //pin where the led strip is hooked up +#else + #define LED_PIN 5 //pin where the led strip is hooked up +#endif +#define NUM_LEDS 150 //number of LEDs in the strip +#define BRIGHTNESS 255 //strip brightness 255 max +#define SUNSIZE 30 //percentage of the strip that is the "sun" + + +#define ENABLE_OTA 1 + +//#define DEBUG 1 + +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ +/***************** END USER CONFIG SECTION *********************************/ From 9ae306f01e969ef4d85733770b630b978bc74779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:53:57 -0400 Subject: [PATCH 14/24] Exclude the ./build folder from git. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 11b4961..a1e74d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ +build/ Sunrise/config.h From 766f3ebf801ea9147913b8d4d0f6a573146a6388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 18:54:54 -0400 Subject: [PATCH 15/24] Add ESP32 support --- Sunrise/Sunrise.ino | 97 +++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index f17802a..7b165c8 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -1,23 +1,45 @@ +/***************** USER CONFIG SECTION ***************************************/ +#include "config.h" + /****************** LIBRARY SECTION *************************************/ #include //https://github.com/adafruit/Adafruit_NeoPixel #include //https://github.com/thehookup/Simple-Timer-Library #include //https://github.com/knolleary/pubsubclient -#include //if you get an error here you need to install the ESP8266 board manager -#include //if you get an error here you need to install the ESP8266 board manager -#include //ArduinoOTA is now included with the ArduinoIDE - -#include "config.h" +#ifdef ESP32 + #include + #include +#elif defined(ESP8266) + #include + #include +#endif +#ifdef ENABLE_OTA + #include //ArduinoOTA is now included with the ArduinoIDE +#endif + +#ifdef ESP32 + #define LED_ON HIGH + #define LED_OFF LOW +#else + #define LED_ON LOW + #define LED_OFF HIGH +#endif + +// Function definitions +void increaseSunFadeStep(); +void increaseFadeStep(); +void increaseWhiteLevel(); +void increaseSunPhase(); /*********************** WIFI AND MQTT SETUP *****************************/ /*********************** DON'T CHANGE THIS INFO *****************************/ -const char* ssid = USER_SSID ; +const char* ssid = USER_SSID ; const char* password = USER_PASSWORD ; const char* mqtt_server = USER_MQTT_SERVER ; const int mqtt_port = USER_MQTT_PORT ; const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; -const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; /***************** DECLARATIONS ****************************************/ WiFiClient espClient; @@ -48,8 +70,22 @@ int currentSun = 100; int oldSun = 0; int sunFadeStep = 98; -void setup_wifi() +void setup_wifi() { + #ifdef ESP32 + WiFi.setSleep(false); + #else + WiFi.setSleepMode(WIFI_NONE_SLEEP); + #endif + + WiFi.mode(WIFI_STA); + + #ifdef ESP32 + WiFi.setHostname(USER_MQTT_CLIENT_NAME); + #else + WiFi.hostname(USER_MQTT_CLIENT_NAME); + #endif + // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); @@ -69,7 +105,7 @@ void setup_wifi() Serial.println(WiFi.localIP()); } -void reconnect() +void reconnect() { // Loop until we're reconnected int retries = 0; @@ -78,7 +114,7 @@ void reconnect() { Serial.print("Attempting MQTT connection..."); // Attempt to connect - if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) + if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) { Serial.println("connected"); // Once connected, publish an announcement... @@ -89,15 +125,15 @@ void reconnect() } if(boot == false) { - client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Reconnected"); + client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Reconnected"); } client.subscribe(USER_MQTT_CLIENT_NAME"/command"); client.subscribe(USER_MQTT_CLIENT_NAME"/effect"); client.subscribe(USER_MQTT_CLIENT_NAME"/color"); client.subscribe(USER_MQTT_CLIENT_NAME"/white"); client.subscribe(USER_MQTT_CLIENT_NAME"/wakeAlarm"); - } - else + } + else { Serial.print("failed, rc="); Serial.print(client.state()); @@ -121,7 +157,7 @@ void reconnect() /************************** MQTT CALLBACK ***********************/ -void callback(char* topic, byte* payload, unsigned int length) +void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); String newTopic = topic; @@ -161,7 +197,7 @@ void callback(char* topic, byte* payload, unsigned int length) } if (newTopic == USER_MQTT_CLIENT_NAME "/color") { - client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); + client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); // get the position of the first and second commas uint8_t firstIndex = newPayload.indexOf(','); uint8_t lastIndex = newPayload.lastIndexOf(','); @@ -256,7 +292,7 @@ void drawSun() { sunFadeStep = 0; } - + int sunStart = (NUM_LEDS/2)-(currentSun/2); int newSunLeft = sunStart-1; int newSunRight = sunStart+currentSun; @@ -269,7 +305,7 @@ void drawSun() } for(int i = sunStart; i < sunStart+currentSun; i++) { - strip.setPixelColor(i, 255, 64,0,whiteLevel); + strip.setPixelColor(i, 255, 64,0,whiteLevel); } oldSun = currentSun; } @@ -298,7 +334,7 @@ void drawAurora() } for(int i = sunStart; i < sunStart+currentAurora; i++) { - strip.setPixelColor(i, 127, 25,0,0); + strip.setPixelColor(i, 127, 25,0,0); } oldFadeStep = fadeStep; oldAurora = currentAurora; @@ -308,7 +344,7 @@ void drawAmbient() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, whiteLevel, 0,0,0); + strip.setPixelColor(i, whiteLevel, 0,0,0); } } @@ -340,42 +376,53 @@ void selectEffect() if(effect == "sunrise") { sunRise(); + digitalWrite(LED_BUILTIN, LED_ON); } if(effect == "mqttRGB") { mqttRGB(); + digitalWrite(LED_BUILTIN, LED_ON); } if(effect == "off") { off(); + digitalWrite(LED_BUILTIN, LED_OFF); } } -void setup() +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + digitalWrite(LED_BUILTIN, LED_OFF); // Turn the LED off by making the voltage HIGH Serial.begin(115200); - WiFi.setSleepMode(WIFI_NONE_SLEEP); - WiFi.mode(WIFI_STA); +#if defined(DEBUG) && defined(ESP8266) + gdbstub_init(); +#endif setup_wifi(); + client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); + #ifdef ENABLE_OTA ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); - ArduinoOTA.begin(); + ArduinoOTA.begin(); + #endif strip.setBrightness(BRIGHTNESS); strip.begin(); } void loop() { - if (!client.connected()) + if (!client.connected()) { reconnect(); } client.loop(); + #ifdef ENABLE_OTA ArduinoOTA.handle(); + #endif timer.run(); selectEffect(); - strip.show(); + strip.show(); } From e733526e2251a27f590ec9e5dcacb915b7f6f6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:16:19 -0400 Subject: [PATCH 16/24] Remove unnecessary checks. uint8_t is always between 0 and 255 --- Sunrise/Sunrise.ino | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 7b165c8..be9395b 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -101,7 +101,7 @@ void setup_wifi() Serial.println(""); Serial.println("WiFi connected"); - Serial.println("IP address: "); + Serial.print("IP address: "); Serial.println(WiFi.localIP()); } @@ -203,33 +203,13 @@ void callback(char* topic, byte* payload, unsigned int length) uint8_t lastIndex = newPayload.lastIndexOf(','); uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); - if (rgb_red < 0 || rgb_red > 255) - { - return; - } - else - { - red = rgb_red; - } - + red = rgb_red; + uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); - if (rgb_green < 0 || rgb_green > 255) - { - return; - } - else - { - green = rgb_green; - } + green = rgb_green; uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); - if (rgb_blue < 0 || rgb_blue > 255) - { - return; - } - else - { - blue = rgb_blue; + blue = rgb_blue; } } } From 88c6f5a9359fd5818b436e499f69f3270dbfb0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:25:32 -0400 Subject: [PATCH 17/24] Add some debug code to see the memory usage --- Sunrise/Sunrise.ino | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index be9395b..ae95fb6 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -70,6 +70,10 @@ int currentSun = 100; int oldSun = 0; int sunFadeStep = 98; +#ifdef DEBUG + unsigned int debugTime; +#endif + void setup_wifi() { #ifdef ESP32 @@ -210,7 +214,6 @@ void callback(char* topic, byte* payload, unsigned int length) uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); blue = rgb_blue; - } } } @@ -403,6 +406,23 @@ void loop() timer.run(); selectEffect(); strip.show(); + + #ifdef DEBUG + if ( millis() - debugTime > 5000 ) { + Serial.print("FreeHeap: "); + Serial.print(ESP.getFreeHeap()); + #if defined(ESP8266) + Serial.print(" HeapFragmentation: "); + Serial.print(ESP.getHeapFragmentation()); + Serial.print(" MaxFreeBlockSize: "); + Serial.println(ESP.getMaxFreeBlockSize()); + #elif defined(ESP32) + Serial.print(" MaxAllocHeap: "); + Serial.println(ESP.getMaxAllocHeap()); + #endif + debugTime = millis(); + } + #endif } From b5625744b5212ce6cf9ede40ba26376908cf2cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:39:43 -0400 Subject: [PATCH 18/24] Use enum as effect instead of string comparison. --- Sunrise/Sunrise.ino | 79 +++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index ae95fb6..32ff7dc 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -41,6 +41,9 @@ const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +/***************** ENUMS ****************************************/ +enum Effects { eOff, eSunrise, eMqttRGB }; + /***************** DECLARATIONS ****************************************/ WiFiClient espClient; PubSubClient client(espClient); @@ -59,7 +62,7 @@ byte red = 127; byte green = 127; byte blue = 127; byte white = 127; -String effect = "off"; +Effects effect = eOff; char charPayload[50]; int wakeDelay = 1000; int fadeStep = 98; @@ -167,16 +170,25 @@ void callback(char* topic, byte* payload, unsigned int length) String newTopic = topic; Serial.print(topic); Serial.print("] "); - payload[length] = '\0'; - String newPayload = String((char *)payload); + memset(&charPayload,0,sizeof(charPayload)); + memcpy(charPayload, payload, min(sizeof(charPayload),length)); + charPayload[length] = '\0'; + String newPayload = String(charPayload); int intPayload = newPayload.toInt(); Serial.println(newPayload); Serial.println(); - newPayload.toCharArray(charPayload, newPayload.length() + 1); - - if (newTopic == USER_MQTT_CLIENT_NAME"/command") + newPayload.toCharArray(charPayload, newPayload.length() + 1); + + if (newTopic == USER_MQTT_CLIENT_NAME"/command") { - effect = newPayload; + //effect = newPayload; + if ( strcmp(charPayload, "off") == 0 ) + { + effect = eOff; + } else if ( strcmp(charPayload, "mqttRGB") == 0 ) + { + effect = eMqttRGB; + } client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload); } if (newTopic == USER_MQTT_CLIENT_NAME"/wakeAlarm") @@ -185,7 +197,7 @@ void callback(char* topic, byte* payload, unsigned int length) sunPhase = 0; fadeStep = 0; sunFadeStep = 0; - effect = "sunrise"; + effect = eSunrise; wakeDelay = intPayload*10; timer.setTimeout(wakeDelay, increaseSunPhase); timer.setTimeout(wakeDelay, increaseWhiteLevel); @@ -203,17 +215,20 @@ void callback(char* topic, byte* payload, unsigned int length) { client.publish(USER_MQTT_CLIENT_NAME "/colorState", charPayload); // get the position of the first and second commas - uint8_t firstIndex = newPayload.indexOf(','); - uint8_t lastIndex = newPayload.lastIndexOf(','); - - uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); - red = rgb_red; - - uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); - green = rgb_green; - - uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); - blue = rgb_blue; + int firstIndex = newPayload.indexOf(','); + int lastIndex = newPayload.lastIndexOf(','); + + if ( ( firstIndex > -1) && (lastIndex > -1) && (firstIndex != lastIndex) ) + { + uint8_t rgb_red = newPayload.substring(0, firstIndex).toInt(); + red = rgb_red; + + uint8_t rgb_green = newPayload.substring(firstIndex + 1, lastIndex).toInt(); + green = rgb_green; + + uint8_t rgb_blue = newPayload.substring(lastIndex + 1).toInt(); + blue = rgb_blue; + } } } @@ -356,20 +371,20 @@ void mqttRGB() void selectEffect() { - if(effect == "sunrise") - { - sunRise(); - digitalWrite(LED_BUILTIN, LED_ON); - } - if(effect == "mqttRGB") - { - mqttRGB(); - digitalWrite(LED_BUILTIN, LED_ON); - } - if(effect == "off") + switch(effect) { - off(); - digitalWrite(LED_BUILTIN, LED_OFF); + case eSunrise: + sunRise(); + digitalWrite(LED_BUILTIN, LED_ON); + break; + case eMqttRGB: + mqttRGB(); + digitalWrite(LED_BUILTIN, LED_ON); + break; + default: + off(); + digitalWrite(LED_BUILTIN, LED_OFF); + break; } } From e0bcd5258344ec51830c899d54ec8b2b6cfc56d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 19:47:11 -0400 Subject: [PATCH 19/24] Adding additional OTA code. --- Sunrise/Sunrise.ino | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 32ff7dc..98bb57f 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -401,8 +401,38 @@ void setup() client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); #ifdef ENABLE_OTA - ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); - ArduinoOTA.begin(); + ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME); + ArduinoOTA.onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) { + type = "sketch"; + } else { // U_SPIFFS + type = "filesystem"; + } + Serial.println("Start updating " + type); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) { + Serial.println("Auth Failed"); + } else if (error == OTA_BEGIN_ERROR) { + Serial.println("Begin Failed"); + } else if (error == OTA_CONNECT_ERROR) { + Serial.println("Connect Failed"); + } else if (error == OTA_RECEIVE_ERROR) { + Serial.println("Receive Failed"); + } else if (error == OTA_END_ERROR) { + Serial.println("End Failed"); + } + }); + + ArduinoOTA.begin(); #endif strip.setBrightness(BRIGHTNESS); strip.begin(); @@ -416,7 +446,7 @@ void loop() } client.loop(); #ifdef ENABLE_OTA - ArduinoOTA.handle(); + ArduinoOTA.handle(); #endif timer.run(); selectEffect(); From 995262b1571af1c830c24e02beb373691b6a417d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 13 Oct 2019 22:07:22 -0400 Subject: [PATCH 20/24] Swap out the Adafruit_Neopixel library with NeoPixelBus library --- Sunrise/Sunrise.ino | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 98bb57f..3d9496f 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -2,7 +2,7 @@ #include "config.h" /****************** LIBRARY SECTION *************************************/ -#include //https://github.com/adafruit/Adafruit_NeoPixel +#include //https://github.com/Makuna/NeoPixelBus #include //https://github.com/thehookup/Simple-Timer-Library #include //https://github.com/knolleary/pubsubclient #ifdef ESP32 @@ -48,7 +48,7 @@ enum Effects { eOff, eSunrise, eMqttRGB }; WiFiClient espClient; PubSubClient client(espClient); SimpleTimer timer; -Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRBW + NEO_KHZ800); +NeoPixelBus strip(NUM_LEDS, LED_PIN); /***************** GENERAL VARIABLES *************************************/ @@ -298,12 +298,12 @@ void drawSun() { int redValue = map(sunFadeStep, 0, 100, 127, 255); int whiteValue = map(sunFadeStep, 0, 100, 0, whiteLevel); - strip.setPixelColor(newSunLeft, redValue, 25,0,whiteValue); - strip.setPixelColor(newSunRight, redValue, 25,0,whiteValue); + strip.SetPixelColor(newSunLeft, RgbwColor(redValue, 25,0,whiteValue)); + strip.SetPixelColor(newSunRight, RgbwColor(redValue, 25,0,whiteValue)); } for(int i = sunStart; i < sunStart+currentSun; i++) { - strip.setPixelColor(i, 255, 64,0,whiteLevel); + strip.SetPixelColor(i, RgbwColor(255, 64,0,whiteLevel)); } oldSun = currentSun; } @@ -327,12 +327,12 @@ void drawAurora() { int redValue = map(fadeStep, 0, 100, whiteLevel, 127); int greenValue = map(fadeStep, 0, 100, 0, 25); - strip.setPixelColor(newAuroraRight, redValue, greenValue,0,0); - strip.setPixelColor(newAuroraLeft, redValue, greenValue,0,0); + strip.SetPixelColor(newAuroraRight, RgbwColor(redValue, greenValue,0,0)); + strip.SetPixelColor(newAuroraLeft, RgbwColor(redValue, greenValue,0,0)); } for(int i = sunStart; i < sunStart+currentAurora; i++) { - strip.setPixelColor(i, 127, 25,0,0); + strip.SetPixelColor(i, RgbwColor(127, 25,0,0)); } oldFadeStep = fadeStep; oldAurora = currentAurora; @@ -342,7 +342,7 @@ void drawAmbient() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, whiteLevel, 0,0,0); + strip.SetPixelColor(i, RgbwColor(whiteLevel,0,0,0)); } } @@ -357,7 +357,7 @@ void off() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, 0,0,0,0); + strip.SetPixelColor(i, RgbwColor(0,0,0,0)); } } @@ -365,7 +365,7 @@ void mqttRGB() { for(int i = 0; i < NUM_LEDS; i++) { - strip.setPixelColor(i, red,green,blue,white); + strip.SetPixelColor(i, RgbwColor(red,green,blue,white)); } } @@ -434,8 +434,10 @@ void setup() ArduinoOTA.begin(); #endif - strip.setBrightness(BRIGHTNESS); - strip.begin(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); } void loop() @@ -450,7 +452,7 @@ void loop() #endif timer.run(); selectEffect(); - strip.show(); + strip.Show(); #ifdef DEBUG if ( millis() - debugTime > 5000 ) { From d556762d6f7a9a641276b38665ddf3459199d263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Wed, 16 Oct 2019 06:43:22 -0400 Subject: [PATCH 21/24] MQTT tweaks, adding last will and making the state retain. --- Sunrise/Sunrise.ino | 6 ++++-- Sunrise/config_template.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 3d9496f..9c7d625 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -40,6 +40,7 @@ const int mqtt_port = USER_MQTT_PORT ; const char *mqtt_user = USER_MQTT_USERNAME ; const char *mqtt_pass = USER_MQTT_PASSWORD ; const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; +const char *mqtt_lwt_topic = LWTTOPIC ; /***************** ENUMS ****************************************/ enum Effects { eOff, eSunrise, eMqttRGB }; @@ -121,9 +122,10 @@ void reconnect() { Serial.print("Attempting MQTT connection..."); // Attempt to connect - if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) + if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass, mqtt_lwt_topic, 0, true, "Offline")) { Serial.println("connected"); + client.publish(mqtt_lwt_topic, "Online", true); // Once connected, publish an announcement... if(boot == true) { @@ -189,7 +191,7 @@ void callback(char* topic, byte* payload, unsigned int length) { effect = eMqttRGB; } - client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload); + client.publish(USER_MQTT_CLIENT_NAME"/state", charPayload, true); } if (newTopic == USER_MQTT_CLIENT_NAME"/wakeAlarm") { diff --git a/Sunrise/config_template.h b/Sunrise/config_template.h index 60308de..729b5a8 100644 --- a/Sunrise/config_template.h +++ b/Sunrise/config_template.h @@ -10,6 +10,8 @@ #define USER_MQTT_USERNAME "YOUR_MQTT_LOGIN" #define USER_MQTT_PASSWORD "YOUR_MQTT_PASSWORD" #define USER_MQTT_CLIENT_NAME "SunriseMCU" //used to define MQTT topics, MQTT Client ID, and ArduinoOTA +#define LWTTOPIC "LWT/" USER_MQTT_CLIENT_NAME + #if defined(ESP32) #define LED_PIN 23 //pin where the led strip is hooked up #else From ec0a41dca5e3e93cfa85414eb154cba227b0c51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20B=C3=A1cskay?= Date: Sun, 20 Oct 2019 12:07:00 -0400 Subject: [PATCH 22/24] Add availability to the example --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2e62dcc..f69419b 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ light: rgb_state_topic: "SunriseMCU/colorState" white_value_command_topic: "SunriseMCU/white" white_value_state_topic: "SunriseMCU/whiteState" + availability_topic: "LWT/SunriseMCU" + payload_available: "Online" + payload_not_available: "Offline" white_value_scale: 255 retain: true ``` From 0559f7bbd9aa73de40aba3be7154851f3ace4477 Mon Sep 17 00:00:00 2001 From: Balazs Bacskay Date: Mon, 4 May 2020 00:31:42 -0400 Subject: [PATCH 23/24] PlatformIO initial configuration --- .gitignore | 6 +++- .travis.yml | 67 +++++++++++++++++++++++++++++++++++++++++ .vscode/extensions.json | 7 +++++ README.md | 19 ++++++++++++ Sunrise/Sunrise.ino | 3 +- include/README | 39 ++++++++++++++++++++++++ platformio.ini | 53 ++++++++++++++++++++++++++++++++ test/README | 11 +++++++ 8 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 .travis.yml create mode 100644 .vscode/extensions.json create mode 100644 include/README create mode 100644 platformio.ini create mode 100644 test/README diff --git a/.gitignore b/.gitignore index a1e74d1..fb8649c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ -.vscode/ +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch build/ Sunrise/config.h +.pio diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7c486f1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..0f0d740 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/README.md b/README.md index f69419b..5129651 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,22 @@ light: retain: true ``` +## How to build with PlatformIO + +1. Install PlatformIO Core +2. Clone the repo with git or download the sources as .zip and extract it +3. Change into the folder where the platformio.ini is +4. Run these commands: +```shell + # Download/Install project libraries + > platformio lib install + + # Build project + > platformio run + + # Upload firmware + > platformio run --target upload + + # Clean build files + > platformio run --target clean + diff --git a/Sunrise/Sunrise.ino b/Sunrise/Sunrise.ino index 68d2b71..8ed0ad8 100644 --- a/Sunrise/Sunrise.ino +++ b/Sunrise/Sunrise.ino @@ -2,6 +2,7 @@ #include "config.h" /****************** LIBRARY SECTION *************************************/ +#include #include //https://github.com/Makuna/NeoPixelBus #include //https://github.com/thehookup/Simple-Timer-Library #include //https://github.com/knolleary/pubsubclient @@ -172,7 +173,7 @@ void callback(char* topic, byte* payload, unsigned int length) Serial.print(topic); Serial.print("] "); memset(&charPayload,0,sizeof(charPayload)); - memcpy(charPayload, payload, min(sizeof(charPayload),length)); + memcpy(charPayload, payload, min(sizeof(charPayload),(unsigned long)length)); charPayload[length] = '\0'; String newPayload = String(charPayload); int intPayload = newPayload.toInt(); diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..9a505a5 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,53 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +description = MQTT RGBW Sunrise animation with brightness and color control via MQTT +default_envs = esp32doit-devkit-v1, nodemcuv2 +src_dir = Sunrise + + +;Global environment setting +[env] +framework = arduino +monitor_speed = 115200 +lib_ldf_mode = chain+ +lib_deps = + NeoPixelBus@~2.5.7 + PubSubClient@~2.7 + https://github.com/thehookup/Simple-Timer-Library.git +build_flags = + -D MQTT_MAX_PACKET_SIZE=160 + +;[env-esp8266] +;lib_deps = +; ESP8266WiFi +; ESP8266mDNS + +;[env-esp32] +;lib_deps = +; WiFi +; ESPmDNS + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 +build_flags = ${env.build_flags} +lib_deps = +; ${env-esp8266.lib_deps} + ${env.lib_deps} + +[env:esp32doit-devkit-v1] +board = esp32doit-devkit-v1 +platform = espressif32 +build_flags = ${env.build_flags} +lib_deps = +; ${env-esp32.lib_deps} + ${env.lib_deps} diff --git a/test/README b/test/README new file mode 100644 index 0000000..df5066e --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html From 761293c46cf76f5025f6341e65d95b19d582cc58 Mon Sep 17 00:00:00 2001 From: Balazs Bacskay Date: Mon, 4 May 2020 00:44:11 -0400 Subject: [PATCH 24/24] Update readme with target dependent firmware upload --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5129651..64f851c 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,15 @@ light: ```shell # Download/Install project libraries > platformio lib install - + # Build project > platformio run - # Upload firmware - > platformio run --target upload + # Upload firmware to NodeMCU 1.0 + > platformio run -e nodemcuv2 --target upload + + # Upload firmware to DOIT ESP32 DEVKIT V1 + > platformio run -e esp32doit-devkit-v1 --target upload # Clean build files > platformio run --target clean