FastLED library for RGB controls

I had what I thought was a clever idea, but its not working as well as I’d hoped. I have a guess why, but I’m not sure, and hoping someone can enlighten me.

I’m using PWM-driven MOSFETS (N306AD logic-level) off pins 3, 5, and 6 of a pro-mini for controlling an LED strip. The MOSFET gate is connected directly to the arduino pin, with a 10K resistor tying it to ground.

I’m well-familiar with the FastLED library, so I thought I’d just use my existing FastLED code for analog strips by using the analogWrite() function for each color channel in place of the FastLED.show() commands.

Here’s an example of the code:

void ColorWheel(){
for (uint8_t i=0; i<NUM_LEDS; i++){
leds*= CHSV(COLOR, HUE, BRIGHTNESS);*

  • }*

  • analogWrite(R, leds[0].red);*

  • analogWrite(G, leds[0].green);*

  • analogWrite(B, leds[0].blue);*

  • unsigned long tic = millis();*

  • unsigned long toc = millis() - tic;*

  • while (toc < WAIT){*

  • check_Net();*

  • toc = millis() - tic;*

  • }*

  • COLOR++;*
    }
    [/quote]
    *But the results in the strip are anything but smooth. The color channels are jittery and do not fade cleanly when they’re at low values. I’m assuming this has something to do with the 8-bit resolution of PWM, but that’s just a guess. *
    Other code for fading and such executes cleanly, so I know its not a power supply issue.
    Thanks in advance. :slight_smile:

Hmmmm, but when I use the code posted here it works like I thought it should.

silly_cone: Here's an example of the code:

Please post all your code, not just a part of it. And please use code tags, not quotation tags.

silly_cone: But the results in the strip are anything but smooth. The color channels are jittery and do not fade cleanly when they're at low values. I'm assuming this has something to do with the 8-bit resolution of PWM, but that's just a guess.

Most "neopixel" strips/leds (e.g. ws2811, ws2812b) are also 8-bit resolution PWM.

I think I've got the problem solved. And I'll read up on forum code-posting procedures for the future.

Then start by posting the answer here...

And if you only have one CRGB object, it's a bit useless to put it into an array...

The only reason I was still using the array was to minimize alterations to the code from previous FastLED programs I had. It has since been eliminated.

I think I traced the original problem back to network functions for checking and updating the RF24 network. The main program was trying to exchange messages with nodes that weren't present and it was causing hiccups. Once the function-calls were removed it ran smoothly, and once the other nodes were active, it also ran smoothly.

Below is the complete code for the driver in question. It receives commands from a separate controller that sends an array of the button states, which are then parsed by the controller to switch program modes, brightness, speeds, etc. The main driver then also has two slaves that it sends the light commands to so they all move in synch.

An image of the schematic is attached below as well.

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <FastLED.h>

RF24 radio(A1,10);                    // nRF24L01(+) radio attached using Getting Started board 

RF24Network network(radio);          // Network uses that radio

const uint16_t this_node = 03;  // This node ID

const uint16_t NUM_NODES = 2;  // Number of slaves

uint16_t Index[NUM_NODES]{  // Slave IDs
  Index[0] = 023,
  Index[1] = 033};

int mode = 4, max_mode = 5, G = 3, R = 5, B = 6, div_bright = 1, WAIT = 20;

uint8_t COLOR = 0, HUE = 255, BRIGHTNESS = 255; 

uint8_t buttons[5];  //Button-array received from Controller

boolean rcvd = false;  

void setup()   
{
  radio.begin();
  network.begin(/*channel*/ 90, /*node address*/ this_node);
  SPI.begin();
  Serial.begin(9600);
  
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);

  colorBars();
  
}

void loop()  
{ 
/*
  Serial.println();
  Serial.print("Current Mode: ");
  Serial.println(mode);
  Serial.println();
*/ 
  check_Net();        // Update network and take subsequent actions
  
  switch (mode){    // Switch-case contains the lighting operations
    case 0:
      showAnalogRGB( CRGB(0,0,0) );
      break;

    case 1:
      White();
      break;

    case 2:
      ColorWheel();
      break;

    case 3:
      Rand_Color();
      break;

    case 4:
      Twilight();
      break;

    case 5:
      Waver();
      break;
  }
}


