ESP32 reboots with 8x32 WS2812 matrix when sharing power source

My project is a modified version of Scott Marley’s excellent 16x16 FFT vu meter.

Here’s my wiring diagram:

Here’s my code:

#include <arduinoFFT.h>
#include <FastLED.h>
#include <FastLED_NeoMatrix.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
//#include <EEPROM.h>

#define SAMPLES         256          // Must be a power of 2
#define SAMPLING_FREQ   20000         // Hz, must be 40000 or less due to ADC conversion time. Determines maximum frequency that can be analysed by the FFT Fmax=sampleF/2.

#define AUDIO_IN_PIN    35            // Signal in on this pin
#define LED_PIN         2             // LED strip data
#define COLOR_ORDER     GRB           // If colours look wrong, play with this
#define CHIPSET         WS2812B       // LED strip type
#define MAX_MILLIAMPS   2000          // Careful with the amount of power here if running off USB port

#define LED_VOLTS       5             // Usually 5 or 12
#define NUM_BANDS       32            // To change this, you will need to change the bunch of if statements describing the mapping from bins to bands
#define NOISE           400           // Used as a crude noise filter, values below this are ignored

const uint8_t kMatrixWidth = 32;                          // Matrix width
const uint8_t kMatrixHeight = 8;                         // Matrix height

#define MATRIX_TILE_H       1
#define MATRIX_TILE_V       1

#define NUM_LEDS       (kMatrixWidth * kMatrixHeight * MATRIX_TILE_H * MATRIX_TILE_V)   // Total number of LEDs
#define BAR_WIDTH      (kMatrixWidth * MATRIX_TILE_H / (NUM_BANDS - 1))  // If width >= 8 light 1 LED width per bar, >= 16 light 2 LEDs width bar etc
#define TOP            (kMatrixHeight)                // Don't allow the bars to go offscreen

#define SQUARE_LENGTH   (kMatrixHeight / 2)

uint8_t gHue = 0; // rotating "base color" used by many of the patterns

CRGB leds[NUM_LEDS];

FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, kMatrixWidth * MATRIX_TILE_H, kMatrixHeight,
  NEO_MATRIX_TOP        + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS       + NEO_MATRIX_ZIGZAG +
  NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS + NEO_TILE_PROGRESSIVE);

//AUDIO SAMPLING
unsigned int sampling_period_us;
int oldBarHeights[NUM_BANDS];
int oldSquareLevels[16];
int bandValues[NUM_BANDS];
double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned long newTime;

arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);

//BLUETOOTH
/*#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>

#define BLYNK_USE_DIRECT_CONNECT*/

//WIFI
char auth[] = "blah"
char ssid[] = "blah";
char pass[] = "blah";

//BLYNK PARAMS
boolean showGlitter = false;
boolean paintRainbow = true;
boolean flip = false;
boolean invert = false;
byte patternNumber = 0;
byte brightness = 50;
int amp =       400;

void setup() {

  Serial.begin(115200);

  FastLED.addLeds<CHIPSET, LED_PIN,  COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
  FastLED.setMaxPowerInVoltsAndMilliamps(LED_VOLTS, MAX_MILLIAMPS);
  FastLED.setBrightness(brightness);
  FastLED.clear();
  FastLED.show();
  delay(3000);
  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQ));

  //WIFI
  Blynk.begin(auth, ssid, pass);
  
}

void loop() {

  int t1 = millis();
  
  processAudio();

  int t2 = millis();
  
  paintLEDs();

  int t3 = millis();
  
}

