Ticker.h cause ESP8266 crash

Hello, I kindly asking for some help to my AC dimming project.
I moved the hardware to ESP8266 from an Arduino MEGA and want to control an AC dimming.
It works fine with MEGA, but when moving to a WEMOS D1, code crash with Serial output as below.
ets Jan 8 2013,rst cause:4, boot mode:(1,6)
wdt reset

I know the TimerOne.h can’t work on ESP8266 and use Ticker.h instead.

// lines marked with * works with Arduino MEGA etc boards.
// #include <TimerOne.h>                // Use with Arduino MEGA etc.

#include <Ticker.h>                     // Ticker Library for ESP8266
Ticker TimeMS;

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
// * int AC_pin = 3;                 // Output to Opto Triac
int AC_pin = 13;
int dim = 130;                  // Dimming level (0-30)  0 = on, 130 = 0ff
int inc=1;                      // counting up or down, 1=up, -1=down

int freqStep = 75;              // This is the delay-per-brightness step in microseconds.

void setup() 
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
 // * attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
 attachInterrupt(digitalPinToInterrupt(12), zero_cross_detect, RISING);  // Attach an Interupt to I/O 12 
 // * Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
 // * Timer1.attachInterrupt(dim_check, freqStep);    
  TimeMS.attach_ms(freqStep, dim_check);            // Check every 75ms (50Hz)                                           

void zero_cross_detect() 
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  digitalWrite(AC_pin, LOW);       // turn off TRIAC (and AC)

// Turn on the TRIAC at the appropriate time
void dim_check() 
  if(zero_cross == true) 
      digitalWrite(AC_pin, HIGH); // turn on light       
      i=0;  // reset time step counter                         
      zero_cross = false; //reset zero cross detection
      Serial.println("Zero Cross Detected");
      i++; // increment time step counter                     

void loop() 
  if((dim>=135) || (dim<=0))
  1. Are you using an newish release of the Arduino ESP8266 Core software? Current is 2.4.1.
  2. A Serial.println there is a bad idea.
  3. Try forcing the routine to stay in RAM: void ICACHE_RAM_ATTR dim_check()

You have access to a timer1 on the ESP8266. Here is one example. Google for the instructions on using it.

  timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP);
  timer1_write( 160000UL ); //  TIM_DIV1 = 80 ticks/uS  80000UL = 1mS

There are very few things you can do safely inside an interrupt routine.
If you stick to simple math on intergers and functions such as digitalRead() and digitalWrite().
You will have a much simplier and happier life.

3. Try forcing the routine to stay in RAM: void ICACHE_RAM_ATTR dim_check()

That's indeed a must for ISRs in the ESP. Caused me quite a few headaches!

The ESP tends to swap parts of code in and out of RAM as it is executed, and code needs to be in RAM to run. An ISR is called without warning, and when it's not in RAM when called, a crash results. The ICACHE_RAM_ATTR forces it to stay in RAM at all times, ready to be called.


for 50Hz the zerocross freq is 100Hz and you need a 1/128 part of it so:

1/100/1280 = 78.125 us not ms.