Issue on FastLED web client, to control on and off for ws2812

What i want to do is, access web link, http://x.x.x.x/2/on, LED strip of 300 NUM_LED on, and then if click button off, all LED strip off.

But i encounter device stuck when i clicked on, sometime LED not all switch on, and the web seems no response, then wait few seconds, try to click on again, sometime the LED can all on. But off LED totally not work.

#include <ESP8266WiFi.h>

#include <FastLED.h>
#define DATA_PIN 5
#define NUM_LEDS 300
CRGB leds[NUM_LEDS];
#define COLOR_ORDER GRB
#define BRIGHTNESS 254
#define FRAMES_PER_SECOND 30


// Enter your wifi network name and Wifi Password
const char* ssid = "Yukitson";
const char* password = "23062306";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// These variables store current output state of LED
String outputRedState = "off";


// Assign output variables to GPIO pins
const int redLED = 5;





// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);


  //FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  LEDS.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  // 初始化光带
  FastLED.setBrightness(BRIGHTNESS);                            // 设置光带亮度
  set_max_power_in_volts_and_milliamps(5, 2000);                 // 光带电源管理(设置光带5伏特,500mA)
  FastLED.clearData();
  FastLED.setMaxRefreshRate(0);


  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  WiFiClient client = server.available(); // Listen for incoming clients

  if (client) { // If a new client connects,
    Serial.println("New Client."); // print a message out in the serial port
    String currentLine = ""; // make a String to hold incoming data from the client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
      currentTime = millis();
      if (client.available()) { // if there's bytes to read from the client,
        char c = client.read(); // read a byte, then
        Serial.write(c); // print it out the serial monitor
        header += c;
        if (c == '\n') { // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /2/on") >= 0) {
              Serial.println("RED LED is on");
              outputRedState = "on";
              for (int ledNum = 0; ledNum < NUM_LEDS; ledNum++)
              {
                leds[ledNum] = CRGB::Red;
              }
              FastLED.show();



            } else if (header.indexOf("GET /2/off") >= 0) {
              Serial.println("RED LED is off");
              outputRedState = "off";
              FastLED.clear();




            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".buttonRed { background-color: #ff0000; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".buttonOff { background-color: #77878A; border: none; color: white; padding: 16px 40px; border-radius: 70%;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>My LED Control Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 2 Red LED
            client.println("<p>Red LED is " + outputRedState + "</p>");
            // If the outputRedState is off, it displays the OFF button
            if (outputRedState == "off") {
              client.println("<p><a href=\"/2/on\"><button class=\"button buttonOff\">OFF</button></a></p>");
            } else {
              client.println("<p><a href=\"/2/off\"><button class=\"button buttonRed\">ON</button></a></p>");
            }

            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') { // if you got anything else but a carriage return character,
          currentLine += c; // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

It could be a problem with the structure of your code. It is difficult to see because your code is not indented correctly. Please click Tools->Auto Format, then post the updated code.

You seem to close the client at the end of your very long loop function.
This was opened in the setup function, so you never seem to open it again.

re-formated

1 Like

how can i change? any hint?

I think you need FastLED.show() after this line. I don't think .clear() updates the LEDs without that.

I cannot immediately see a problem with the structure of your code.

Can you please post output from serial monitor (paste the text between code tags) when the LEDs correctly switch on/off. Also post the output when the LEDs do not correctly switch on/off.

Do not close the connection.

21:30:08.154 -> ⸮⸮a8⸮⸮⸮⸮J9"EH⸮⸮⸮⸮⸮⸮⸮噈H1(⸮@⸮⸮⸮⸮⸮⸮-⸮
21:30:09.976 -> ⸮⸮L⸮
21:30:09.976 -> ⸮⸮J!g⸮܇y1⸮Nފ⸮⸮ֵ⸮⸮]⸮91⸮⸮⸮⸮⸮⸮⸮⸮H)t⸮⸮Ο!)01a!gʾ˥⸮1R⸮⸮L9NN⸮̥⸮
21:30:20.430 -> H)⸮⸮⸮⸮⸮⸮⸮-⸮⸮⸮⸮⸮1}⸮H⸮01 !g⸮܇9⸮⸮⸮⸮,⸮1⸮
21:30:22.679 -> ⸮⸮⸮⸮⸮C⸮

