I have a program that receives 4 commands on 4 channels to change the color of an LED using mqtt communication. Lets just focus on two of the channels, the time and the red.
I am sending a length of time that I would like to complete the color change by, and a new color value.
I have ran my test runs to calculate the amount of time it seems to take to update a single value. I calculate this by setting the intervalRed value to 0.01 with a duty cycle of 1024, commanding the led to go from its starting value to its ending value of fully on, by the interval value would be 10,240 ticks. when I send that command, take the resulting execution time ( 287ms ) and calculate the time to update a single tick I get a value of 0.028027 ms to complete a single increment. When I set the hardcoded tickTime to that value: 0.028027 and I send a color change from off to on/vice-versa with a requested completion time of 1000ms, the actual execution time varies.
the larger the requested execution time varies, causes a greater difference between the actual and requested time.
I ran many test trials with a set interval to gain a value for the length of time for a single tick but no matter when value I use, there are still discrepancies. I dont believe using a hardcoded value for the length of time for a single tick is the correct way to assure the color change will occur over a given time.
I am happy to provide the terminal output for any attempts to show the output of values used in my calculations if needed (But I believe I need a difference approach all together)
What is the best way to assure the color change completes in the requested amount of time? Perhaps some calculation based on the amount of time passed rather then calculating a hardcoded value for the time of a single tick?
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define CLIENT_NAME "ESP8266_1" // just a name to identify this client
WiFiClient wifiClient;
PubSubClient mqttClient("10.0.0.131", 1883, wifiClient);
//set rgb led pins
int pinGreen = 4;
int pinBlue = 12;
int pinRed = 14;
float currentRed = 1024;
float currentGreen = 1024;
float currentBlue = 1024;
int nextRed = -1;
int nextGreen = -1;
int nextBlue = -1;
float intervalRed = -1;
float intervalGreen = -1;
float intervalBlue = -1;
//the float time was calculated by
//IntervalValue(set to 0.01)/Value Change (1024 when going from on to off) = 10,240 ticks
//ExecutionTime (beginning time - end time) /# of ticks = 0.0347643
// I seem to be getting varying execution times so I have tried values between 0.028 and 0.04
float tickTime = 0.028027;
int executionTime = 1;
int showTime = 1;
int beginningReceivedData;
void setup()
{
Serial.begin(9600);
//set rgb led pins to output
pinMode(pinRed, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinBlue, OUTPUT);
digitalWrite(pinRed, HIGH);
digitalWrite(pinGreen, HIGH);
digitalWrite(pinBlue, HIGH);
mqttClient.setCallback(callback);
WiFi.begin("partyHouse", "whatsthepassword");
connectToWiFiAndBroker();
}
void connectToWiFiAndBroker()
{
Serial.print("\nConnecting to WIFI");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println("Connected to WIFI!");
Serial.println("Connecting to broker");
while (!mqttClient.connect(CLIENT_NAME))
{
Serial.print(".");
delay(500);
}
Serial.println("Connected to broker!");
mqttClient.subscribe("InterestingTopics/#");
}
void loop()
{
if (!mqttClient.connected()) {
connectToWiFiAndBroker();
}
mqttClient.loop();
updateColors();
}
//------------------------------------------------------------------------------------------------------------------------
//The CallBack for processing incoming data
//------------------------------------------------------------------------------------------------------------------------
//the topic is the path based on the subscription
void callback(char* topic, byte* payload, unsigned int length)
{
//for tracking the time it takes to process the data, as well as the time it takes to complete updating the colors over the desired time
beginningReceivedData = millis();
char commandValue[length+1];
for (int i = 0; i < length; i++)
{
commandValue[i] = (char)payload[i];
}
commandValue[length+1] = '\0';
if (strcmp(topic, "InterestingTopics/time") == 0) {
executionTime = atoi(commandValue);
}
if (strcmp(topic, "InterestingTopics/red") == 0) {
showTime = 1;
nextRed = atoi(commandValue);
intervalRed = (nextRed - currentRed)/(executionTime/tickTime);
//manual Interval value used for calculating the tickTime
if (nextRed < currentRed) {
intervalRed = -0.1;
} else {
intervalRed = 0.1;
}
Serial.print("next: ");
Serial.print(nextRed);
Serial.print(" Current: ");
Serial.print(currentRed);
Serial.print(" Interval: ");
Serial.println(intervalRed, 10);
Serial.print("time to process incoming single value (red): ");
Serial.println(millis() - beginningReceivedData);
}
if (strcmp(topic, "InterestingTopics/green") == 0) {
nextGreen = atoi(commandValue);
intervalGreen = (nextGreen - currentGreen)/(executionTime/tickTime);
}
if (strcmp(topic, "InterestingTopics/blue") == 0) {
nextBlue = atoi(commandValue);
intervalBlue = (nextBlue - currentBlue)/(executionTime/tickTime);
}
}
void updateColors() {
//------------------------------------------------------------------------------------------------------------------------
//Updating the Red
//------------------------------------------------------------------------------------------------------------------------
if (currentRed != nextRed && nextRed > -1) {
currentRed = currentRed + intervalRed;
//if value decreasing and it passes the next value, set values equal to prevent passing
if (intervalRed < 0 && currentRed < nextRed) {
currentRed = nextRed;
}
if (intervalRed > 0 && currentRed > nextRed) {
currentRed = nextRed;
}
analogWrite(pinRed, (int)currentRed);
//this else exists just to print the different in time from receiving the value to the time it took to update
} else if (currentRed == nextRed && nextRed > -1 && showTime == 1) {
//showTime set to zero to only print the time once
showTime = 0;
Serial.print("full color change has completed taking this much time: ");
Serial.println(millis() - beginningReceivedData);
}
//------------------------------------------------------------------------------------------------------------------------
if (currentGreen != nextGreen && nextGreen > -1) {
currentGreen = currentGreen + intervalGreen;
//if value decreasing and it passes the next value, set values equal to prevent passing
if (intervalGreen < 0 && currentGreen < nextGreen) {
currentGreen = nextGreen;
}
if (intervalGreen > 0 && currentGreen > nextGreen) {
currentGreen = nextGreen;
}
analogWrite(pinGreen, (int)currentGreen);
}
if (currentBlue != nextBlue && nextBlue > -1) {
currentBlue = currentBlue + intervalBlue;
//if value decreasing and it passes the next value, set values equal to prevent passing
if (intervalBlue < 0 && currentBlue < nextBlue) {
currentBlue = nextBlue;
}
if (intervalBlue > 0 && currentBlue > nextBlue) {
currentBlue = nextBlue;
}
analogWrite(pinBlue, (int)currentBlue);
}
}