WS2812B with FastLED shows only 1 first led

Hi,
Im using WS2812B led strip with FastLed library and wemos d1 r1 esp8266
The code simply receives http post method to control the led color and number of ON led

My issue is, when i received a command, there is a for loop to turn all led off, and the second for loop to set corresponding color in the desired number of led. As per my understanding, the correct way is to fill all desired data to leds array then call FastLed.show() once. But only 1 first led is lighted up, the rest are off.

Then i tried to call FastLed.show() in every iterator for loop, and somehow it's working. But it introduced a new issue that the execution time increased of course.

Could you please take a look at my code and figure out my wrong codes. Thank you.

There are 2 folders, the Fast and the Slow
The Fast calls FastLed.show() once
The Slow calls FastLed.show() in every iterator loop
Line 175, 184 and 187

Sorry for inconvenience, I posted full code in the comment below. Thank you

1 Like

Not going to download and unzip a zip file from an untrusted site.

Please post your code here. Read the forum guidelines to see how to properly post code and some good information on making a good post.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

If the code is too long, create a minimal reproducable example that shows the problem.

@tanmanh0707 Welcome to the forum! You may consider @groundFungus demand to be unreasonable; please do as he suggested.
There are generally several helpish people around at any one time on this forum, but most will hang back until a newbie has provided good information to start the discussion.
C

Sorry, I did not intent to sound demanding so I edited my request to sound less demanding. Nevertheless, I won't download zip files as it can be a real risk to my computer. A risk that I am not willing to take.

I'm fully on board with that!
C

A schematic of the wiring would also be useful, please.

Hi, sorry for inconvenience. Yesterday I used mobile to create this topic, I could not find how to post code with mobile phone. Below is the full code. Please take a look at lines 175, 184 and 187 for the show( ) calling.
The circuit is simple as the picture. Even the logs show the correct for loop with number of leds, there is only 1 first led lighted up

#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include "configs.h"
#if defined (EEPROM_ENABLED)
#include <EEPROM.h>
#endif

#include "html.h"
#include "js.h"

const byte DNS_PORT = 53;
const char WiFiPassword[] = "12345678";
const char AP_NameChar[] = "LEDControl" ;
DNSServer dnsServer;

#define DATA_PIN D6 // The DATA PIN for the assignable LEDs

CRGB leds[MAX_NUM_LEDS]; // Define the array of leds

#include <Adafruit_GFX.h>  // Include core graphics library for the display
#include <Adafruit_SSD1306.h>  // Include Adafruit_SSD1306 library to drive the display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
//WiFiServer server(80);
ESP8266WebServer webserver(80);

String request = "";
ledSettings_st ledSettings;
String oled_color_hex = "";

#if defined (WIFI_AP_CONFIG_MANUAL) 
IPAddress   WIFI_AP_IP          (192,168,4,23); /* NOTE: The seperator should be a comma (,) */
IPAddress   WIFI_AP_GATEWAY     (192,168,4,1);
IPAddress   WIFI_AP_SUBNET      (255,255,255,0);
#else
IPAddress   WIFI_AP_IP          (192,168,4,1);
#endif

void handleWebRoot( void );
void handleLED();

void LocalWriteDatabase( byte h, byte s, byte v, uint16_t numled, byte state )
{
#if defined (EEPROM_ENABLED)
    EEPROM.write( DB_LED_COLOR_ADDR_HUE, h );
    EEPROM.write( DB_LED_COLOR_ADDR_SAT, s );
    EEPROM.write( DB_LED_COLOR_ADDR_BRI, v );

    byte byte1 = numled >> 8;
    byte byte2 = numled & 0x00FF;
    EEPROM.write( DB_LED_COLOR_ADDR_NUM, byte1 );
    EEPROM.write( DB_LED_COLOR_ADDR_NUM + 1, byte2 );
    
    EEPROM.write( DB_LED_STATE_ADDR,     state );

    if ( EEPROM.commit() ) 
    {
        Serial.println("EEPROM successfully committed");
    } else {
        Serial.println("ERROR! EEPROM commit failed");
    }
#endif
}