void paintLEDs(){
  
  if(patternNumber != 2 && patternNumber != 3){
    FastLED.clear();
  }

  int AMPLITUDE = amp;

  if(patternNumber == 0){
    
    for (byte band = 0; band < NUM_BANDS; band++) {
  
      // Scale the bars for the display
      int barHeight = bandValues[band] / AMPLITUDE;

      if (barHeight > TOP) barHeight = TOP;
      // Small amount of averaging between frames      

      double avBarHeight = ((double)oldBarHeights[band] + (double) barHeight) / 2;
      
      if(oldBarHeights[band] > 1){
        barHeight = ceil(avBarHeight); // round up to get top bar height
      }
      
      drawBar(band, barHeight);
      
      oldBarHeights[band] = barHeight;
    }
  }
  else if (patternNumber == 1){
    for (byte i = 0; i < 16; i++){
      drawSquare(i);
    }
  }
  else if (patternNumber == 2){
    for (byte band = 0; band < NUM_BANDS; band++) {
      drawRain(band);
    }
  }
  /*else if (patternNumber == 3){
    for (byte band = 0; band < NUM_BANDS; band++) {
      drawPulse(band);
    }
  }*/

  if(showGlitter){
    addGlitter(80);
  }

  FastLED.show();

  EVERY_N_MILLISECONDS( 200 ) { gHue++; }

  Blynk.run();
  
}

void processAudio(){

  for (int i = 0; i<NUM_BANDS; i++){
    bandValues[i] = 0;
  }

  // Sample the audio pin
  for (int i = 0; i < SAMPLES; i++) {
    newTime = micros();
    vReal[i] = analogRead(AUDIO_IN_PIN); // A conversion takes about 9.7uS on an ESP32
    vImag[i] = 0;
    //while ((micros() - newTime) < sampling_period_us) { /* chill */ }
  }

  // Compute FFT
  FFT.DCRemoval();
  FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(FFT_FORWARD);
  FFT.ComplexToMagnitude();
  
  // Analyse FFT results
  for (int i = 1; i < (SAMPLES/2); i++){       // Don't use sample 0 and only first SAMPLES/2 are usable. Each array element represents a frequency bin and its value the amplitude.    
    if (vReal[i] > NOISE) {                    // Add a crude noise filter
    //16 bands, 12kHz top band
      if (i==2 )           bandValues[0]  += (int)vReal[i];
      if (i==3  ) bandValues[1]  += (int)vReal[i];
      if (i==4  ) bandValues[2]  += (int)vReal[i];
      if (i==5  ) bandValues[3]  += (int)vReal[i];
      if (i==6  ) bandValues[4]  += (int)vReal[i];
      if (i==7 ) bandValues[5]  += (int)vReal[i];
      if (i==8) bandValues[6]  += (int)vReal[i];
      if (i==9 ) bandValues[7]  += (int)vReal[i];
      if (i==10 ) bandValues[8]  += (int)vReal[i];
      if (i==11 ) bandValues[9]  += (int)vReal[i];
      if (i==12 ) bandValues[10]  += (int)vReal[i];
      if (i==13 ) bandValues[11]  += (int)vReal[i];
      if (i==14 ) bandValues[12]  += (int)vReal[i];
      if (i==15 ) bandValues[13]  += (int)vReal[i];
      if (i==16 ) bandValues[14]  += (int)vReal[i];
      if (i==17 ) bandValues[15]  += (int)vReal[i];
      if (i==18 ) bandValues[16]  += (int)vReal[i];
      if (i>18 && i <=20 ) bandValues[17]  += (int)vReal[i];
      if (i>20 && i <=24 ) bandValues[18]  += (int)vReal[i];
      if (i>24 && i <=29 ) bandValues[19]  += (int)vReal[i];
      if (i>29 && i <=34 ) bandValues[20]  += (int)vReal[i];
      if (i>34 && i <=41 ) bandValues[21]  += (int)vReal[i];
      if (i>41 && i <=48 ) bandValues[22]  += (int)vReal[i];
      if (i>48 && i <=57 ) bandValues[23]  += (int)vReal[i];
      if (i>57 && i <=68 ) bandValues[24]  += (int)vReal[i];
      if (i>68 && i <=80 ) bandValues[25]  += (int)vReal[i];
      if (i>80 && i <=95 ) bandValues[26]  += (int)vReal[i];
      if (i>95 && i <=113 ) bandValues[27]  += (int)vReal[i];
      if (i>113 && i <=134 ) bandValues[28]  += (int)vReal[i];
      if (i>134 && i <=159 ) bandValues[29]  += (int)vReal[i];
      if (i>159 && i <=189 ) bandValues[30]  += (int)vReal[i];
      if (i>189 && i <=224 ) bandValues[31]  += (int)vReal[i];
      
    }
  }
}