why my output like this?

Incorrect baud rate selected on serial monitor, I think.

It should match the rate in your code:

Thanks. after change to 9600. the text come out.

Below is when i clicked Off.

22:49:33.688 -> New Client.
22:49:33.688 -> GET /2/off HTTP/1.1
22:49:33.735 -> Host: 192.168.2.196
22:49:33.735 -> Connection: keep-alive
22:49:33.780 -> Upgrade-Insecure-Requests: 1
22:49:33.780 -> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
22:49:33.920 -> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
22:49:34.059 -> Referer: http://192.168.2.196/2/on
22:49:34.106 -> Accept-Encoding: gzip, deflate
22:49:34.106 -> Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6,ja;q=0.5
22:49:34.245 ->
22:49:34.245 -> RED LED is off
22:49:34.245 -> Client disconnected.
22:49:34.245 ->
22:49:34.245 -> New Client.
22:49:36.153 -> Client disconnected.
22:49:36.153 ->

How can I blink this LED strips in 5 seconds?

            // turns the GPIOs on and off
            if (header.indexOf("GET /2/on") >= 0) {
              Serial.println("RED LED is on");
              outputRedState = "on";
              fill_solid(leds, NUM_LEDS, CRGB::Red);

            }

I would choose 115200. 9600 is very slow.

Is it working now, do the LEDs go off after my suggestion about using .show()?

I think this means the client was closed too soon, and the code thinks another client has connected, but actually it is the same client. But no data is received, so after 2000ms timeout, the client is closed again.

Perhaps the full request from the client should be read, not stop reading after the header, so that the client is not closed too soon.

Can you capture the serial monitor output when a request to switch the LEDs on or off does not work correctly?

Shall we get the previous problems corrected before adding extra features?

The led on and off are worked now after add Fastled.show
But the client close message, i hear that the device seems reboot as i connected the usb power to the pc.

I don't understand what you are saying. Is there still a problem?

Yes it will do. Applying power to the USB will trigger the automatic reset circuit.

May I have some code related to subject?

code related to Neopixels blinking.