bool LocalReadEEPROM( ledSettings_st &ledSettings )
{
  bool ret = false;

#if defined (EEPROM_ENABLED)
  byte indicator = EEPROM.read(0);

  Serial.print("EEPROM indicator: "); Serial.println(indicator, HEX);

  if ( DATABASE_INDICATOR == indicator )
  {
    ledSettings.hue         = EEPROM.read(DB_LED_COLOR_ADDR_HUE);
    ledSettings.saturation  = EEPROM.read(DB_LED_COLOR_ADDR_SAT);
    ledSettings.bright      = EEPROM.read(DB_LED_COLOR_ADDR_BRI);

    byte byte1 = EEPROM.read(DB_LED_COLOR_ADDR_NUM);
    byte byte2 = EEPROM.read(DB_LED_COLOR_ADDR_NUM + 1);
    ledSettings.numled = ((uint16_t)byte1 << 8) + (uint16_t)byte2;
    
    ledSettings.state       = EEPROM.read(DB_LED_STATE_ADDR);
    ret = true;
  }
  else
  {
    //Wrong database
    EEPROM.write( 0, DATABASE_INDICATOR );
    ledSettings.hue         = 0;
    ledSettings.saturation  = 0;
    ledSettings.bright      = 0;
    ledSettings.numled      = MAX_NUM_LEDS;
    ledSettings.state       = LED_OFF;

    LocalWriteDatabase( ledSettings.hue, ledSettings.saturation,
                        ledSettings.bright, ledSettings.numled, ledSettings.state );
  }
#endif

  return ret;
}
 
void setup() 
{
#if defined (EEPROM_ENABLED)
    EEPROM.begin(512);
#endif

    Serial.begin(115200);
    Serial.println(WiFi.macAddress());

    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Initialize display with the I2C address of 0x3C
    display.clearDisplay();  // Clear the buffer
    display.setTextColor(WHITE);  // Set color of the text
    display.setRotation(0);  // Set orientation. Goes from 0, 1, 2 or 3
    display.setTextWrap(true);  // By default, long lines of text are set to automatically β€œwrap” back to the leftmost column.
    display.dim(0);  //Set brightness (0 is maximun and 1 is a little dim)
  
    FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, MAX_NUM_LEDS);

    WiFi.mode(WIFI_AP);

#if defined (WIFI_AP_CONFIG_MANUAL)    
    WiFi.softAPConfig(WIFI_AP_IP, WIFI_AP_GATEWAY, WIFI_AP_SUBNET);
#endif

    String AP_NameMAC = String("LED ") + String(WiFi.macAddress());
    boolean conn = WiFi.softAP(AP_NameMAC);
    dnsServer.setTTL(300);
    dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
#if defined (WIFI_AP_CONFIG_MANUAL)
    dnsServer.start(DNS_PORT, LED_CONTROL_DOMAIN_NAME, WIFI_AP_IP);
#else
    dnsServer.start(DNS_PORT, LED_CONTROL_DOMAIN_NAME, WIFI_AP_IP);
#endif
    

    webserver.on( "/", handleWebRoot );  
    webserver.on( "/led", HTTP_POST, handleLED );
    webserver.begin();

    if ( LocalReadEEPROM( ledSettings ) == true )
    {
        Serial.printf("Database - hue(%d) - saturation(%d) - bright(%d) - numled(%d) - state(%d)\n",
                      ledSettings.hue, ledSettings.saturation, ledSettings.bright,
                      ledSettings.numled, ledSettings.state);
    }
    else
    {
        Serial.println("No database found!!!");
    }

    FastLED.setMaxRefreshRate(0);

    /* Turn off */
    for( int i = 0; i < MAX_NUM_LEDS; i++ )
    {
        leds[i] = CHSV(0, 0, 0);
//        FastLED.show();
    } 

    /* Update last settings */
    if ( LED_ON == ledSettings.state )
    {
      for( int i = 0; i < ledSettings.numled; i++ )
      {
          leds[i] = CHSV(ledSettings.hue, ledSettings.saturation, ledSettings.bright);
//          FastLED.show();
      }
    }
    FastLED.show();

    char buff[10];
    sprintf( buff, "#%02X%02X%02X", ledSettings.hue, ledSettings.saturation, ledSettings.bright );
    oled_color_hex = String( buff );
    display.setTextSize(2);  // Set text size. We are using a custom font so you should always use the text size of 0
    display.setCursor(44, 20);  // (x,y)
    if ( LED_ON == ledSettings.state )
    {
        Serial.println(String("OLED: ")+oled_color_hex);
        display.print(oled_color_hex);
    }
    else
    {
        Serial.println(String("OLED: OFF"));
        display.print(String("OFF"));
    }
    display.display();

    Serial.println("Server started");

//    pinMode(LED_BUILTIN, OUTPUT);
} // void setup()
 
String log_debug;
void loop() 
{
//    display.clearDisplay();  // Clear the display so we can refresh
    display.setTextSize(1);
    display.setCursor(0, 45);
    display.println("  WiFi MAC Address:");
    display.setCursor(0, 55);
    display.print("  ");
    display.println(WiFi.macAddress());
    display.display();

    dnsServer.processNextRequest();
    webserver.handleClient();
    
    display.setTextSize(2);  // Set text size. We are using a custom font so you should always use the text size of 0
    display.setCursor(44, 20);  // (x,y)
     
    delay(5);
  // The client will actually be disconnected when the function returns and 'client' object is detroyed
 
} // void loop()

