How to drive RGB LEDs with ESP32 & ESP8266

I'm LED mad! It's deLEDhtfull!

I’m starring at 410 individually addressable LEDs (WS2812b). They all blink in rainbow fashion driven by a test FastLED library. I have to say the road was bumpy and took me longer than I initially thought it would, to get here. The internet is lacking a clear set of instructions how to drive RGB LEDs with ESP32 & ESP8266. This is my contribution.

WS2812b RGB LEDs with ESP32 & ESP8266

I had some spare LEDs left from my automated staircase lights project. I had over 400 of them left to be precise. Previously, I used Arduino Nano to drive the LEDs. This was simple enough as both Arduino and individually addressable LEDs use the same 5V logic.

Support NotEnoughTech
Buy RGB LEDs (ws2812) 

Arduino I used has no internet. I figured out, it would be nice to drive the LEDs with an ESP of some kind. To my surprise, there is more to level logic shifting than adding a module I had. Nothing worked until I consulted the internet. Turns out my LLC were too slow to deal with PWM signal. Since I knew what’s wrong, finding the suitable components was quick and easy. Well, it was easy, as I had to wait 4 weeks for the IC to be shipped.

The parts are here and I’m using an IC SN74HCT245 to handle the level shifting for me. The data sheet can be daunting if you never had to read one of these. Don’t worry, I will explain all the information you need to know.

I have tested the RGB LEDs with ESP32 & ESP8266, however, I think my project will end up running on ESP32 if I want to host a web server. I will have more processing power to handle the changes and the ESP32 should perform faster in that aspect.

Support NotEnoughTech

SN74HTC245 or SN74HTC125

Take a look at the pin out of the IC.  You will see this chip can shift 8 (or 4 for SN74HTC125) channels in both directions. To properly connect the IC you have to also read this table:

Here is the schematic how you should connect the IC to drive RGB LEDs with ESP32 & ESP8266. In my video I’m driving 410 LEDs with a single ESP32, you should be able to achieve the same with ESP28266.

Make sure that ESP’s share GND with LED’s power supply otherwise the lights won’t work properly. I was actually surprised how little power these 400+ LEDs has been using.  I never hit the 2A mark even when the brightness has been will find a colour palette sketch to try your lights. Don’t worry, I know the sketch says it’s for WS2811 LED’s. It will work just fine!

 

ARDUINO IDE: Color Palette
#include 

#define LED_PIN     2
#define NUM_LEDS    50
#define BRIGHTNESS  64
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100

CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


void setup() {
    delay( 3000 ); // power-up safety delay
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
    
    currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}

void loop()
{
    ChangePalettePeriodically();
    
    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    
    FillLEDsFromPaletteColors( startIndex);
    
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < NUM_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}

void ChangePalettePeriodically()
{
    uint8_t secondHand = (millis() / 1000) % 60;
    static uint8_t lastSecond = 99;
    
    if( lastSecond != secondHand) {
        lastSecond = secondHand;
        if( secondHand ==  0)  { currentPalette = RainbowColors_p;         currentBlending = LINEARBLEND; }
        if( secondHand == 10)  { currentPalette = RainbowStripeColors_p;   currentBlending = NOBLEND;  }
        if( secondHand == 15)  { currentPalette = RainbowStripeColors_p;   currentBlending = LINEARBLEND; }
        if( secondHand == 20)  { SetupPurpleAndGreenPalette();             currentBlending = LINEARBLEND; }
        if( secondHand == 25)  { SetupTotallyRandomPalette();              currentBlending = LINEARBLEND; }
        if( secondHand == 30)  { SetupBlackAndWhiteStripedPalette();       currentBlending = NOBLEND; }
        if( secondHand == 35)  { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND; }
        if( secondHand == 40)  { currentPalette = CloudColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 45)  { currentPalette = PartyColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 50)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND;  }
        if( secondHand == 55)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
    }
}

void SetupTotallyRandomPalette()
{
    for( int i = 0; i < 16; i++) {
        currentPalette[i] = CHSV( random8(), 255, random8());
    }
}

void SetupBlackAndWhiteStripedPalette()
{
    // 'black out' all 16 palette entries...
    fill_solid( currentPalette, 16, CRGB::Black);
    // and set every fourth one to white.
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;
    
}

void SetupPurpleAndGreenPalette()
{
    CRGB purple = CHSV( HUE_PURPLE, 255, 255);
    CRGB green  = CHSV( HUE_GREEN, 255, 255);
    CRGB black  = CRGB::Black;
    
    currentPalette = CRGBPalette16(
                                   green,  green,  black,  black,
                                   purple, purple, black,  black,
                                   green,  green,  black,  black,
                                   purple, purple, black,  black );
}


const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
{
    CRGB::Red,
    CRGB::Gray, // 'white' is too bright compared to red and blue
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Red,
    CRGB::Gray,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Black,
    CRGB::Black
};

I used Arduino IDE and the FastLED library to drive the LEDs.  You can install this library directly through the Library Manager. The sketched used by me to test the matrix is the Color Palette. Adjust the following details:

#include <FastLED.h>

#define LED_PIN 2 //signal pin 
#define NUM_LEDS 50 //number of LEDs in your strip
#define BRIGHTNESS 64  //brightness  (max 254) 
#define LED_TYPE WS2811  // I know we are using ws2812, but it's ok!
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

 Conclusion

I hope this short article will help you with your project. Driving RGB LEDs with ESP32 & ESP8266 is fun and enables a lot of functionality, that was not possible with Arduino Nano. My next project will involve the set up presented to you! I have included the project file and the IC datasheet for you in the download link. If you want to learn more about how to power this monster of a matrix check out this post.

Support NotEnoughTech
A lot of time and effort goes into keeping NotEnoughTech alive! If my work helped you out, consider buying me a coffee or check out exclusive rewards available to Patreon supporters.
SHARE