0

I have an analog or dumb RGB strip that I control with HTTP commands. I want to be able to make the strip fade between different colours when I call http://XX.X.X.XXX/fade. I want it to do this infinitely until another colour is set or it turns on or off. I have tried doing this with a while loop but I can no longer change the state of the light from fading. Does anyone know how to do this? I'll link my code below.

//NodeMCU RGB-Controller for Homebridge & HomeKit (Siri)

#include <ESP8266WiFi.h>

#include <DNSServer.h>
#include <ESP8266WebServer.h>

#define redPin 13 //D7 - Red channel
#define grnPin 12 //D6 - Green channel
#define bluPin 14 //D5 - Blue channel

#define max(a,b) ((a)>(b)?(a):(b))

WiFiServer server(80); //Set server port

String readString;           //String to hold incoming request
String hexString = "FFFFFF"; //Define inititial color here (hex value), 080100 would be a calm warmtone i.e.

int state;

bool fading;

int r;
int g;
int b;

float R;
float G;
float B;

int x;
int V;

///// WiFi SETTINGS - Replace with your values /////////////////
const char* ssid = "SSID";
const char* password = "PASSWORD";
IPAddress ip(XX,X,X,XXX);      // set a fixed IP for the NodeMCU
IPAddress gateway(XX.X.X.X);  // Your router IP
IPAddress subnet(XXX.XXX.XXX.X); // Subnet mask
////////////////////////////////////////////////////////////////////

void WiFiStart() {
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet); //Set a fixed IP. You can comment this out and set it in your router instead.
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print("_");
  }
  Serial.println();
  Serial.println("Done");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("");

  server.begin();                   
}

void allOff() {
  state = 0;
  for (float fade = 1.0; fade >= 0.0; fade -= 0.01) {
    analogWrite(redPin, map((r * fade), 0, 255, 0, 1023));
    analogWrite(grnPin, map((g * fade), 0, 255, 0, 1023));
    analogWrite(bluPin, map((b * fade), 0, 255, 0, 1023));
    delay(2);
  }
  // Set r/g/b to 0 so fade in is possible
  r = 0;
  b = 0;
  g = 0;
}

//Write requested hex-color to the pins
void setHex() {
  const float STEPS = 100; // Change number of steps while fading (lower is faster)
  // Save old values of r/g/b
  byte oldR = r;
  byte oldG = g;
  byte oldB = b;
  long number = (long) strtol( &hexString[0], NULL, 16);
  r = number >> 16;
  g = number >> 8 & 0xFF;
  b = number & 0xFF;
  float deltaR = (r - oldR) / STEPS;
  float deltaG = (g - oldG) / STEPS;
  float deltaB = (b - oldB) / STEPS;
  // Fade to new colour
  for (float f = 0; f < STEPS; f++) {
    analogWrite(redPin, map((oldR + (deltaR * f)), 0, 255, 0, 1023));
    analogWrite(grnPin, map((oldG + (deltaG * f)), 0, 255, 0, 1023));
    analogWrite(bluPin, map((oldB + (deltaB * f)), 0, 255, 0, 1023));
    delay(2);
  }
  state = 1;
}

//Compute current brightness value
void getV() {
  R = roundf(r/2.55);  //was (r/10.23);
  G = roundf(g/2.55);  //was (g/10.23);
  B = roundf(b/2.55);  //was (b/10.23);
  x = max(R,G);
  V = max(x, B);
}

//For serial debugging only
void showValues() {
  Serial.print("Status on/off: ");
  Serial.println(state);
  Serial.print("RGB color: ");
  Serial.print(r);
  Serial.print(".");
  Serial.print(g);
  Serial.print(".");
  Serial.println(b);
  Serial.print("Hex color: ");
  Serial.println(hexString);
  getV();
  Serial.print("Brightness: ");
  Serial.println(V);
  Serial.println("");
}

void setup() {
  Serial.begin(9600);
  delay(1);
  pinMode(redPin, OUTPUT);
  pinMode(grnPin, OUTPUT);
  pinMode(bluPin, OUTPUT);
  WiFi.mode(WIFI_STA);
  WiFiStart();
  setHex();
}

void loop() {
  WiFiClient client = server.available();

  if (!client) {
    return;
  }

  while(client.connected() && !client.available()) {
    delay(1);
  }

  //Respond on certain Homebridge HTTP requests
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (readString.length() < 100) {
          readString += c;
        } 
        if (c == '\n') {
          Serial.print("Request: ");
          Serial.println(readString);

          //Send reponse
          client.println("HTTP/1.1 200 OK"); 
          client.println("Content-Type: text/html");
          client.println();

          //On
          if(readString.indexOf("on") >0) {
            setHex();
            showValues();
            fading = false;
          }

          //Off
          if(readString.indexOf("off") >0) {
            allOff();
            showValues();
            fading = false;
          }

          //Fade
          if(readString.indexOf("fade") >0) {
            fade();
            fading = true;
          }

          //Set color
          if(readString.indexOf("set") >0) {
            hexString = "";
            hexString = (readString.substring(9,15));
            setHex();
            showValues();
            fading = false;
          }

          //Status on/off
          if(readString.indexOf("status") >0) {
          client.println(state);
          }

          //Status color (hex)
          if(readString.indexOf("color") >0) {
          client.println(hexString);
          }

          //Status brightness (%)
          if(readString.indexOf("bright") >0) {
          getV();
          client.println(V);
          }

          delay(1);
          client.stop();
          readString="";
        }
      }
    }
  }
}

void fade() {
  while(fading == true){
    hexString = "000000";
    setHex();
    hexString = "FFFFFF";
    setHex();
    hexString = "FF0000";
    setHex();
    hexString = "008000";
    setHex();
    hexString = "0000FF";
    setHex();
    hexString = "FFFF00";
    setHex();
    hexString = "1E1E1E";
    setHex();
   }
 }
  • 1. get rid of the client.read() malarky using server.on() to handle your API outside of loop(). 2. move your setHex code to loop, and make enough of the control variables globals so that it performs as expected. 3. have your API modify the control variables, like step increment (which can be zero to pause/halt), current colors, etc. – dandavis Jul 12 '18 at 8:24
0

The variable fading cannot ever change, once you are in that while loop, since your code doesn't do it and you don't use interrupts either (And I don't know, if the library is supporting this). So the Arduino is stuck forever in this loop and will not respond to any interactions but resetting.

There are basically there are 2 different options for you (not counting the usage of a hypothetical interrupt capability of the Wifi library, as I don't know enough about the library):

  1. Adding Wifi code to the while loop: You can just add code, that watches the Wifi interface into the while loop and set the fading variable correspondingly. This is the easiest to program option.
  2. Rewrite your code (especially the fade() function) to be non-blocking, which means it will not block the execution of other code, but will only do something, when it is time to do so, and otherwise return from the function. You can achieve this by using the millis() function, which returns the milliseconds since the last startup/reset to use as a time source. Refer to the BlinkWithoutDelay example of the Arduino IDE. Also you can google for millis(); there are a ton of tutorials out there. When writing non-blocking code you might also want to implement a Finite State Machine (FSM). It's simpler as it sounds. You basically define a simple variable, which sets your current state (for example the states fading, off, specific_color, ...). In your loop() function you make a switch(state_variable){ case statement, where you insert code for every state in it's own case. Outside of the switch statement you can then check the Wifi interface and set the state variable correspondingly. If everything is written non-blocking it should work like a charm.
  • Thank you. It worked when I made a switch case in the loop then made a new function called handleWifi() to handle the wifi code. – Username Jul 12 '18 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.