I am trying to have 3 indicator LEDs for a weather station. I want the LEDs to dim at night, so they're not blindingly bright.
My code achieves this, with one physical glitch - RGB LEDs don't like being driven at such slow PWMs apparently, and on the LED that is supposed to indicate yellow, the green LED shuts off, and it goes to full red.
I can even watch the threshold at which this happens by attaching a slider on my IOT app to the led brightness. I drag the slider down, and the yellow RGB LED gets dimmer and dimmer, until I drag the slider below a certain point and it instantly turns red.
I had tried playing around with various resistors - someone said this is because the red anode operates at a lower voltage than the green or blue ones, and requires a larger resistor as a result. Let me tell you this did not help one bit.
So I bought some Neopixel LEDs thinking this would solve the issue once and for all. They are fully balanced either internally, or in the libraries. I don't have to mess around with green being twice as bright or anything, they took care of all that.
It still happens. The exact same way. With a freakin Neopixel LED. With a completely different code library driving the LED, with a completely different LED.brightness function. It still turns red if I drag the brightness too low.
You're all welcome to look at my code if you want, it's large and messy. I have no idea if the issue is code or not. I figured it shouldn't have happened switching from analog LEDs to fully self contained RGB drivers, which tells me it's code. But then the fact that my code completely switched libraries tells me it isn't.
Here's the code that I think is relevant. Here is where I decide what colours to drive the LEDs based on information from my weather station, with poorly chosen variable names:
if (menuValue == 2)
{
pmG = 55 - sliderValue; //"slidervalue" is indoor pm2.5
if (pmG < 0) {pmG = 0;}
pmG *= (255.0/55.0);
if (pmG > 255) {pmG = 255;}
pmR = sliderValue;
if (pmR < 0) {pmR = 0;}
pmR *= (255.0/55.0);
if (pmR > 255) {pmR = 255;}
pmB = sliderValue - 100;
if (pmB < 0) {pmB = 0;}
pmB *= (255.0/55.0);
if (pmB > 255) {pmB = 255;}
pmG2 = 55 - bridgedata; //bridgedata is outdoor pm2.5
if (pmG2 < 0) {pmG2 = 0;}
pmG2 *= (255.0/55.0);
if (pmG2 > 255) {pmG2 = 255;}
pmR2 = bridgedata;
if (pmR2 < 0) {pmR2 = 0;}
pmR2 *= (255.0/55.0);
if (pmR2 > 255) {pmR2 = 255;}
pmB2 = bridgedata - 100;
if (pmB2 < 0) {pmB2 = 0;}
pmB2 *= (255.0/55.0);
if (pmB2 > 255) {pmB2 = 255;}
pmG3 = 155 - bmeiaq; //bmeiaq is IAQ from BME680
if (pmG3 < 0) {pmG3 = 0;}
pmG3 *= (255.0/155.0);
if (pmG3 > 255) {pmG3 = 255;}
pmR3 = bmeiaq;
if (pmR3 < 0) {pmR3 = 0;}
pmR3 *= (255.0/155.0);
if (pmR3 > 255) {pmR3 = 255;}
pmB3 = bmeiaq - 155;
if (pmB3 < 0) {pmB3 = 0;}
pmB3 *= (255.0/155.0);
if (pmB3 > 255) {pmB3 = 255;}
strip.setBrightness(LEDbrightness);
strip.setPixelColor(2, strip.Color(pmR3, pmG3, pmB3));
strip.setPixelColor(0, strip.Color(pmR, pmG, pmB));
strip.setPixelColor(1, strip.Color(pmR2, pmG2, pmB2));
}
And here is where I decide how bright to drive the LEDs, by combining the values from a photocell on an analogread pin, and a slider on my IOT app to give more control over the photocell:
{
LEDbrightness = ((analogRead(A0) * 0.0005) * sliderLEDbrightness);
if (LEDbrightness > 255) {LEDbrightness = 255;}
if (LEDbrightness < 1) {LEDbrightness = 1;}
}
If I change the "1"'s in that last line of code to a larger number over the threshold, like 6, so that LEDbrightness is forbidden from going below 6, then this prevents my issue, and the LEDs are always the colour they are told to be. It's only when that value goes below 6 (or 4, I can't remember which) that it suddenly snaps from the proper blended orangey yellow, to full red.
This happens whether I am driving a Neopixel 1wire RGB LED through a Neopixel library, or whether I'm driving a proper regular RGB LED through three PWM pins, even with proper resistor values (higher for the red pin) on all 3 pins.