Created
April 27, 2017 14:48
-
-
Save darookee/339943181cf7bddce76b945b3e279da9 to your computer and use it in GitHub Desktop.
Arduino-Code for cheap ESP8266 based WiFi RGB-Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ESP8266WiFi.h> | |
#include <DNSServer.h> //Local DNS Server used for redirecting all requests to the configuration portal | |
#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal | |
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic | |
#include <ESP8266mDNS.h> | |
#include <WiFiUdp.h> | |
#include <ArduinoOTA.h> | |
#include <EEPROM.h> | |
#include <PubSubClient.h> // https://github.com/Imroy/pubsubclient | |
#include <LEDFader.h> | |
#include "tempcolor.h" | |
// RGB Pins | |
#define redPIN 15 // 13 | |
#define greenPIN 13 // 12 | |
#define bluePIN 12 // 15 | |
// W Pins | |
#define w1PIN 14 | |
#define w2PIN 4 | |
// onbaord green LED D1 | |
#define LEDPIN 5 | |
// onbaord red LED D2 | |
#define LED2PIN 1 | |
// note | |
// TX GPIO2 @Serial1 (Serial ONE) | |
// RX GPIO3 @Serial | |
#define LEDoff digitalWrite(LEDPIN,HIGH) | |
#define LEDon digitalWrite(LEDPIN,LOW) | |
#define LED2off digitalWrite(LED2PIN,HIGH) | |
#define LED2on digitalWrite(LED2PIN,LOW) | |
#define fadeTime 2250 | |
#define fadeTimeWhite 1125 | |
char* mqttServer = "192.168.254.254"; | |
char *myName = "MyRGB"; | |
bool shouldSave = false; | |
long lastWiFiReconnectAttempt = 0; | |
long lastMqttReconnectAttempt = 0; | |
LEDFader leds[5] = { | |
LEDFader(redPIN), | |
LEDFader(greenPIN), | |
LEDFader(bluePIN), | |
LEDFader(w1PIN), | |
LEDFader(w2PIN) | |
}; | |
#define red 0 | |
#define green 1 | |
#define blue 2 | |
#define w1 3 | |
#define w2 4 | |
bool rgbState = false; | |
bool w1State = false; | |
bool w2State = false; | |
int myRed = 255; | |
int myGreen = 95; | |
int myBlue = 15; | |
int myRGBBrightness = 255; | |
int myRGBColorTemp = 290; | |
int myW1Brightness = 255; | |
int myW2Brightness = 255; | |
char msgBuffer[255]; | |
WiFiClient espClient; | |
PubSubClient client(espClient); | |
int kelvinMired(int tValue) { | |
return 1000000/tValue; | |
} | |
void publishMyRgbStates() { | |
char myCurrentColors[11]; | |
char myCurrentBrightness[3]; | |
char myCurrentMired[4]; | |
char buf[150]; | |
sprintf(myCurrentColors, "%d,%d,%d", myRed, myGreen, myBlue); | |
sprintf(myCurrentBrightness, "%d", myRGBBrightness); | |
sprintf(myCurrentMired, "%d", myRGBColorTemp); | |
sprintf(buf, "home/light/strips/%s/%s/state/switch", myName, "rgb"); | |
client.publish(buf, (rgbState?"on":"off"), true); | |
sprintf(buf, "home/light/strips/%s/%s/state/color", myName, "rgb"); | |
client.publish(buf, myCurrentColors, true); | |
sprintf(buf, "home/light/strips/%s/%s/state/brightness", myName, "rgb"); | |
client.publish(buf, myCurrentBrightness, true); | |
sprintf(buf, "home/light/strips/%s/%s/state/colortemp", myName, "rgb"); | |
client.publish(buf, myCurrentMired, true); | |
} | |
void publishMyWhiteStates() { | |
char myCurrentW1Brightness[3]; | |
char myCurrentW2Brightness[3]; | |
char buf[150]; | |
sprintf(myCurrentW1Brightness, "%d", myW1Brightness); | |
sprintf(myCurrentW2Brightness, "%d", myW2Brightness); | |
sprintf(buf, "home/light/strips/%s/%s/state/switch", myName, "w1"); | |
client.publish(buf, (w1State?"on":"off")); | |
sprintf(buf, "home/light/strips/%s/%s/state/switch", myName, "w2"); | |
client.publish(buf, (w2State?"on":"off")); | |
sprintf(buf, "home/light/strips/%s/%s/state/brightness", myName, "w1"); | |
client.publish(buf, myCurrentW1Brightness); | |
sprintf(buf, "home/light/strips/%s/%s/state/brightness", myName, "w2"); | |
client.publish(buf, myCurrentW2Brightness); | |
} | |
void publishMyStates() { | |
publishMyRgbStates(); | |
publishMyWhiteStates(); | |
} | |
void setR(int value) { | |
leds[red].fade(value, fadeTime); | |
} | |
void setG(int value) { | |
leds[green].fade(value, fadeTime); | |
} | |
void setB(int value) { | |
leds[blue].fade(value, fadeTime); | |
} | |
void setW1(int value) { | |
leds[w1].fade(value, fadeTimeWhite); | |
} | |
void setW2(int value) { | |
leds[w2].fade(value, fadeTimeWhite); | |
} | |
void turnOffRGB() { | |
setR(0); | |
setG(0); | |
setB(0); | |
rgbState = false; | |
} | |
void turnOnRGB() { | |
int cRed = map(myRed, 0, 255, 0, myRGBBrightness); | |
int cGreen = map(myGreen, 0, 255, 0, myRGBBrightness); | |
int cBlue = map(myBlue, 0, 255, 0, myRGBBrightness); | |
setR(cRed); | |
setG(cGreen); | |
setB(cBlue); | |
rgbState = true; | |
} | |
void turnOnW1() { | |
setW1(myW1Brightness); | |
w1State = true; | |
} | |
void turnOffW1() { | |
setW1(0); | |
w1State = false; | |
} | |
void turnOnW2() { | |
setW2(myW2Brightness); | |
w1State = true; | |
} | |
void turnOffW2() { | |
setW2(0); | |
w1State = false; | |
} | |
/** | |
* splitColor() - Receive a uint32_t value, and spread into bits. | |
*/ | |
uint8_t splitColor ( uint32_t c, char value ) { | |
switch ( value ) { | |
case 'r': return (uint8_t)(c >> 16); | |
case 'g': return (uint8_t)(c >> 8); | |
case 'b': return (uint8_t)(c >> 0); | |
default: return 0; | |
} | |
} | |
void setColorTempFromMired(int mired) { | |
// calculations are done from kelvin | |
int k = kelvinMired(mired); | |
// store as mired for HA | |
myRGBColorTemp = mired; | |
uint32_t colorCode = temp.color(k, 255); | |
myRed = splitColor(colorCode, 'r'); | |
myGreen = splitColor(colorCode, 'g'); | |
myBlue = splitColor(colorCode, 'b'); | |
} | |
void mqttCallback(char* ctopic, byte* bpayload, unsigned int length) { | |
String topic = String(ctopic); | |
int i = 0; | |
for(i=0; i<length; i++) { | |
msgBuffer[i] = bpayload[i]; | |
} | |
msgBuffer[i] = '\0'; | |
String payload = String(msgBuffer); | |
Serial1.print(topic); | |
Serial1.print(" => "); | |
Serial1.println(payload); | |
if(topic.endsWith("/rgb/command/color")) { | |
int c1 = payload.indexOf(','); | |
int c2 = payload.indexOf(',',c1+1); | |
myRed = constrain(payload.toInt(), 0, 255); | |
myGreen = constrain(payload.substring(c1+1,c2).toInt(), 0, 255); | |
myBlue = constrain(payload.substring(c2+1).toInt(), 0, 255); | |
if (rgbState) { | |
turnOnRGB(); | |
} | |
} | |
if(topic.endsWith("/rgb/command/switch")) { | |
if (payload == "off") { | |
turnOffRGB(); | |
} else { | |
turnOnRGB(); | |
} | |
} | |
if(topic.endsWith("/rgb/command/brightness")) { | |
myRGBBrightness = constrain(payload.toInt(), 0, 255); | |
if (rgbState) { | |
turnOnRGB(); | |
} | |
} | |
if(topic.endsWith("/rgb/command/colortemp")) { | |
int mired = constrain(payload.toInt(), 153, 500); | |
setColorTempFromMired(mired); | |
if (rgbState) { | |
turnOnRGB(); | |
} | |
} | |
if(topic.endsWith("/w1/command/switch")) { | |
if (payload == "off") { | |
turnOffW1(); | |
} else { | |
turnOnW1(); | |
} | |
} | |
if(topic.endsWith("/w1/command/brightness")) { | |
myW1Brightness = constrain(payload.toInt(), 0, 255); | |
if (w1State) { | |
turnOnW1(); | |
} | |
} | |
if(topic.endsWith("/w2/command/switch")) { | |
if (payload == "off") { | |
turnOffW2(); | |
} else { | |
turnOnW2(); | |
} | |
} | |
if(topic.endsWith("/w2/command/brightness")) { | |
myW2Brightness = constrain(payload.toInt(), 0, 255); | |
if (w2State) { | |
turnOnW2(); | |
} | |
} | |
publishMyStates(); | |
} | |
void saveConfigCallback () { | |
shouldSave = true; | |
} | |
void saveConfig() { | |
String myNameStr = String(myName); | |
String mqttServerStr = String(mqttServer); | |
String okStr = "OK"; | |
EEPROM.begin(512); | |
for (int i = 0; i < 96; ++i) { EEPROM.write(i, 0); } | |
for (int i = 0; i < 32; ++i) { | |
EEPROM.write(i, myNameStr[i]); | |
} | |
for (int i = 0; i < 32; ++i) { | |
EEPROM.write(32+i, mqttServerStr[i]); | |
} | |
for (int i = 0; i < 2; ++i) { | |
EEPROM.write(64+i, okStr[i]); | |
} | |
EEPROM.commit(); | |
} | |
void loadConfig() { | |
String myNameStr; | |
String mqttServerStr; | |
String okReadStr; | |
String okStr = "OK"; | |
EEPROM.begin(512); | |
for (int i = 0; i < 32; ++i) { | |
myNameStr += char(EEPROM.read(i)); | |
} | |
for (int i = 32; i < 64; ++i) { | |
mqttServerStr += char(EEPROM.read(i)); | |
} | |
for (int i = 64; i < 66; ++i) { | |
okReadStr += char(EEPROM.read(i)); | |
} | |
Serial1.println(okReadStr); | |
if (okStr == okReadStr) { | |
strcpy(myName, myNameStr.c_str()); | |
strcpy(mqttServer, mqttServerStr.c_str()); | |
} else { | |
Serial1.println(F("Could not read from EEPROM!")); | |
} | |
} | |
void setup() | |
{ | |
pinMode(LEDPIN, OUTPUT); | |
pinMode(LED2PIN, OUTPUT); | |
pinMode(redPIN, OUTPUT); | |
pinMode(greenPIN, OUTPUT); | |
pinMode(bluePIN, OUTPUT); | |
pinMode(w1PIN, OUTPUT); | |
pinMode(w2PIN, OUTPUT); | |
turnOffRGB(); | |
turnOffW1(); | |
turnOffW2(); | |
LEDon; | |
LED2on; | |
// Setup console | |
Serial1.begin(115200); | |
delay(10); | |
loadConfig(); | |
Serial1.println(F("Started.")); | |
WiFiManagerParameter mqtt_server_parameter("server", "MQTT Server", mqttServer, 40); | |
WiFiManagerParameter myname_parameter("myname", "RGB Name", myName, 20); | |
WiFiManager wifiManager; | |
wifiManager.resetSettings(); | |
wifiManager.addParameter(&mqtt_server_parameter); | |
wifiManager.addParameter(&myname_parameter); | |
wifiManager.setSaveConfigCallback(saveConfigCallback); | |
if (!wifiManager.autoConnect()) { | |
Serial1.println(F("Failed to connect and hit timeout.")); | |
delay(3000); | |
//reset and try again, or maybe put it to deep sleep | |
ESP.reset(); | |
delay(5000); | |
} | |
LEDoff; | |
strcpy(mqttServer, mqtt_server_parameter.getValue()); | |
strcpy(myName, myname_parameter.getValue()); | |
client.setServer(mqttServer, 1883); | |
client.setCallback(mqttCallback); | |
Serial1.println(mqttServer); | |
setColorTempFromMired(myRGBColorTemp); | |
if (shouldSave) { | |
Serial1.println("Saving"); | |
saveConfig(); | |
} | |
ArduinoOTA.begin(); | |
} | |
boolean reconnectWiFi() { | |
while (WiFi.status() != WL_CONNECTED) { | |
LEDoff; | |
delay(500); | |
Serial1.print("."); | |
LEDon; | |
} | |
Serial1.println("WiFi connected"); | |
Serial1.print("IP address: "); | |
Serial1.println(WiFi.localIP()); | |
} | |
boolean reconnectMqtt() { | |
char buf[60]; | |
LED2on; | |
sprintf(buf, "home/light/strips/%s/rgb/state/switch", myName); | |
if (client.connect(myName, buf, 0, false, "off")) { | |
sprintf(buf, "home/light/strips/%s/+/command/#", myName); | |
// subscribe for commands | |
client.subscribe(buf); | |
Serial1.println("MQTT connected"); | |
publishMyStates(); | |
} | |
return client.connected(); | |
} | |
void loop() { | |
/* | |
if (WiFi.status() != WL_CONNECTED) { | |
unsigned long now = millis(); | |
if (now - lastWiFiReconnectAttempt > 5000) { | |
lastWiFiReconnectAttempt = now; | |
Serial1.println("Reconnecting WiFi..."); | |
if (reconnectWiFi()) { | |
lastWiFiReconnectAttempt = 0; | |
} | |
} | |
return; | |
} | |
*/ | |
ArduinoOTA.handle(); | |
if (!client.connected()) { | |
long now = millis(); | |
if (now - lastMqttReconnectAttempt > 5000) { | |
lastMqttReconnectAttempt = now; | |
Serial1.println(F("Reconnecting MQTT...")); | |
// Attempt to reconnect | |
if (reconnectMqtt()) { | |
LED2off; | |
lastMqttReconnectAttempt = 0; | |
} | |
} | |
return; | |
} | |
// Client connected | |
client.loop(); | |
for (byte i = 0; i < 5; i++) { | |
LEDFader *led = &leds[i]; | |
led->update(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment