Skip to content

Instantly share code, notes, and snippets.

@darookee
Created April 27, 2017 14:48
Show Gist options
  • Save darookee/339943181cf7bddce76b945b3e279da9 to your computer and use it in GitHub Desktop.
Save darookee/339943181cf7bddce76b945b3e279da9 to your computer and use it in GitHub Desktop.
Arduino-Code for cheap ESP8266 based WiFi RGB-Controller
#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