/*void drawPulse(int band){

  int value = bandValues[band];

  byte x = random8(0,31);
  byte y = random8(0,7);

  if(paintRainbow){
    matrix-> drawPixel(x, y, CHSV(band * (255 / 32) + gHue, 255, value));
  }
  else{
    matrix-> drawPixel(x, y, CHSV(band * 2 + gHue, 255, value));
  }

  int centrePixel = matrix->XY(x, y);
  int topPixel = matrix->XY(x, y+1);
  int bottomPixel = matrix->XY(x, y-1);
  int rightPixel = matrix->XY(x+1, y);
  int leftPixel = matrix->XY(x-1, y);

  leds[topPixel] = leds[centrePixel] + leds[topPixel];
  leds[bottomPixel] = leds[centrePixel] + leds[bottomPixel];
  leds[rightPixel] = leds[centrePixel] + leds[rightPixel];
  leds[leftPixel] = leds[centrePixel] + leds[leftPixel];

  leds[centrePixel].fadeToBlackBy(150);
  leds[topPixel].fadeToBlackBy(150);
  leds[bottomPixel].fadeToBlackBy(150);
  leds[rightPixel].fadeToBlackBy(150);
  leds[leftPixel].fadeToBlackBy(150);
  
}*/

void drawSquare(byte pos){

  byte n = pos*2;
      
  int level = (oldSquareLevels[pos] + (bandValues[n] + bandValues[n+1]) / 2) / 2;

  level = level / (amp/50);

  if (level > 255) level = 255;
  
  double avLevel = ((double)oldSquareLevels[pos] + (double) level) / 2;
      
  if(level > 0){
    level = ceil(avLevel); // round up to get top bar height
  }

  oldSquareLevels[pos] = level;
  
  byte xStart = (pos / 2) * 4; //multiply quotient

  byte yStart = (pos % 2) * 4;

  for (int x = xStart; x < xStart + SQUARE_LENGTH; x++){
    for (int y = yStart; y < yStart + SQUARE_LENGTH; y++){
      if(invert){
        matrix-> drawPixel(x, y, CHSV(pos * (255 / 16) + gHue, 255, 255-level));
      }
      else{
        matrix-> drawPixel(x, y, CHSV(pos * (255 / 16) + gHue, 255, level));
      }
    }
  }
}

void drawBar(int band, int barHeight) {
  
  int xStart = BAR_WIDTH * band;
  
  for (int x = xStart; x < xStart + BAR_WIDTH; x++) {

    if(flip && !invert){
      for (int y = TOP; y >= TOP-barHeight; y--) {
        if(barHeight > 0) draw(x,y);
      }
    }
    
    else if(flip && invert){
      for (int y = TOP; y >= barHeight; y--) {
        draw(x,y);
      }
    }
    
    else if(!flip && invert){
      for (int y = 0; y <= TOP-barHeight; y++) {
        draw(x,y);
      }
    }
    
    else{
      for (int y = 0; y < barHeight; y++) {
        if(barHeight > 0) draw(x,y);
      }
    } 
  }
}

void drawRain(int band){

  int value = bandValues[band];

  if(paintRainbow){
    matrix-> drawPixel(band, kMatrixHeight-1, CHSV(band * (255 / 32) + gHue, 255, value));
  }
  else{
    matrix-> drawPixel(band, kMatrixHeight-1, CHSV(band * 2 + gHue, 255, value));
  }

  if (band == NUM_BANDS - 1){
    //EVERY_N_MILLISECONDS (50){
      for (int y = 0; y < kMatrixHeight-1; y++) {
        for (int x = 0; x < kMatrixWidth; x++) {
          int newPixelIndex = matrix->XY(x, y);
          int oldPixelIndex = matrix->XY(x, y + 1);
          leds[newPixelIndex] = leds[oldPixelIndex];
          leds[newPixelIndex].nscale8(180);
          if(leds[newPixelIndex].getAverageLight() < 5){
            leds[newPixelIndex] = CRGB::Black;
          }
        }
      }
    //}
  }
}

