0

I am using the ESP32 for a simple project. I know how to animate an led strip using atmega328p with arduino but when I animate it on the ESP32 it does not work that great. It will be nice if I can use the same ESP32 to run my entire project without having to include another MCU. Has someone managed to be able to animate an led strip meanwhile using wifi on the ESP32 ?

This is the code I use to animate an LED stip meanwhile using wifi. I wrote this code myself so maybe I am doing something wrong. It works better than any of the libraries I have found online. The library that works best is esp32WS2811-master. But still this code works better than that library in my case.

#include <Arduino.h>
#include "WiFi.h"
#include <Adafruit_NeoPixel.h>

// we will runt the task that animates led strip on a separate core of arduino
TaskHandle_t Task1;

// where led pin is connected and number of leds to animate
#define PIN 32
#define NUM_LEDS 80

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

// mutex that helps enter critical sections meanwhile we animate led strip
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;


// it will run on core 0 of esp32. Responsible for animating led strip.
void loop2(void *parameter)
{
   uint32_t _color = strip.Color(0, 0, 0);

   for (;;) // infinite loop
   {
      _color = strip.Color(0, 0, 255);

      // animation 1
      for (uint16_t i = 0; i < strip.numPixels(); i++)
      {                                  
         strip.setPixelColor(i, _color); 

         //portDISABLE_INTERRUPTS();      // arternative to portENTER_CRITICAL
         portENTER_CRITICAL(&mux);        /* start critical section */

         strip.show();

         //portENABLE_INTERRUPTS();       // alternative to portEXIT_CRITICAL
         portEXIT_CRITICAL(&mux);         /* end critical section */

         vTaskDelay(15);                  // one tick delay (15ms) in between reads for stability
      }

     
      // animation 2
      _color = strip.Color(0, 255, 0);
      for (uint16_t i = 0; i < strip.numPixels(); i++)
      {                                   
         strip.setPixelColor(i, _color);  

         //portDISABLE_INTERRUPTS();      // arternative to portENTER_CRITICAL
         portENTER_CRITICAL(&mux);        /* start critical section */

         strip.show();

         //portENABLE_INTERRUPTS();       // alternative to portEXIT_CRITICAL
         portEXIT_CRITICAL(&mux);         /* end critical section */

         vTaskDelay(15);                  // one tick delay (15ms) in between reads for stability
      }
   }
}

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

   // disabling wifi helps but we need it
   // WiFi.mode(WIFI_OFF);

   // init led strip
   strip.begin();
   strip.setBrightness(4);
   strip.show(); // Initialize all pixels to 'off'

   // create a task that runs on core 0 of esp32
   xTaskCreatePinnedToCore(
       loop2,
       "Task_1",
       1000,
       NULL,
       2, // priority of 0 is the lowest.
       &Task1,
       0 // use core 0. Core 1 is the default core
   );

   // continue running code on default core 1 of esp32

   // Set WiFi to station mode and disconnect from an AP if it was previously connected
   WiFi.mode(WIFI_STA);
   WiFi.disconnect();
   
   Serial.println("Setup done");
}

// on main loop scan network just to show how led strip does not work great when wifi is in use
// This code I copied and pasted from the WiFi examples of the esp32
void loop()
{
   Serial.println("scan start");

   // WiFi.scanNetworks will return the number of networks found
   int n = WiFi.scanNetworks();
   Serial.println("scan done");
   if (n == 0)
   {
      Serial.println("no networks found");
   }
   else
   {
      Serial.print(n);
      Serial.println(" networks found");
      for (int i = 0; i < n; ++i)
      {
         // Print SSID and RSSI for each network found
         Serial.print(i + 1);
         Serial.print(": ");
         Serial.print(WiFi.SSID(i));
         Serial.print(" (");
         Serial.print(WiFi.RSSI(i));
         Serial.print(")");
         Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
         delay(10);
      }
   }
   Serial.println("");           

   // wait 5 seconds for next network scan
   auto end = millis() + (unsigned long)5000;
   while(millis() < end)  {
      vTaskDelay(1);
   }

}