void handleLED() 
{
    bool requestValid = false;

    String onoff_str = webserver.arg("onoff");
    if ( ! onoff_str.isEmpty() )
    {
        ledSettings.state = LED_ON;
    }
    else
    {
        Serial.println("LED OFF");
        ledSettings.state = LED_OFF;
    }

    String hue_str = webserver.arg("hue");
    if ( ! hue_str.isEmpty() )
    {
        ledSettings.hue = hue_str.toInt();
    }

    String sat_str = webserver.arg("sat");
    if ( ! sat_str.isEmpty() )
    {
        ledSettings.saturation = sat_str.toInt();
    }

    String bright_str = webserver.arg("bright");
    if ( ! bright_str.isEmpty() )
    {
        ledSettings.bright = bright_str.toInt();
    }

    String lednum_str = webserver.arg("lednumber");
    if ( ! lednum_str.isEmpty() )
    {
        ledSettings.numled = lednum_str.toInt();
        requestValid = true;
    }

    if ( requestValid )
    {
        Serial.print("Update LEDS #");
        Serial.print(ledSettings.hue, HEX);
        Serial.print(ledSettings.saturation, HEX);
        Serial.print(ledSettings.bright, HEX);
        Serial.print(" - Num: ");
        Serial.print(ledSettings.numled, DEC);
        Serial.print(" - State: ");
        Serial.println(ledSettings.state, DEC);
        for( int i = 0; i < MAX_NUM_LEDS; i++ )
        {
            leds[i] = CHSV( 0, 0, 0 ); //Turn off all LEDs
//            FastLED.show();
        }

        //Update color
        if ( LED_ON == ledSettings.state )
        {
            Serial.println("Update LEDs color");
            for( int i = 0; i < ledSettings.numled; i++ )
            {
                leds[i] = CHSV( ledSettings.hue, ledSettings.saturation, ledSettings.bright );
//                FastLED.show();
            }
        }

        delay(100);
        FastLED.show();

        LocalWriteDatabase( ledSettings.hue, ledSettings.saturation,
                            ledSettings.bright, ledSettings.numled, ledSettings.state );

        char buff[10];
        sprintf( buff, "#%02X%02X%02X", ledSettings.hue, ledSettings.saturation, ledSettings.bright );
        oled_color_hex = String( buff );
        display.setTextSize(2);  // Set text size. We are using a custom font so you should always use the text size of 0
        display.setCursor(44, 20);  // (x,y)
        display.clearDisplay();
        if ( LED_ON == ledSettings.state )
        {
            Serial.println(String("OLED: ")+oled_color_hex);
            display.print(oled_color_hex);
        }
        else
        {
            Serial.println(String("OLED: OFF"));
            display.print(String("OFF"));
        }
        display.display();
    }
    else
    {
      Serial.println("Client has no request!!!");
    }

//    digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
    webserver.sendHeader("Location","/");
    webserver.send(303);
}

void handleWebRoot( void )
{
    webserver.sendContent( header );
    webserver.sendContent( html_style );
//    webserver.sendContent( log_debug );
    webserver.sendContent("<form id='F1' action='/led' method='POST'>");
    String html_switch_preview = html_onoff;
    String str_preview = String("hsl(") + String((ledSettings.hue*100/255)*360/100)
                         + String(", ") + String((ledSettings.saturation*100/255)*100/100)
                         + String("%, ") + String((ledSettings.bright*100/255)*50/100)
                         + String("%)");
    html_switch_preview.replace("%state", (LED_ON==ledSettings.state)?"checked":"");
    html_switch_preview.replace("%s", String(str_preview));
    webserver.sendContent( html_switch_preview );
    
    String html_preview = html_preview_hex;
    html_preview.replace("%s", oled_color_hex);
    webserver.sendContent( html_preview );

    String html_hue = html_sb_hue;
    html_hue.replace("%s", String(ledSettings.hue));
    webserver.sendContent( html_hue );

    String html_sat = html_sb_sat;
    html_sat.replace("%s", String(ledSettings.saturation));
    webserver.sendContent( html_sat );

    String html_val = html_sb_bri;
    html_val.replace("%s", String(ledSettings.bright));
    webserver.sendContent( html_val );

    String html_5 = html_numled;
    html_5.replace("%numled", String(ledSettings.numled));
    html_5.replace("%maxled", String(MAX_NUM_LEDS));
    webserver.sendContent( html_5 );
    webserver.sendContent( html_save );
    webserver.sendContent( String("</form>") );
    webserver.sendContent( html_js );
    webserver.sendContent( html_tail );
    webserver.sendContent(WiFi.macAddress());
}

