Skip to content

Commit

Permalink
Proper support for transitions. Needs some cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
corbanmailloux committed Aug 1, 2016
1 parent 930d696 commit 23b77fe
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 54 deletions.
3 changes: 3 additions & 0 deletions mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ def turn_off(self, **kwargs):
"""Turn the device off."""
message = {"state": "OFF"}

if ATTR_TRANSITION in kwargs:
message["transition"] = int(kwargs[ATTR_TRANSITION])

mqtt.publish(self._hass, self._topic["command_topic"],
json.dumps(message), self._qos, self._retain)

Expand Down
268 changes: 214 additions & 54 deletions mqtt_esp8266_rgb.ino
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,31 @@ const char* off_cmd = "OFF";

const int BUFFER_SIZE = JSON_OBJECT_SIZE(8);


// Maintained state for reporting to HA
byte red = 255;
byte green = 255;
byte blue = 255;

byte brightness = 255;

// Real values to write to the LEDs (ex. including brightness and state)
byte realRed = 0;
byte realGreen = 0;
byte realBlue = 0;

bool state_on = false;

// Globals for fade/transitions
bool startFade = false;
long lastLoop = 0;
int wait = 0;
bool inFade = false;
int loopCount = 0;
int stepR, stepG, stepB;
int prevR, prevG, prevB;
int redVal, grnVal, bluVal;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup() {
pinMode(redPin, OUTPUT);
Expand Down Expand Up @@ -75,6 +86,19 @@ void setup_wifi() {
Serial.println(WiFi.localIP());
}

/*
SAMPLE PAYLOAD:
{
"brightness": 120,
"color": {
"r": 255,
"g": 100,
"b": 100
},
"transition": 5,
"state": "ON"
}
*/
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Expand All @@ -91,36 +115,19 @@ void callback(char* topic, byte* payload, unsigned int length) {
return;
}

byte redOut;
byte greenOut;
byte blueOut;
if (state_on) {
// Update lights
redOut = map(red, 0, 255, 0, brightness);
greenOut = map(green, 0, 255, 0, brightness);
blueOut = map(blue, 0, 255, 0, brightness);

// redOut = map(red, 0, 255, brightness, 0);
// greenOut = map(green, 0, 255, brightness, 0);
// blueOut = map(blue, 0, 255, brightness, 0);
realRed = map(red, 0, 255, 0, brightness);
realGreen = map(green, 0, 255, 0, brightness);
realBlue = map(blue, 0, 255, 0, brightness);
}
else {
redOut = 0;
greenOut = 0;
blueOut = 0;
realRed = 0;
realGreen = 0;
realBlue = 0;
}

analogWrite(redPin, redOut);
analogWrite(greenPin, greenOut);
analogWrite(bluePin, blueOut);

Serial.println("Setting LEDs:");
Serial.print("r: ");
Serial.print(redOut);
Serial.print(", g: ");
Serial.print(greenOut);
Serial.print(", b: ");
Serial.println(blueOut);
startFade = true;

sendState();
}
Expand All @@ -135,20 +142,6 @@ bool processJson(char* message) {
return false;
}

/*
SAMPLE PAYLOAD:
{
"brightness": 120,
"color": {
"r": 255,
"g": 100,
"b": 100
},
"transition": 5,
"state": "ON"
}
*/

if (root.containsKey("state")) {
if (strcmp(root["state"], on_cmd) == 0) {
state_on = true;
Expand All @@ -169,7 +162,10 @@ bool processJson(char* message) {
}

if (root.containsKey("transition")) {
// TODO
wait = root["transition"];
}
else {
wait = 0;
}

return true;
Expand Down Expand Up @@ -211,20 +207,184 @@ void reconnect() {
}
}
}

void setColor(int inR, int inG, int inB) {
analogWrite(redPin, inR);
analogWrite(greenPin, inG);
analogWrite(bluePin, inB);

Serial.println("Setting LEDs:");
Serial.print("r: ");
Serial.print(inR);
Serial.print(", g: ");
Serial.print(inG);
Serial.print(", b: ");
Serial.println(inB);
}