When I run this code the first led flickers. The other LEDs animate great 99.99% of the time. When I disable WiFi this code works great. I still need portENTER_CRITICAL(&mux); or portDISABLE_INTERRUPTS(); for it to work even if I disable WiFi. Has anyone managed to be able to animate an led-strip with the ESP-32 successfully meanwhile using WiFi?

If I am required to use a separate micro controller which one do you guys recommend? The ATtiny85?

6
  • it's not the wifi, it's your delay calls and while statements that are stopping the show.
    – dandavis
    Aug 17, 2020 at 18:02
  • The delay is part of the animation. If I disable the wifi the animation works great @dandavis. I need to animate one led every 15 milliseconds.
    – Tono Nam
    Aug 17, 2020 at 19:25
  • well, I know that i can push rgb values over wifi to an esp32 at 30FPS on a 64 pixel strip. If wifi blocked this would look really jerky, but it doesn't, except for occasional hiccups which fix themselves. I didn't even mess with interrupts or explicit flow control. Make your animation routine async (think blink w/o delay) to allow more than one thing at once to happen. For me, this required rewriting the adafruit lib to move the loops into stand-alone callable functions that did a single iteration worth of work at the right time, as determined by the loop()'s logic and millis().
    – dandavis
    Aug 17, 2020 at 19:29
  • 1
    Doesn't all the WiFi management software run on core 0? If you run on core 1 does it improve?
    – Majenko
    Aug 17, 2020 at 21:11
  • @danvis are you using an addressable led strip? are you animating your LED by changing the color of one led at a time? If I use a none addressable led strip it works.
    – Tono Nam
    Aug 17, 2020 at 21:35

1 Answer 1

0

I used the FastLed library and it works now. For some reason the adafruit library only works when I am not using the WiFi. This code works:

#include "Arduino.h"
#include <FastLED.h>
#include "WiFi.h"

// we will runt the task that animates led strip on a separate core of arduino
TaskHandle_t Task1;

#define LED_PIN 32
#define NUM_LEDS 108
#define BRIGHTNESS 10
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100



// scan the network every 5 seconds 
void loop2(void *parameter)
{
    for (;;)
    {
        Serial.println("scan start");

        // WiFi.scanNetworks will return the number of networks found
        int n = WiFi.scanNetworks();
        Serial.println("scan done");
        if (n == 0)
        {
            Serial.println("no networks found");
        }
        else
        {
            Serial.print(n);
            Serial.println(" networks found");
            for (int i = 0; i < n; ++i)
            {
                // Print SSID and RSSI for each network found
                Serial.print(i + 1);
                Serial.print(": ");
                Serial.print(WiFi.SSID(i));
                Serial.print(" (");
                Serial.print(WiFi.RSSI(i));
                Serial.print(")");
                Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
                delay(10);
            }
        }
        Serial.println("");

        vTaskDelay(5000);
    }
}



void setup()
{

    Serial.begin(115200);

    delay(1000); // power-up safety delay
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
    FastLED.setBrightness(BRIGHTNESS);


    // Set WiFi to station mode and disconnect from an AP if it was previously connected
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();

    // create a task that runs on core 0 of esp32
    xTaskCreatePinnedToCore(
        loop2,
        "Task_1",
        1000,
        NULL,
        2, // priority of 0 is the lowest.
        &Task1,
        1 // use core 0. Core 1 is the default core
    );

    Serial.println("Setup done");
}


void loop()
{

    // red
    for (int i = 0; i < NUM_LEDS; i++)
    {
        leds[i] = 0xFF0000;
        FastLED.show();
        FastLED.delay(25);
    }

    // green
    for (int i = 0; i < NUM_LEDS; i++)
    {
        leds[i] = 0x00FF00;
        FastLED.show();
        FastLED.delay(25);
    }

    // blue
    for (int i = 0; i < NUM_LEDS; i++)
    {
        leds[i] = 0x0000FF;
        FastLED.show();
        FastLED.delay(25);
    }

    // rgb red green blue

    //ChangePalettePeriodically();
    //FillLEDsFromPaletteColors( startIndex);
}
1
  • Please accept your own answer so it doesn't pop up over and over again
    – Sim Son
    Aug 19, 2020 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.