I have the exact same Problem.
I could also determine the source of trouble. It's the EEPROM library, especially the EEPROM.commit() method. After using it one time the next FastLed.show() command only sets the first pixel.
This is really frustrating!

As stupid as it sounds a simple workaround is a additional call of FastLED.show() after calling EEPROM.commit().

Have you found any other workarounds or fixes in the mean time?

1 Like

In the tanman sketch
CRGB leds[MAX_NUM_LEDS];

Nowhere is MAX_NUM_LEDS made = to anything.
Perhaps
const int MAX_NUM_LEDS = 16; // or how ever many LEDs there are ??

I don't have FastLED, but making MAX_NUM_LEDS = something is probably important.

I have never figured it out that eeprom caused this issue. So I don't have any workaround solution so far...

Of course MAX_NUM_LEDS is defined in the header file for configuration, otherwise the compilation will give errors. As you can see in my picture, there are 10 Leds so MAX_NUM_LEDS was set to 10

In post #10 ?
Where?

Line 5, there is a header file configs.h

#ifndef _CONFIG_H_
#define _CONFIG_H_

#define LED_CONTROL_DOMAIN_NAME "www.my-domain.com"
#define MAX_NUM_LEDS            10      // How many leds in your strip?

#define EEPROM_ENABLED

#define LED_ON    1
#define LED_OFF   0

#define DATABASE_INDICATOR      0x55

#define DB_LED_COLOR_ADDR_HUE   1
#define DB_LED_COLOR_ADDR_SAT   2
#define DB_LED_COLOR_ADDR_BRI   3
#define DB_LED_COLOR_ADDR_NUM   4
#define DB_LED_STATE_ADDR       6

typedef struct
{
  byte hue;
  byte saturation;
  byte bright;
  uint16_t numled;
  byte state; //ON-OFF
} ledSettings_st;

typedef struct
{
  uint8_t indicator;
  ledSettings_st ledSettings;
} database_st;

#endif  //_CONFIG_H_

But who can see that in the sketch in PostNo.7 ?
(I mentioned postNo.10 last time - in error.)

PE - May I ask if you've run the strip without everything else - to make sure that it's good ?

Sorry for that. I didn't think it was important. Anyway, I posted both source/header files.
Let me try to run the LED strip without anything else.

I tried to minimize the code and this is the simplest block of code with my problem.
If there is 1 show(), only first led lights up
I added one more show() and it works as expected.
Even in the FastLED Blink example, if I want to blink more than 1 led, it always lights up only the first led in the first show() . The subsequence show() can lights up the other leds.
For more details, I'm using Esp8266 Wemos D1 Mini, WS2812B and FastLED library

#include <FastLED.h>

#define NUM_LEDS 24
#define DATA_PIN D6

CRGB leds[NUM_LEDS];
void setup()
{
  uint8_t i = 0;
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);

  for (i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Black;
  }

  for (i = 0; i < 7; i++) {
    leds[i] = CRGB::Red;
  }
  FastLED.show();   //1st show() lights up only the first led
//  FastLED.show();   //2nd show() works as expected
}

void loop() {
}

It looks like you are missing a show() after you assign them all to "black".
For blinking you assign the color etc, show(), delay or however, assign them as "black", show(), delay, repeat.

Thank you for your response.

Actually I don't want to show() after assign them all to black. The assignment to black is to make sure I will not have garbage data. Besides, my understanding is that we need to set all desired value and then call show() in the end, is my understanding correct?

Another use case is, NUM_LEDS = 24, I want 10 first leds to be red and the others to be green. So I think the correct way is to set 10 first leds to red, then set the others to green, and finally call show(). This use case is the same as above code. Therefore, is it neccessary to call show() when we have not finished setting all values?

My code is not for blinking, the blinking I mentioned is another case that has the same issue.

Every change has to be followed by a show(). LED0 and LED1 could be assigned green, followed by show() and they should display so.
Later LED0 can be assigned red and 5 minutes later LED1 can be assigned yellow but that change won't be seen till a show() is sent.

When I run this sketch they all (8) go Red the they all (8) go Blue --

#include <FastLED.h>

#define NUM_LEDS 8
#define DATA_PIN 3

CRGB leds[NUM_LEDS];

void setup() 
{ 
    FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);  // GRB ordering is typical
}

void loop() 
{ 
  for(byte idx = 0; idx < NUM_LEDS; idx ++)
  {
    leds[idx] = CRGB::Blue;
  }
  FastLED.show();
  delay(500);

  for(byte idx = 0; idx < NUM_LEDS; idx ++)
  {
    leds[idx] = CRGB::Red;
  }
  FastLED.show();
  delay(500);  
}

Even though I have the Adafruit "neopixel stick", I had to change it to WS2812 )because it did all Red, 1-7 Red, all Blue, . . .).