Esp32 ws2812 with timer (not delay) show() -> reset

Hello,
I discover esp32, ntp, ws2812.
I find a sketch working fine, but it use delay(1000).
Now I want blink color when sec or min or hour have same pixel.
I tryed with timer.
It work fine about Serial.print("information");
But when I use show() with timer esp32 reset.
What is wrong ?
This is my code

String compilation = "Compiled: " __DATE__ ", " __TIME__ ", " __VERSION__;
String nom_fichier = __FILE__ ;

#include <Adafruit_NeoPixel.h>
#define LED_PIN   15 
#define LED_COUNT 60 
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

#include <WiFi.h>
const char* ssid      = "ssid";
const char* password  = "password";
const char* ntpServer = "fr.pool.ntp.org"; 

struct tm mytime;
hw_timer_t *My_timer = NULL;

byte locsec = 99;
byte sequen = 88;

//###############################################################################
void verif_ws2812()
{ Serial.println("init ws2812");
  uint led_color[] = { 0 ,strip.Color(255,   0,   0),strip.Color(  0, 255,   0),strip.Color(255, 255, 255), 0 };
  strip.fill(0,0,strip.numPixels());
  strip.show();
  strip.setBrightness(10);
  for(byte i = 0; i<5;i++)
  { strip.fill( led_color[i], 0 ,strip.numPixels());
    strip.show(); delay(500);
  }
}
//############################################################################ 
void IRAM_ATTR onTimer()
{/**/
  Serial.println("########################### IRAM_ATTR onTimer() ");
  if(!getLocalTime(&mytime))
  {  Serial.println("Could not obtain time info - IRAM_ATTR "); 
     return;
  }
  if(locsec != mytime.tm_sec)
  { 
    Serial.println("  - - - - - - - - -  ");
    Serial.println(asctime(&mytime));
    locsec = mytime.tm_sec ;
    sequen = 0;
 }
  Serial.println(" o o o o o o o o o o ");
  Serial.print(&mytime, "%A %d %B %Y %H:%M:%S | ");
  Serial.println(sequen++) ;
  
    Serial.println(" 0-0-0-0-0-0-0-0-0-0 ");
    Serial.println(asctime(&mytime));
    strip.setPixelColor(locsec, strip.Color(0, 0, 0));
    locsec = mytime.tm_sec ;
    strip.setPixelColor(locsec, strip.Color(0, 0, 255));
 Serial.println("########################### IRAM_ATTR onTimer() - before strip.show() ");
    strip.show();
    Serial.println("########################### IRAM_ATTR onTimer() - after strip.show() ");
  
  }
////////////////////////////////////////////////////////////////////////////// 
void setup()
{
  Serial.begin(115200);
  Serial.println(compilation);
  Serial.println(nom_fichier);
  strip.begin();
  verif_ws2812(); // strip.show() in this function work fine at this time
  WiFi.begin(ssid, password);
  Serial.print("Connecting...");
  while (WiFi.status() != WL_CONNECTED) 
  {   delay(500);
      Serial.print("...");
  }
  Serial.print("\nConnected with success ");
  Serial.print("IP locale : ");
  Serial.println(WiFi.localIP());


  My_timer = timerBegin(1, 80, true);
  timerAttachInterrupt(My_timer, &onTimer, true);
  timerAlarmWrite(My_timer, 333000, true);
  timerAlarmEnable(My_timer); 

  configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer); // summer time for France
}
////////////////////////////////////////////////////////////////////////////// 
void loop()
{ // here strip.show() work fine with delay(1000), but I want use timer
}

and this is serial monitor

Compiled: Sep 23 2022, 14:32:28, 5.2.0
file path an name.ino
init ws2812
Connecting...........................
Connected with success IP locale : 190.123.0.120
########################### IRAM_ATTR onTimer() 
  - - - - - - - - -  
Fri Sep 23 11:43:58 2022

 o o o o o o o o o o 
Friday 23 September 2022 11:43:58 | 0
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 11:43:58 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
abort() was called at PC 0x400873d1 on core 1

ELF file SHA256: 0000000000000000

Backtrace: 0x40088f9c:0x3ffbfd30 0x40089219:0x3ffbfd50 0x400873d1:0x3ffbfd70 0x400874fd:0x3ffbfda0 0x40130ba6:0x3ffbfdc0 0x400d0706:0x3ffbfdf0 0x400d091d:0x3ffbfe50 0x400811a6:0x3ffbfe70 0x400814f5:0x3ffbfe90 0x400878e5:0x3ffbfeb0 0x400d1e0d:0x3ffb1fb0 0x4008acde:0x3ffb1fd0

Rebooting...
Compiled: Sep 23 2022, 14:32:28, 5.2.0
file path an name.ino
init ws2812
Connecting...........................
Connected with success IP locale : 190.123.0.120
########################### IRAM_ATTR onTimer() 
  - - - - - - - - -  
Fri Sep 23 11:44:05 2022

 o o o o o o o o o o 