#include <WiFi.h>
#include <PubSubClient.h>
#include "certs.h"
#include "sdkconfig.h"
#include "esp32/ulp.h"
#include "driver/rtc_io.h"
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include <Adafruit_NeoPixel.h>
#include "AudioAnalyzer.h"
////
/* define event group and event bits */
EventGroupHandle_t eg;
#define evtDo_AudioReadFreq       ( 1 << 0 ) // 1
////
QueueHandle_t xQ_LED_Info;
////
//const int LED_COUNT = 24; //total number of leds in the strip
const int LED_COUNT = 108; //total number of leds in the strip
////
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
Adafruit_NeoPixel leds = Adafruit_NeoPixel( LED_COUNT, 26, NEO_GRB + NEO_KHZ800 );
//
WiFiClient wifiClient;
PubSubClient MQTTclient(mqtt_server, mqtt_port, wifiClient);
////
SemaphoreHandle_t sema_MQTT_KeepAlive;
////
void ULP_BLINK_RUN(uint32_t us);
////
void setup()
{
  ULP_BLINK_RUN(100000);
  eg = xEventGroupCreate();
  ////
  int FreqVal[7]; // used to set queue size
  xQ_LED_Info = xQueueCreate ( 1, sizeof(FreqVal) );
  ////
  sema_MQTT_KeepAlive = xSemaphoreCreateBinary();
  xSemaphoreGive( sema_MQTT_KeepAlive );
  ////
  // setting must be set before a mqtt connection is made
  MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds
  connectToWiFi();
  connectToMQTT();
  //////////////////////////////////////////////////////////////////////////////////////////////
  xTaskCreatePinnedToCore( MQTTkeepalive, "MQTTkeepalive", 7000, NULL, 5, NULL, 1 );
  xTaskCreatePinnedToCore( fDo_AudioReadFreq, "fDo_ AudioReadFreq", 30000, NULL, 3, NULL, 1 );
  xTaskCreatePinnedToCore( fDo_LEDs, "fDo_ LEDs", 30000, NULL, 3, NULL, 1 );

  xEventGroupSetBits( eg, evtDo_AudioReadFreq );
} // setup()
////
void loop() {} // void loop
////
void fMQTT_Disconnect(  )
{
  MQTTclient.disconnect();
}
////
void GetTheTime()
{
  char* ntpServer = "2.us.pool.ntp.org";
  int gmtOffset_sec = -(3600 * 7 );
  int daylightOffset_sec = 3600;
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();
}
////
// http://www.cplusplus.com/reference/ctime/strftime/
////
void MQTTkeepalive( void *pvParameters )
{
  int keepCount = 0;
  for (;;)
  {
    log_i( " mqtt keep alive run." );

    if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      //      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); //
      MQTTclient.loop();
      //      xSemaphoreGive( sema_MQTT_KeepAlive );
    }
    else {
      log_i( "MQTT keep alive found MQTT status %s WiFi status %s", String(wifiClient.connected()), String(WiFi.status()) );
      if ( !(WiFi.status() == WL_CONNECTED) )
      {
        connectToWiFi();
      }
      connectToMQTT();
    }
    vTaskDelay( 4900 );
    keepCount++;
    log_i( "%d", keepCount );
    if ( keepCount >= 5 )
    {
      fMQTT_Disconnect();
      keepCount = 0;
    }
  }
  vTaskDelete ( NULL );
}
////
int getHour()
{
  struct tm timeinfo;
  getLocalTime(&timeinfo);
  char _time[ 5 ];
  strftime( _time, 80, "%T", &timeinfo );
  return String(_time).toInt();
}
////
void printLocalTime() {
  struct tm timeinfo;
  getLocalTime(&timeinfo);
  char _time[ 80 ];
  strftime( _time, 80, "%T", &timeinfo );
  log_i( "%s", _time);
  //  }
}
////
void connectToMQTT()
{
  log_i( "connect to mqtt" );
  while ( !MQTTclient.connected() )
  {
    MQTTclient.connect( clientID, mqtt_username, mqtt_password );
    log_i( "connecting to MQTT" );
    vTaskDelay( 250 );
  }
  log_i("MQTT Connected");
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( mqtt_topic );
}
////
void connectToWiFi()
{
  log_i( " Begin Connect to wifi" );
  while ( WiFi.status() != WL_CONNECTED )
  {
    WiFi.disconnect();
    WiFi.begin( SSID, PASSWORD );
    log_i(" waiting on wifi connection" );
    vTaskDelay( 4000 );
  }
  log_i( "End connected to WiFi" );
  WiFi.onEvent( WiFiEvent );
  GetTheTime();
}
////
static void mqttCallback(char* topic, byte * payload, unsigned int length)
{

  //xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY);
  //str_eTopicPtr = topic + '\0';

  int i = 0;
  String temp = "";
  for ( i; i < length; i++) {
    temp += ((char)payload[i]);
  }
  log_i( " topic %s payload %s", topic, temp );
  //  strPayloadPtr[i] = '\0';
  // xSemaphoreGive ( sema_MQTT_KeepAlive );
  //
} // void mqttCallback(char* topic, byte* payload, unsigned int length)
////
void fDo_LEDs( void *pvParameters )
{
  const int Brightness = 200;
  const int SEG = 6; // how many parts you want to separate the led strip into
  const int ledCount = LED_COUNT; //total number of leds in the strip
  int iFreqVal[7];
  int j;
  leds.begin(); // Call this to start up the LED strip.
  clearLEDs( ledCount );  // This function, defined below, de-energizes all LEDs...
  leds.show();  // ...but the LEDs don't actually update until you call this.
  leds.setBrightness( Brightness ); //  1 = min brightness (off), 255 = max brightness.
  for (;;)
  {
    if (xQueueReceive( xQ_LED_Info, &iFreqVal,  portMAX_DELAY) == pdTRUE)
    {
      j = 0;
      //assign different values for different parts of the led strip
      for (j = 0; j < ledCount; j++)
      {
        if ( (0 <= j) && (j < (ledCount / SEG)) )
        {
          //log_i( "segment 0 %d", iFreqVal[0] );
          set( j, iFreqVal[0], ledCount, SEG ); // set the color of led
        }
        else if ( ((ledCount / SEG) <= j) && (j < (ledCount / SEG * 2)) )
        {
          set( j, iFreqVal[0], ledCount, SEG );
        }
        else if ( ((ledCount / SEG * 2) <= j) && (j < (ledCount / SEG * 3)) )
        {
          set( j, iFreqVal[0], ledCount, SEG );
        }
        else if ( ((ledCount / SEG * 3) <= j) && (j < (ledCount / SEG * 4)) )
        {
          set( j, iFreqVal[0], ledCount, SEG );
        }
        else if ( ((ledCount / SEG * 4) <= j) && (j < (ledCount / SEG * 5)) )
        {
          set( j, iFreqVal[0], ledCount, SEG );
        }
        else
        {
          set( j, iFreqVal[0], ledCount, SEG );
        }
      }
      leds.show();
    }
    xEventGroupSetBits( eg, evtDo_AudioReadFreq );
  }
  vTaskDelete( NULL );
} // void fDo_ LEDs( void *pvParameters )
////
void fDo_AudioReadFreq( void *pvParameters )
{
  int FreqVal[7];
  const int NOISE = 10; // noise that you want to chop off
  const int A_D_ConversionBits = 4096; // arduino use 1024, ESP32 use 4096
  Analyzer Audio = Analyzer( 5, 15, 36 );//Strobe pin ->15  RST pin ->2 Analog Pin ->36
  Audio.Init(); // start the audio analyzer
  int64_t EndTime = esp_timer_get_time();
  int64_t StartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros
  for (;;)
  {
    xEventGroupWaitBits (eg, evtDo_AudioReadFreq, pdTRUE, pdTRUE, portMAX_DELAY);
    EndTime = esp_timer_get_time() - StartTime;
    // log_i( "TimeSpentOnTasks: %d", EndTime );
    Audio.ReadFreq(FreqVal);
    for (int i = 0; i < 7; i++)
    {
      FreqVal[i] = constrain( FreqVal[i], NOISE, A_D_ConversionBits );
      FreqVal[i] = map( FreqVal[i], NOISE, A_D_ConversionBits, 0, 255 );
      // log_i( "Freq %d Value: %d", i, FreqVal[i]);//used for debugging and Freq choosing
    }
    xQueueSend( xQ_LED_Info, ( void * ) &FreqVal, 0 );
    StartTime = esp_timer_get_time();
  }
  vTaskDelete( NULL );
} // fDo_ AudioReadFreq( void *pvParameters )
////
//the following function set the led color based on its position and freq value
//
void set(byte position, int value, int ledCount, int segment)
{
  int valueLowLimit = 20;
  // segment 0, red
  if ( (0 <= position) && (position < ledCount / segment) ) // segment 0 (bottom to top)
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor( position, 0, 0, 0 );
    }
    else
    {
      leds.setPixelColor( position, leds.Color( value , 0, 0) );
    }
  }
  else if ( (ledCount / segment <= position) && (position < ledCount / segment * 2) ) // segment 1 yellow
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor(position, leds.Color(0, 0, 0));
    }
    else
    {
      leds.setPixelColor(position, leds.Color( value, value, 0)); // works better to make yellow
    }
  }
  else if ( (ledCount / segment * 2 <= position) && (position < ledCount / segment * 3) ) // segment 2 pink
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor(position, leds.Color(0, 0, 0));
    }
    else
    {
      leds.setPixelColor(position, leds.Color( value, 0, value * .91) ); // pink
    }
  }
  else if ( (ledCount / segment * 3 <= position) && (position < ledCount / segment * 4) ) // seg 3, green
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor(position, leds.Color( 0, 0, 0));
    }
    else //
    {
      leds.setPixelColor( position, leds.Color( 0, value, 0) ); //
    }
  }
  else if ( (ledCount / segment * 4 <= position) && (position < ledCount / segment * 5) ) // segment 4, leds.color( R, G, B ), blue
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor(position, leds.Color( 0, 0, 0));
    }
    else //
    {
      leds.setPixelColor(position, leds.Color( 0, 0, value) ); // blue
    }
  }
  else // segment 5
  {
    if ( value <= valueLowLimit )
    {
      leds.setPixelColor(position, leds.Color( 0, 0, 0));
    }
    else
    {
      leds.setPixelColor( position, leds.Color( value, value * .3, 0) ); // orange
    }
  }
} // void set(byte position, int value)
////
void clearLEDs( int ledCount)
{
  for (int i = 0; i < ledCount; i++)
  {
    leds.setPixelColor(i, 0);
  }
} // void clearLEDs()
////
void WiFiEvent(WiFiEvent_t event)
{
  // log_i( "[WiFi-event] event: %d\n", event );
  switch (event)
  {
    case SYSTEM_EVENT_STA_CONNECTED:
      log_i("Connected to access point");
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      log_i("Disconnected from WiFi access point");
      break;
    case SYSTEM_EVENT_AP_STADISCONNECTED:
      log_i("WiFi client disconnected");
    default: break;
  }
}
//////////////////////////////////////////////
/*
  Each I_XXX preprocessor define translates into a single 32-bit instruction. So you can count instructions to learn which memory address are used and where the free mem space starts.

  To generate branch instructions, special M_ preprocessor defines are used. M_LABEL define can be used to define a branch target.
  Implementation note: these M_ preprocessor defines will be translated into two ulp_insn_t values: one is a token value which contains label number, and the other is the actual instruction.

*/
void ULP_BLINK_RUN(uint32_t us)
{
  size_t load_addr = 0;
  RTC_SLOW_MEM[12] = 0;
  ulp_set_wakeup_period(0, us);
  const ulp_insn_t  ulp_blink[] =
  {
    I_MOVI(R3, 12),                         // #12 -> R3
    I_LD(R0, R3, 0),                        // R0 = RTC_SLOW_MEM[R3(#12)]
    M_BL(1, 1),                             // GOTO M_LABEL(1) IF R0 < 1
    I_WR_REG(RTC_GPIO_OUT_REG, 26, 27, 1),  // RTC_GPIO2 = 1
    I_SUBI(R0, R0, 1),                      // R0 = R0 - 1, R0 = 1, R0 = 0
    I_ST(R0, R3, 0),                        // RTC_SLOW_MEM[R3(#12)] = R0
    M_BX(2),                                // GOTO M_LABEL(2)
    M_LABEL(1),                             // M_LABEL(1)
    I_WR_REG(RTC_GPIO_OUT_REG, 26, 27, 0),// RTC_GPIO2 = 0
    I_ADDI(R0, R0, 1),                    // R0 = R0 + 1, R0 = 0, R0 = 1
    I_ST(R0, R3, 0),                      // RTC_SLOW_MEM[R3(#12)] = R0
    M_LABEL(2),                             // M_LABEL(2)
    I_HALT()                                // HALT COPROCESSOR
  };
  const gpio_num_t led_gpios[] =
  {
    GPIO_NUM_2,
    // GPIO_NUM_0,
    // GPIO_NUM_4
  };
  for (size_t i = 0; i < sizeof(led_gpios) / sizeof(led_gpios[0]); ++i) {
    rtc_gpio_init(led_gpios[i]);
    rtc_gpio_set_direction(led_gpios[i], RTC_GPIO_MODE_OUTPUT_ONLY);
    rtc_gpio_set_level(led_gpios[i], 0);
  }
  size_t size = sizeof(ulp_blink) / sizeof(ulp_insn_t);
  ulp_process_macros_and_load( load_addr, ulp_blink, &size);
  ulp_run( load_addr );
} // void ULP_BLINK_RUN(uint32_t us)
//////////////////////////////////////////////

what kind of requirement have to install?
library?

Requirement? What does that mean?