NeoPixel Arrays makes my ESP32 reboot ! Why?

Viewed 72

I'm triing to replace five "Adafruit_NeoPixel" objets by an array of 5 objects?. In other words, thansform this :

Adafruit_NeoPixel strips_0 (LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strips_1 (LED_COUNT, LED_PIN_1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strips_2 (LED_COUNT, LED_PIN_2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strips_3 (LED_COUNT, LED_PIN_3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strips_4 (LED_COUNT, LED_PIN_4, NEO_GRB + NEO_KHZ800);

into this:

Adafruit_NeoPixel strips[]
{
  (LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_1, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_2, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_3, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_4, NEO_GRB + NEO_KHZ800)
};

Then of course, i have modified:

strips_0.begin();
strips_0.show();
(...)

by:

strips[0].begin();
strips[0].show();
(...)

(so far so good ?)

The problem occurs in the main loop:

I have replaced this (which worked well)

for(int i=0; i <60 ; i++)
{
  strips_0.setPixelColor (i,colors[0]);
  strips_0.show();

  strips_1.setPixelColor (i,colors[0]);
  strips_1.show();

  strips_2.setPixelColor (i,colors[0]);
  strips_2.show();

  strips_3.setPixelColor (i,colors[0]);
  strips_3.show();

  strips_4.setPixelColor (i,colors[0]);
  strips_4.show();

  delay(20);
  shiftFirstNumbers(1); // modifies the value of colors[0]
}

by this (which does not work anymore):

for(int i=0; i <60 ; i++)
 {   for(int j = 0;j<=4;j++)
   {
   strips[j].setPixelColor (i,colors[0]);   strips[j].show();
   }
  delay(20);   shiftFirstNumbers(1);
 }

This make the ESP32 reboot (and reboot)

here is waht I can see in the console

99
Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x800de840  PS      : 0x00060a30  A0      : 0x800de840  A1      : 0x3ffb1ee0  
A2      : 0x00000007  A3      : 0x00000000  A4      : 0x00000000  A5      : 0x00000000  
A6      : 0x3ff56000  A7      : 0x00000000  A8      : 0x3ffc4348  A9      : 0x3ffb1ec0  
A10     : 0x3ffbb208  A11     : 0x40085474  A12     : 0x00000006  A13     : 0x00000001  
A14     : 0x00060420  A15     : 0x00000000  SAR     : 0x0000001a  EXCCAUSE: 0x00000014  
EXCVADDR: 0x800de840  LBEG    : 0x400de7ed  LEND    : 0x400de7fe  LCOUNT  : 0x00000000  

Backtrace: 0x400de840:0x3ffb1ee0 0x400de83d:0x3ffb1f10 0x400de658:0x3ffb1f70 0x400d1d74:0x3ffb1f90 0x400e0c3d:0x3ffb1fb0 0x40089c61:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac

(99 is a Serial.print(99) at the beginnind of the loop)

Any idea what's wrong with my code ? Sorry i'm a newbie in C++, I hope you can help !

regards

1 Answers

Good question. C-style arrays mixed with C++ objects are tricky as hell. The syntax you've used here doesn't call the constructor for the class Adafruit_NeoPixel with the three arguments you've specified:

Adafruit_NeoPixel strips[] {
  (LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_1, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_2, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_3, NEO_GRB + NEO_KHZ800),
  (LED_COUNT, LED_PIN_4, NEO_GRB + NEO_KHZ800)
};

Correct way to create a C array of C++ objects is either this (note the curly braces which enforce initialization and invocation of the constructor):

Adafruit_NeoPixel strips[] {
  {LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800},
  {LED_COUNT, LED_PIN_1, NEO_GRB + NEO_KHZ800},
  {LED_COUNT, LED_PIN_2, NEO_GRB + NEO_KHZ800},
  {LED_COUNT, LED_PIN_3, NEO_GRB + NEO_KHZ800},
  {LED_COUNT, LED_PIN_4, NEO_GRB + NEO_KHZ800}
};

or this (constructor called explicitly):

Adafruit_NeoPixel strips[] {
  Adafruit_NeoPixel(LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(LED_COUNT, LED_PIN_1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(LED_COUNT, LED_PIN_2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(LED_COUNT, LED_PIN_3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(LED_COUNT, LED_PIN_4, NEO_GRB + NEO_KHZ800)
};


If you are interested in the root of your problems, it's the expression (LED_COUNT, LED_PIN_0, NEO_GRB + NEO_KHZ800). This gets treated as a comma operator which evaluates all comma separated statements sequentially and returns the value from the last one. So your Adafruit_NeoPixel class got constructed by calling Adafruit_NeoPixel(NEO_GRB + NEO_KHZ800) which probably breaks something important inside it.

Consider this snippet of code:

#include <iostream>

class Foo {
public:
    Foo(int m, int n = -1): _m(m), _n(n) {}
    int _m, _n;
};

int main() {
    Foo farr[] {
        (1, 2), 
        {3, 4}
    };
    for (int i = 0; i < 2; i++) {
        printf("%d %d\n", farr[i]._m, farr[i]._n);
    }
}

You'd expect it to print out

1 2
3 4

But it doesn't. Instead it prints out

2 -1
3 4

That's because the first object effectively got constructed with Foo(2)

Related