void loop() {

if (!client.connected()) {
reconnect();
}
client.loop();

// long now = millis();
// if (now - lastMsg > 2000) {
// lastMsg = now;
// ++value;
// snprintf (msg, 75, "hello world #%ld", value);
// Serial.print("Publish message: ");
// Serial.println(msg);
// client.publish("outTopic", msg);
// }

if (startFade) {
// If we don't want to fade, skip it.
if (wait == 0) {
setColor(realRed, realGreen, realBlue);
prevR = realRed;
prevG = realGreen;
prevB = realBlue;

redVal = realRed;
grnVal = realGreen;
bluVal = realBlue;

startFade = false;
}
else {
loopCount = 0;
stepR = calculateStep(prevR, realRed);
stepG = calculateStep(prevG, realGreen);
stepB = calculateStep(prevB, realBlue);

inFade = true;
}
}

if (inFade) {
startFade = false;
long now = millis();
if (now - lastLoop > wait) {
if (loopCount <= 1020) {
lastLoop = now;

redVal = calculateVal(stepR, redVal, loopCount);
grnVal = calculateVal(stepG, grnVal, loopCount);
bluVal = calculateVal(stepB, bluVal, loopCount);

setColor(redVal, grnVal, bluVal); // Write current values to LED pins

Serial.print("Loop count: ");
Serial.println(loopCount);
loopCount++;
}
else {
// Update current values for next loop
prevR = redVal;
prevG = grnVal;
prevB = bluVal;

inFade = false;
}
}
}
}

// From https://www.arduino.cc/en/Tutorial/ColorCrossfader
/* BELOW THIS LINE IS THE MATH -- YOU SHOULDN'T NEED TO CHANGE THIS FOR THE BASICS
*
* The program works like this:
* Imagine a crossfade that moves the red LED from 0-10,
* the green from 0-5, and the blue from 10 to 7, in
* ten steps.
* We'd want to count the 10 steps and increase or
* decrease color values in evenly stepped increments.
* Imagine a + indicates raising a value by 1, and a -
* equals lowering it. Our 10 step fade would look like:
*
* 1 2 3 4 5 6 7 8 9 10
* R + + + + + + + + + +
* G + + + + +
* B - - -
*
* The red rises from 0 to 10 in ten steps, the green from
* 0-5 in 5 steps, and the blue falls from 10 to 7 in three steps.
*
* In the real program, the color percentages are converted to
* 0-255 values, and there are 1020 steps (255*4).
*
* To figure out how big a step there should be between one up- or
* down-tick of one of the LED values, we call calculateStep(),
* which calculates the absolute gap between the start and end values,
* and then divides that gap by 1020 to determine the size of the step
* between adjustments in the value.
*/
int calculateStep(int prevValue, int endValue) {
int step = endValue - prevValue; // What's the overall gap?
if (step) { // If its non-zero,
step = 1020/step; // divide by 1020
}

return step;
}

/* The next function is calculateVal. When the loop value, i,
* reaches the step size appropriate for one of the
* colors, it increases or decreases the value of that color by 1.
* (R, G, and B are each calculated separately.)
*/
int calculateVal(int step, int val, int i) {
if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
if (step > 0) { // increment the value if step is positive...
val += 1;
}
else if (step < 0) { // ...or decrement it if step is negative
val -= 1;
}
}

// Defensive driving: make sure val stays in the range 0-255
if (val > 255) {
val = 255;
}
else if (val < 0) {
val = 0;
}

return val;
}

/* crossFade() converts the percentage colors to a
* 0-255 range, then loops 1020 times, checking to see if
* the value needs to be updated each time, then writing
* the color values to the correct pins.
*/
// void crossFade(int color[3], int wait) {
// // Convert to 0-255
// // int R = (color[0] * 255) / 100;
// // int G = (color[1] * 255) / 100;
// // int B = (color[2] * 255) / 100;

// int R = color[0];
// int G = color[1];
// int B = color[2];

// // Spark.publish("crossFade", String(R) + "," + String(G) + "," + String(B));

// int stepR = calculateStep(prevR, R);
// int stepG = calculateStep(prevG, G);
// int stepB = calculateStep(prevB, B);

// for (int i = 0; i <= 1020; i++) {
// if (interruptFade) {
// break;
// }

// redVal = calculateVal(stepR, redVal, i);
// grnVal = calculateVal(stepG, grnVal, i);
// bluVal = calculateVal(stepB, bluVal, i);

// setColor(redVal, grnVal, bluVal); // Write current values to LED pins

// delay(wait); // Pause for 'wait' milliseconds before resuming the loop
// }

// // Update current values for next loop
// prevR = redVal;
// prevG = grnVal;
// prevB = bluVal;
// delay(hold); // Pause for optional 'wait' milliseconds before resuming the loop
// }

0 comments on commit 23b77fe

Please sign in to comment.