void draw(int x, int y){
  if(paintRainbow){
    matrix-> drawPixel(x, y, CHSV((x / BAR_WIDTH) * (255 / NUM_BANDS) + gHue, 255, 255));
  }
  else{
    matrix-> drawPixel(x, y, CHSV(gHue+(x+y), 255, 255));
  }
}

void addGlitter(fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

BLYNK_WRITE(V0)
{
  brightness = param.asInt();
  FastLED.setBrightness(brightness);
}

BLYNK_WRITE(V1)
{
  showGlitter = param.asInt();
}

BLYNK_WRITE(V2)
{
  paintRainbow = param.asInt();
}

BLYNK_WRITE(V3)
{
  patternNumber = param.asInt();
}

BLYNK_WRITE(V4)
{
  amp = param.asInt();
}

BLYNK_WRITE(V5)
{
  flip = param.asInt();
}

BLYNK_WRITE(V6)
{
  invert = param.asInt();
}

256 * 60mA = 15A.
You need a power supply of 15A, when all the leds are full white.

You could start by setting the overall brightness to 10 or so.
The FastLED library can set the maximum current, which adapts the brightness runtime.

The 5V ledstrips prefer a 5V signal. You can use a single Neopixel for that or use a transistor. If the leds don’t turn on very well or the pattern is weird, keep in mind that the signal level might be too low.

Could you edit your post and put three backslash-single-quotes on a line before the code and three after the code ?

Such as this:

```
Your sketch
```

Thanks Koepel for the fast reponse! Good tip r.e. code mark-up. Addressed that above.

R.e. current : I use FastLED code to limit current. In the code it’s set at 2A, but previously I had that at 10A and the problem I describe exists in both cases. My power supply is usually 10A, but I also have a 60A supply and the problem persists then, too. The LEDs turn on fine and the pattern is not weird. Any clue why the ESP32 might re-boot if LEDs and ESP32 are powered by same supply vs separate supply?

I have a ESP32 running a LED strip of 240 LED’s.

I got a single supply of 9V. I have 2 regulators. One regulator drops the 9 volts down to 5 to supply the LED strip. The other regulator just supplies the ESP32. Kind of isolating the LED power from the MCU power.

Thank you sir! Other than dropping voltage to 5V, what purpose are they serving, if any? Trying to understand if / why / how a regulator could help my issue…

Just for a try:
take 2 Power - supplies, one for your ESP-board, the other for the LED - Matrix. Make only 1 connection between both Suppies on the “-” (Ground) Level.

1 Like

Isolation.

Got it. Thank you! I’ll definitely try and give that a go. Any recommendations on regulator type? I’m a total newbie and learning as I go :slight_smile:

One other follow-up… any theories on what might be causing the reboot? Irregular voltage to the ESP?

Correction: if I use the 60A supply and use separate terminals for ESP and LEDs, I don’t get the issue.

What could happen:
In switching on - moment, the LED takes a high peak of current - the voltage drops below the working - voltage of the ESP and this causes a reboot.
During booting, the Outputs of the ESP go to indefinite state - this causes the LED (contollers inside) to reinitialize the LED and all of them do the same as above described - each takes the needed current for reinitialize and the voltage drops again… and again … and again …

Right I see. So I might be getting voltage drop on ESP… If I put regulator in between power source and esp, when there is a sharp rise in current draw from power source for the LEDs, how does regulator help protect voltage drop? I guess I need to do some Googling :slight_smile: Any recommendations on what voltage regulator to buy? I did some searching but found it utterly bewildering!

There are generally 2 possibilities: a) A 2nd voltage source, which is independent of the first voltage source and is only connected via ground line or b) A current buffer for the ESP, which is decoupled from the main supply. This buffer can be created from a small circuit. Principle: Supply 5.xV - Diode (Germanium) - Capacitor against Ground // VCC of the ESP

More useful insights. Thank you! A friend of mine thought these might do the trick: 5 Pcs 3 Terminals 1.5A 5V L7805CV Postive Voltage Regulators https://www.amazon.co.uk/dp/B00EZ89A54/ref=cm_sw_r_cp_api_glt_fabc_0K8GA4BAB8DBPAE6FXYC

They’re arriving soon so will give them a try and see what happens!