void White (){
  showAnalogRGB( CRGB(255, 90, 40) );
}


void ColorWheel(){
  
  showAnalogRGB( CHSV( COLOR, HUE, BRIGHTNESS) );
  
  unsigned long tic = millis();
  unsigned long toc = millis() - tic;

  while (toc < WAIT){
    toc = millis() - tic;
    check_Net();
  }
  COLOR++;
}

void Rand_Color(){
  
  COLOR = random(255);

  showAnalogRGB( CHSV( COLOR, HUE, BRIGHTNESS) );

  unsigned long tic = millis();
  unsigned long toc = millis() - tic;

  while (toc < WAIT){
    toc = millis() - tic;
    check_Net();
  }
}

void Twilight(){

  int green2 = beatsin16(6, 10, 255);
  int green1 = beatsin16(2.5, 50, 200);
  int blue1 = beatsin16(0.5, 10, 250);
  int blue2 = beatsin16(4.8, 30, 200);

  int avg_green = (green1 + green2) / 2;
  int avg_blue = (blue1 + blue2) / 2;

  showAnalogRGB( CRGB( 255, avg_green, avg_blue) );
}

void Waver(){
  int sin_1 = beatsin16(3.2, 50, 255);
  int sin_2 = beatsin16(0.5, 60, 255);

  int brightness = (sin_1 + sin_2) / 2;

  showAnalogRGB( CHSV(5, 190, brightness));
}


void showAnalogRGB( const CRGB& rgb)
{
  analogWrite(R, rgb.r );
  analogWrite(G, rgb.g );
  analogWrite(B,  rgb.b );
  update_Nodes(rgb);
}


void colorBars()
{
  showAnalogRGB( CRGB::Red );   delay(1000);
  showAnalogRGB( CRGB::Green ); delay(1000);
  showAnalogRGB( CRGB::Blue );  delay(1000);
  showAnalogRGB( CRGB::Black ); delay(1500);
}

void update_Nodes (const CRGB& rgb){  // Update Slave modules
    uint8_t payload[3];
    payload[0] = rgb.r;
    payload[1] = rgb.g;
    payload[2] = rgb.b;

    for (int i = 0; i < NUM_NODES; i++){
    RF24NetworkHeader header(/*to node*/ Index[i], 'L');
    bool ok = network.write(header,&payload,sizeof(payload));
    if (ok){Serial.print("TX, Node: "); Serial.print (Index[i]); Serial.println(" = TRUE");}
    else{Serial.print("TX, Node: "); Serial.print (Index[i]); Serial.println(" = FALSE");}
    }
}

void check_Net(){  // update newtork and take subsequent action
  network.update();
  
  while ( network.available() )  {                      // Is there anything ready for us?
     
    RF24NetworkHeader header;                            // If so, take a look at it
    network.peek(header);

    switch (header.type){                              // Dispatch the message to the correct handler.
      case 'B': network.read(header,&buttons,sizeof(buttons)); update_Buttons(); break;
    }
  }
}

void update_Buttons(){
  //Serial.println(buttons[0]); // Mode
  //Serial.println(buttons[1]); // Off
  //Serial.println(buttons[2]); // Brightness
  //Serial.println(buttons[3]); // Left pot
  //Serial.println(buttons[4]); // Right pot
    
  if (buttons[0] == 1){
    buttons[0] = 0;
    mode++;
    if (mode > max_mode){mode=0;}
  }

  if (buttons[1] == 1){
    buttons[1] = 0;
    mode = 0;
    return;
  }

  if (buttons[2] == 1){
    buttons[2] = 0;
    BRIGHTNESS -= 51;
  }

    //Serial.println(buttons[0]); // Mode
    //Serial.println(buttons[1]); // Off
    //Serial.println(buttons[2]); // Brightness
    //Serial.println(buttons[3]); // Left pot
    //Serial.println(buttons[4]); // Right pot
    //Serial.print("Now in Mode: ");
    //Serial.println(mode);
  
  return;
}