Friday 23 September 2022 11:44:05 | 0
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 11:44:05 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
abort() was called at PC 0x400873d1 on core 1

ELF file SHA256: 0000000000000000

Backtrace: 0x40088f9c:0x3ffbfd30 0x40089219:0x3ffbfd50 0x400873d1:0x3ffbfd70 0x400874fd:0x3ffbfda0 0x40130ba6:0x3ffbfdc0 0x400d0706:0x3ffbfdf0 0x400d091d:0x3ffbfe50 0x400811a6:0x3ffbfe70 0x400814f5:0x3ffbfe90 0x400878e5:0x3ffbfeb0 0x400d1e04:0x3ffb1fb0 0x4008acde:0x3ffb1fd0

Rebooting...

but I comment strip.show() in timer function

  Serial.println("########################### IRAM_ATTR onTimer() - before strip.show() ");
    // strip.show();
    Serial.println("########################### IRAM_ATTR onTimer() - after strip.show() ");

sketch work fine ...

this is serial monitor


Compiled: Sep 23 2022, 14:37:12, 5.2.0
file path an name.ino
init ws2812
Connecting...........................
Connected with success IP locale : 190.123.0.120

########################### IRAM_ATTR onTimer() 
  - - - - - - - - -  
Fri Sep 23 14:38:40 2022

 o o o o o o o o o o 
Friday 23 September 2022 14:38:40 | 0
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:40 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 
########################### IRAM_ATTR onTimer() 
 o o o o o o o o o o 
Friday 23 September 2022 14:38:40 | 1
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:40 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 
########################### IRAM_ATTR onTimer() 
 o o o o o o o o o o 
Friday 23 September 2022 14:38:40 | 2
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:40 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 
########################### IRAM_ATTR onTimer() 
  - - - - - - - - -  
Fri Sep 23 14:38:41 2022

 o o o o o o o o o o 
Friday 23 September 2022 14:38:41 | 0
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:41 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 
########################### IRAM_ATTR onTimer() 
 o o o o o o o o o o 
Friday 23 September 2022 14:38:41 | 1
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:41 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 
########################### IRAM_ATTR onTimer() 
 o o o o o o o o o o 
Friday 23 September 2022 14:38:41 | 2
 0-0-0-0-0-0-0-0-0-0 
Fri Sep 23 14:38:41 2022

########################### IRAM_ATTR onTimer() - before strip.show() 
########################### IRAM_ATTR onTimer() - after strip.show() 


Thank you for yours answers.

PS: I do not want use millis() because bug after 47 days.

You were deceived, with the correct use of millis, there is no bug after 47 days

I want understand why I have an error in my code.
Esp32 have 4 timers, I hope use theese for other actions (button, ota, wifi client if new ssid, etc)
I think it can be more difficult with millis().

But I can try millis() if you explain me or give me a link what is the right way.

Is your power supply sufficient?
These ledstrips can take large currents.
A power dip will reset your controller...

power is good 10A
this sketch does not works also when ws2812 is unplugged

You can't use interrupt based functions inside the other interrupt. So you shouldn't use a Serial and WS2812 functions in the irq

In general, you absolutely do not understand the meaning of interrupts. They are designed to accurately perform short actions, literally in 2-3 lines of code - and not to pack the entire program into them.
What you want can and should be done through millis, and not through interrupts

1 Like

where is variable sec is defined?

I am sorry, I made mistake when I copy/paste my source code.
I just edited now my first post and change that.
I replace sec by locsec.
I have not useful with this forum.

I do not understand what you explain me, sorry.

You are right !
I want progress and stop use delay().

show() for 60 leds is less than 20ms and timer is 33ms.
My_timer = timerBegin(1, 80, true); // 1.000.000 = 1sec
timerAlarmWrite(My_timer, 333.000, true); // = 33ms

Serial.print in void IRAM_ATTR onTimer() is for me helping understand where is problem.

It's 49 days... and it's not a bug.

May be you edited your code, but the question still the same - where the variable sec defined?

Please show exactly the same code that you run. The code that you posted shouldn't compile.

The exact number of days ( 49.71 days) when millis() is overflow and restart at 0 is not really the problem.

PS : solution for millis overflow

Serial uses interrupts.
You should not use interrupts inside an interrupt.
So no Serial in interrupt.

Interrupts should be short. They should set a flag or something. Like:

SomethingHasHappened = True;

Then in your main loop, you do what is needed when that something has happened and you clear the flag...

@mybrain_iq55 If the code uses millis() incorrectly, there is a bug.

If the code uses millis() correctly, there is no bug.

The bug is not inside millis(). It is in the code you copy from another sketch. If you copy the code from a good sketch, there will be no bug. If you copy from a bad sketch ...

of course !
Problem for beginner as me, is "we can't know if it is good or bad" !

it is not sec but locsec, I am sorry for error when copy and paste.

