diff --git a/ESP8266-RGB-MQTT/ESP8266-RGB-MQTT.ino b/ESP8266-RGB-MQTT/ESP8266-RGB-MQTT.ino index f078df1..6b0a286 100644 --- a/ESP8266-RGB-MQTT/ESP8266-RGB-MQTT.ino +++ b/ESP8266-RGB-MQTT/ESP8266-RGB-MQTT.ino @@ -24,7 +24,7 @@ /********************************************************************** * ESP8266-RGB-MQTT - * + * * Links the ESP8266 based RGB led strip to an mqtt broker. * The program uses multiple topics for incoming and outgoing messages. * Incoming topics: @@ -45,12 +45,36 @@ WiFiClient espClient; PubSubClient client(espClient); // RGB strip pin configuration -const short redPin = 14; -const short greenPin = 16; -const short bluePin = 12; +const unsigned char pin[3] = {14,16,12}; +// Color values for the pwm outputs +unsigned char rgbColor[3]; +// Scaling factors for color calibration +const float calibration[3] = {1.0, 1.0, 0.7}; +// Flagss to determine if all necessary information +// has been gathered from mqtt broker +unsigned char isColorSet = 0; +unsigned char isCycleSet = 0; +unsigned char isBreatheSet = 0; +unsigned char isPowerSet = 0; + +// Scaling factors for different color adjustments +unsigned char powerFactor = 0; +unsigned char doColorCycle = 0; +unsigned char doBreathe = 0; +float breathScale = 0.999; +float breathAdjustment = -0.001; + +// Global scaling for pwm, due to pwm scale 0..1023 +const float globalScale = 3.0; + +// Pointer to the current decreasing color +unsigned char decColor = 0; + +// Timestamp for last color update +unsigned long lastColorUpdate = 0; /* * Initial setup for arduino */ @@ -58,7 +82,7 @@ void setup() { // Configure serial port Serial.begin(115200); delay(10); - + // Prepare WiFi connection setup_wifi(); @@ -73,7 +97,7 @@ void setup() { void setup_wifi() { // Connect to the WiFi as a client WiFi.mode(WIFI_STA); - + // Do the connection Serial.println(); Serial.print("Connecting to "); @@ -85,7 +109,7 @@ void setup_wifi() { } Serial.println(""); Serial.println("WiFi connected"); - + // Print IP address to serial Serial.print("My IP address: "); Serial.println(WiFi.localIP()); @@ -104,18 +128,93 @@ void incoming_mqtt(char* topic, byte* payload, unsigned int length) { Serial.println(); if (strcmp(topic, mqtt_topic_power) == 0) { - + isPowerSet = 1; + if (length == 1) { + Serial.println("Setting power factor"); + if ((char)payload[0] == '1') { + powerFactor = 1; + } else { + powerFactor = 0; + } + } } if (strcmp(topic, mqtt_topic_color) == 0) { + isColorSet = 1; + if (length == 7 && (char)payload[0] == '#') { + Serial.println("Setting color"); + // Parse hex input to color values + unsigned char i = 0; + unsigned char colorValue; + while (i < 6) { + // Reset parsing container at start of color + if (i % 2 == 0) { + colorValue = 0; + } + // Grab current char + char data = (char) payload[i+1]; + char value = 0; + if (data >= '0' && data <= '9') { + value = data - '0'; + } + if (data >= 'A' && data <= 'F') { + value = data - 'A'; + value += 10; + } + if (data >= 'a' && data <= 'f') { + value = data; + value += 10; + } + if (i % 2 == 0) { + // First hex digit, shift value to the left + value = value << 4; + } + // Add parsed value to accumulator + colorValue += value; + + if (i % 2 == 1) { + // Write colorValue to rgbValue + rgbColor[i/2] = colorValue; + } + i += 1; + } + } } if (strcmp(topic, mqtt_topic_cycle) == 0) { - + isCycleSet = 1; + if (length == 1) { + Serial.println("Setting color cycling"); + if ((char)payload[0] == '1') { + if (!doColorCycle) { + doColorCycle = 1; + // Reset decreasing color + decColor = 0; + } + } else { + if (doColorCycle) { + doColorCycle = 0; + } + } + } } if (strcmp(topic, mqtt_topic_breathe) == 0) { - + isBreatheSet = 1; + if (length == 1) { + Serial.println("Setting color breathing"); + if ((char)payload[0] == '1') { + if (!doBreathe) { + doBreathe = 1; + breathScale = 0.999; + breathAdjustment = -0.001; + } + } else { + if (doBreathe) { + doBreathe = 0; + breathScale = 1.0; + } + } + } } - } /* @@ -145,8 +244,47 @@ void reconnect() { } } -void updateColor() { - +void updateLight() { + if (doColorCycle) { + updateColorCycling(); + } + if (doBreathe) { + updateBreathing(); + } + setColor(); +} + +void updateColorCycling() { + if (rgbColor[0] == 0 && rgbColor[1] == 0 && rgbColor[2] == 0) { + rgbColor[0] = 255; + decColor = 0; + } + + unsigned char incColor = (decColor + 1) % 3; + if (rgbColor[decColor] > 0) { + rgbColor[decColor] -= 1; + } + if (rgbColor[incColor] < 255) { + rgbColor[incColor] += 1; + } + + if (rgbColor[incColor] == 255 && rgbColor[decColor] == 0) { + decColor = incColor; + } +} + +void updateBreathing() { + breathScale += breathAdjustment; + + if (breathScale <= 0.001 || breathScale >= 0.999) { + breathAdjustment = 0 - breathAdjustment; + } +} + +void setColor() { + for (int i = 0; i < 3; ++i) { + analogWrite(pin[i], rgbColor[i] * powerFactor * globalScale * breathScale * calibration[i]); + } } void loop() { @@ -155,5 +293,11 @@ void loop() { } client.loop(); - updateColor(); + if (isPowerSet & isColorSet & isCycleSet & isBreatheSet) { + unsigned long now = millis(); + if (now - lastColorUpdate > 30) { + lastColorUpdate = now; + updateLight(); + } + } }