Unfortunately, now that this problem has been corrected, there’s another that’s popping up. This time, I believe its regarding the power supply. This driver is controlling cabinet-lighting in the kitchen; there are lights below the main cabinets above the kitchen counter, and also lights illuminating the floor under the counter. These two lines of light are not physically connected and each have their own leads; there are approximately 8-10 meters of LEDs altogether with 60 LEDs/m (each of the two strips are approximately the same length). Assuming a max draw of 1.2 A/m for bright-white, these should top-out at 12A combined. So I decided to test them using a 15A ATX PSU and just took both of the leads for each color channel and connected them together to the MOSFET terminals. So the red from each got screwed into the same mosfet, the blues in theirs, greens, and finally the POS were connected.

When each strip is tested by itself, they work great. When I connected both strips together, I get this weird warbling effect, that’s particularly pronounced during blue and green fade in/out.

I’m assuming this has to do with limitations of the power supply, but I’m otherwise at a loss. It seems like if the supplies were getting maxed-out then the LEDs just wouldn’t be as bright, like you see with wall-warts. I also tried plugging in a 12V, 10A switched-mode LED PSU which buzzed horribly and also warbled when both lines were hooked up, but did great and worked silently when only one line was running.

I also tried using a separate board that uses the exact same circuit as in the schematic, but with different MOSFETs to no avail. The MOSFETs that were used in each are ISL9N306AD3 and ISL9N306AS3ST.

You need to read up on forum procedures a little more! This is how you post a picture/diagram
6bfef08c9c050ed40dbc39adeed6f64b86bf983e.png
So you think it might be a power supply problem? I would probable agree. But if that’s what you think, why haven’t you posted links to the specs of either of the ones you tried?

It didn't even occur to me to post additional for the PSUs. What specs exactly are you interested in seeing from my AliExpress LED PSUs? Everything I know about them can be found here. I included the power rating above, as that's all I know about them. The ATX PSU isn't with me, so I'll have to post that later, but like I said above, its a standard computer power supply with 15A on the 12V line.

And I COULDN'T post the pic up on the forum because I have to wait several minutes after the initial post before I can re-post, and I'm at work, so I got occupied with work-stuff.

silly_cone: IAnd I COULDN'T post the pic up on the forum because I have to wait several minutes after the initial post before I can re-post

Oh, yeah, I keep forgetting about that restriction. Must be annoying, sorry.

Without knowledge of their exact specs on hand, can you help me understand likely why they would be acting so strangely when they should be fully within their current ratings? Surely it must not be too unique to those exact models.

The PSU specs look OK to me. And your current calculations seem sensible.

Do you have some large caps in the circuit? e.g. 1000uF (18V or higher)? One per channel might be worth a try. Place each one accross 12V & ground, near the MOSFETs.

At one point I tried adding a 1000 uF cap across each of the color channel outputs, so the positive went to the 12V and the negative went into the screw-terminal with the LED wire. The PSU reallllly did NOT like that. Or did I put them in the wrong place?

Because you use pwm you DON'T want to put a cap after the mosfet (aka in the pwm signal). If you want to add caps you add them in front of the mosfet aka parallel over the PSU.

I had a feeling that was the case. It didn't make sense to me as I was doing it, but thought I'd try anyway. So it sounds like I want the cap as close to the Sink on the MOSFET as possible then, correct?

Yep :)

I will try that tonight and report back. Thank you both for your valuable input. :-D

I added a 1,000 uF cap on each MOSFET, and the lights are operating much more smoothly than before.

There is still some mild ripple that occurs even when the lights are held at a constant value, though. For instance, I have a custom White that is Red = 255, Green = 90, Blue = 50. When running that combo, the blue channel was a very slight ripple where it gains and loses a small amount of brightness at a regular rhythm; its barely perceptible, but there. I don't have a scope, or else I'd post the output.

I'm going to try adding an additional cap to each channel to see if it smooths out that last ripple.