0

I have a NodeMCU controlling an RGB strip. I have followed a guide and used this code:

#include <ESP8266WiFi.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 initial color here (hex value), 080100 would be a calm warm tone i.e.

int state;
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 = "xxxxxxx";
const char* password = "xxxxx";
IPAddress ip(x,x,x,x);      // set a fixed IP for the NodeMCU
IPAddress gateway(x,x,x,x);  // Your router IP
IPAddress subnet(255,255,255,0); // 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;
  analogWrite(redPin, 0);
  analogWrite(grnPin, 0);
  analogWrite(bluPin, 0);
}

//Write requested hex color to the pins (10-bit PWM)
void setHex() {
  state = 1;
  long number = (long) strtol( &hexString[0], NULL, 16);
  r = number >> 16;
  g = number >> 8 & 0xFF;
  b = number & 0xFF;
  r = map(r, 0, 255, 0, 1023);  //added for 10-bit PWM
  g = map(g, 0, 255, 0, 1023);  //added for 10-bit PWM
  b = map(b, 0, 255, 0, 1023);  //added for 10-bit PWM
  analogWrite(redPin, (r));
  analogWrite(grnPin, (g));
  analogWrite(bluPin, (b));
}

//Compute current brightness value
void getV() {
  R = roundf(r/10.23);  //for 10bit pwm, was (r/2.55);
  G = roundf(g/10.23);  //for 10bit pwm, was (g/2.55);
  B = roundf(b/10.23);  //for 10bit pwm, was (b/2.55);
  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);
  setHex(); //Set initial color after booting. Value defined above
  WiFi.mode(WIFI_STA);
  WiFiStart();
}

void loop() {
  //Reconnect on lost WiFi connection (superfluous - will reconnect anyway)
  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();
          }

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

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

          //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="";
        }
      }
    }
  }
}

I have tried to fade out by putting my code below in the allOff() function, but it only fades out then comes back white. I would also be interested in fading between different colours in the setHex() function.

void allOff() {
  state = 0;
  for (int i=r; i <= 1023; i--){
  analogWrite(redPin, i);
  analogWrite(grnPin, i);
  analogWrite(bluPin, i);
  }
}

I would appreciate it if anyone could give me the right way to do this. Thank you.

1
for (int i=r; i <= 1023; i--){
    analogWrite(redPin, i);
    analogWrite(grnPin, i);
    analogWrite(bluPin, i);
    }

analogWrite expects a range of 0 to 255, not 0 to 1023.

In any case, why are you starting with the r value and decreasing that? What about b and g?

And why not stop at zero? Your code will reach zero, and then keep going down to -1, -2 etc. I think you mean i >= 0 not i <= 1023.

Let's assume that the previously set values of r, g and b are what you want to fade. Make a loop that decreases them at the same rate:

for (float fade = 1.0; fade >= 0.0; fade -= 0.01)  // 100 steps
    {
    analogWrite(redPin, (float) r * fade);
    analogWrite(grnPin, (float) g * fade);
    analogWrite(bluPin, (float) b * fade);
    delay (10);  // short delay so you notice it
    }

So how could I apply this code to fade between colours in my setHex function?

Well, fading to black is a special case of fading from one colour to another. To do it in (say) 100 steps you need to work out a "delta" - that is the difference, for each of r/g/b from the initial colour to the new one. So for example if the old red value was 10 and the new red value is 50, then the delta is 40 (50 - 10). So over your 100 steps you need to change the red value by 40 / 100. Using floating point arithmetic lets you handle numbers which aren't integers (in this case 40 / 100 would be 0.4). Example code:

  const float STEPS = 100;

  // save old values of r/g/b
  byte oldR = r;
  byte oldG = g;
  byte oldB = b;

  // calculate new values
  long number = (long) strtol( &hexString[0], NULL, 16);
  r = number >> 16;
  g = number >> 8 & 0xFF;
  b = number & 0xFF;

  // work out deltas 
  float deltaR = (r - oldR) / STEPS;
  float deltaG = (g - oldG) / STEPS;
  float deltaB = (b - oldB) / STEPS;

  // fade from old to new
  for (float f = 0; f < STEPS; f++)
    {
    analogWrite(redPin, oldR + (deltaR * f));
    analogWrite(grnPin, oldG + (deltaG * f));
    analogWrite(bluPin, oldB + (deltaB * f));
    delay (10);
    } // end of for
| improve this answer | |
  • Thank you this is exactly what I was looking for, I forgot about the b and g values when I was trying to just test how I could get one channel to fade then forgot. Thanks :) – Username Apr 12 '18 at 5:41
  • How could I do the same with fading between colours in the setHex() function? – Username Apr 12 '18 at 7:10
  • Will the float values get truncated to byte for the analogWrite? If so, then just decrement from 255 by 2 or 3, stop when get down to non-detectable level. – CrossRoads Apr 13 '18 at 16:54
  • Yes, there will be truncation, but this method smoothly dims all three colours at the same rate (eg. R/G/B will at some point all be 50% of what they started). They don't necessarily start at 255, since he wants to dim whatever-colour-it-was he started with. If you just subtract (say) 2, and he starts with R=255,G=100,B=10 then blue will very quickly become zero and the hue will change. – Nick Gammon Apr 13 '18 at 21:14
  • So how could I apply this code to fade between colours in my setHex function(see my code). – Username Apr 14 '18 at 23:38

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.