in

    strip.setPixelColor(locsec, strip.Color(0, 0, 0));  // I return black led old seconde on clock
    locsec = mytime.tm_sec ;  // I define new value for seconde on clock
    strip.setPixelColor(locsec, strip.Color(0, 0, 255));  // I define color for new led seconde on clock
     strip.show(); // I send new data on ws2812

No problem. Post the code here. We can tell you good or bad in 1ms.

Ok, maybe slightly longer than 1ms...

And always remember that the 32 bit floating point registers are not saved for the ISR.

String compilation = "Compiled: " __DATE__ ", " __TIME__ ", " __VERSION__;
  String nom_fichier = __FILE__ ;
// affichage de l'heure sur ws2812 ruban led
/* compilation avec carte esp32 dev module
// IMPORTANT BEFORE TO DOWNLOAD SKETCH !!!
//   - Board: ESP32 Dev Module
//   - Flash Mode: QIO
//   - Flash Frequency: 80Mhz
//   - CPU Frequency: 240Mhz (WiFi/BT)
//   - Flash Size: 4MB (32Mb)
//   - PSRAM: Disabled
//   - Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5 SPIFFS)
//   - Upload Speed: 921600
//   - Core Debug Level: None
*/
#include <Adafruit_NeoPixel.h>
#define LED_PIN   15 
#define LED_COUNT 60 
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

#include <WiFi.h>
const char* ssid      = "ssid";
const char* password  = "****";
const char* ntpServer = "fr.pool.ntp.org"; 

struct tm mytime;
hw_timer_t *My_timer = NULL;

byte locsec = 99;
byte sequen = 88;

//###############################################################################
void verif_ws2812()
{ Serial.println("init ws2812");
  uint led_color[] = { 0 ,strip.Color(255,   0,   0),strip.Color(  0, 255,   0),strip.Color(255, 255, 255), 0 };
  strip.fill(0,0,strip.numPixels());
  strip.show();
  strip.setBrightness(10);
  for(byte i = 0; i<5;i++)
  { strip.fill( led_color[i], 0 ,strip.numPixels());
    strip.show(); delay(500);
  }
}
//############################################################################ 
void IRAM_ATTR onTimer()
{/**/
  Serial.println("########################### IRAM_ATTR onTimer() ");
  if(!getLocalTime(&mytime))
  {  Serial.println("Could not obtain time info - IRAM_ATTR "); 
     return;
  }
  if(locsec != mytime.tm_sec)
  { 
    Serial.println("  - - - - - - - - -  ");
    Serial.println(asctime(&mytime));
    locsec = mytime.tm_sec ;
    sequen = 0;
  }
  Serial.println(" o o o o o o o o o o ");
  Serial.print(&mytime, "%A %d %B %Y %H:%M:%S | ");
  Serial.println(sequen++) ;
  Serial.println(" 0-0-0-0-0-0-0-0-0-0 ");
  Serial.println(asctime(&mytime));
  strip.setPixelColor(locsec, strip.Color(0, 0, 0));
  locsec = mytime.tm_sec ;
  strip.setPixelColor(locsec, strip.Color(0, 0, 255));
  Serial.println("########################### IRAM_ATTR onTimer() - before strip.show() ");
  strip.show();
  Serial.println("########################### IRAM_ATTR onTimer() - after strip.show() ");
}
//////////////////////////////////////////////////////////////////////////////
void setup()
{
  Serial.begin(115200);
  Serial.println(compilation);
  Serial.println(nom_fichier);
  strip.begin();
  verif_ws2812(); // strip.show() in this function work fine at this time
  WiFi.begin(ssid, password);
  Serial.print("Connecting...");
  while (WiFi.status() != WL_CONNECTED) 
  {   delay(500);
      Serial.print("...");
  }
  Serial.print("\nConnected with success ");
  Serial.print("IP locale : ");
  Serial.println(WiFi.localIP());


  My_timer = timerBegin(1, 80, true);
  timerAttachInterrupt(My_timer, &onTimer, true);
  timerAlarmWrite(My_timer, 333000, true);
  timerAlarmEnable(My_timer); 

  configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer); // summer time for France
}
////////////////////////////////////////////////////////////////////////////// 
void loop()
{ // here strip.show() work fine with delay(1000), but I want use timer
}

After having studied and understood the sketch of a clock for neopixel, I adapted it to my wishes.
Now I would like when a single pixel indicates the position of 2 or 3 needles, the pixel will blink to see that there are 2 or 3 "needles" in the same place.
If sec=minute color second - color minute - color second.
If sec=minute=hour second color - minute color - hour color.
If ... other combinations ... etc.
It is for this purpose that I thought of using the timer as a time base of 0.33 sec.
And, if I understand correctly, I don't have to use the timer for that, but manage the millis correctly.

But I would also like to be able to manage a tft screen to display the weather or temperature, turn ws2812 on or off with a button, change colors and bright from sunset and sunrise, generate a local pseudo dcf77 for my other clocks which pick up the signal very badly, have a wifi access point to see all that on my phone (the ntp is only queried once an hour).

I sorry but I do not understand.
my brain : iq 55 :slight_smile: