Core resets sometimes using interrupts(?)

I have a problem with following code.
http://pastebin.com/BmgufZXf

Sometimes it just stops, cyan breathing, then cyan stuck, then reset to flashing green and working again. Repeat in 30-60 seconds.

Any advice on that?

This seems to be a common project nowadays :wink:

Just search zero_cross and you’ll find some more elaborate threads.
Another keyword in connection is SparkIntervalTimer
e.g. Alternative to Delay() within Interrupts?

But the short story - don’t use delays beyond a few microsec in an ISR!

A sidenote: digitalWriteFast() is way faster (but with less sanity checking) than digitalWrite() so it’s the way to do it inside an ISR.

Tried using code from here. [Solved] Trying to port an AC Dimmer circuit from Arduino to SparkCore

Well it works in a stable way, but it does not fully dim lights for me(only half-way) and have flickering issues even on incadesent bulbs. No such issues with original code.

While I’d still favour an aproach where you’d set up a SparkIntervalTimer with the dimming time to do the switching from within the zero-cross ISR, you could try this code, to see if your problem disapears

const int AC_LOAD     = D7;           // Output to Opto Triac pin
const int ZERO_DETECT = D4;           // Input pin for the zero detection
const int PERIODE     = 100;          // 65 for 60Hz
const int DIM_DELAY   =  20;          // push dimming level every x ms
const int minDim      =   5;          // minimal dimming level
const int maxDim      =  85;          // maximal dimming level
int dimFact           =  +1;          // dimming factor/direction
int dimming           = minDim+1;     // Dimming level (0-100)

void setup() 
{
  pinMode(AC_LOAD, OUTPUT);           // Set AC Load pin as output
  pinMode(ZERO_DETECT, INPUT);        // Set AC Load pin as output
  attachInterrupt(ZERO_DETECT, zero_crosss_int, RISING);
}

uint32_t msDelay;
void loop() 
{
  if (millis() - msDelay >= DIM_DELAY)
  { // every DIM_DELAY milli seconds push the dim level on
    msDelay = millis();
    dimming += dimFact;               // inc/dec according to current direction/factor 

    dimming = constrain(dimming, minDim, maxDim);    
    if (minDim == dimming || dimming == maxDim)
      dimFact *= -1;                  // invert dimming factor when bounds are reached
  }
}

void zero_crosss_int()                // function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms 
  // Every zerocrossing : (50Hz)-> 10ms (1/2 Cycle) For 60Hz (1/2 Cycle) => 8.33ms 
  // 10ms=10000us
  delayMicroseconds(PERIODE*dimming); // Off cycle
  pinSetFast(AC_LOAD);                // triac firing
  delayMicroseconds(10);              // triac On propogation delay (for 60Hz use 8.33)
  pinResetFast(AC_LOAD);              // triac Off
}

I replaced your delay()s with a non-blocking loop() design and streamlined your ISR a bit too.
Since you are not using WiFi, you could also consider SYSTEM_MODE(MANUAL).

@ryotsuke, this is an untested (due to missing hardware ;-)) version that uses the SparkTimerInterval library

// This #include statement was automatically added by the Particle IDE.
#include "SparkIntervalTimer/SparkIntervalTimer.h"

const int AC_LOAD     = D7;            // Output to Opto Triac pin
const int ZERO_DETECT = D4;            // Input pin for the zero detection
const int PERIODE     = 100;           // 65 for 60Hz
const int DIM_DELAY   =  20;           // push dimming level every x ms
const int minDim      =   5;           // minimal dimming level
const int maxDim      =  85;           // maximal dimming level
int dimFact           =  +1;           // dimming factor/direction
int dimming           = minDim+1;      // Dimming level (0-100)

IntervalTimer dimTimer;

void setup() 
{
  pinMode(AC_LOAD, OUTPUT);            // Set AC Load pin as output
  pinMode(ZERO_DETECT, INPUT);         // Set AC Load pin as output
  dimTimer.begin(doDim, 100000, uSec); // just a dummy time
  dimTimer.interrupt_SIT(INT_DISABLE); // don't fire now
  attachInterrupt(ZERO_DETECT, zero_crosss_int, RISING);
}

uint32_t msDelay;
void loop() 
{
  if (millis() - msDelay >= DIM_DELAY)
  { // every DIM_DELAY milli seconds push the dim level on
    msDelay = millis();
    dimming += dimFact;                // inc/dec according to current direction/factor 

    dimming = constrain(dimming, minDim, maxDim);    
    if (minDim == dimming || dimming == maxDim)
      dimFact *= -1;                   // invert dimming factor when bounds are reached
  }
}

void zero_crosss_int()                 // function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms 
  // Every zerocrossing : (50Hz)-> 10ms (1/2 Cycle) For 60Hz (1/2 Cycle) => 8.33ms 
  // 10ms=10000us
  
  // set up the timer for the actual dimming action
  dimTimer.resetPeriod_SIT(PERIODE*dimming, uSec);  
}

void doDim()
{
  dimTimer.interrupt_SIT(INT_DISABLE); // only one-shot
  pinSetFast(AC_LOAD);                 // triac firing
  delayMicroseconds(10);               // triac On propogation delay (for 60Hz use 8.33)
  pinResetFast(AC_LOAD);               // triac Off
}

I’d be interested how this actually does :wink:

There was something weird happening. First I made it dim 100% by using dim = 255 (with step of 77 that made double period)
When I decided to settle with that workaround it suddenly stopped working and original code with dim = 128 started to work fine.
It almost looks some changes in cloud were happening causing bad builds or something

Due to the way my code does the direction toggling you have to start the dimming within the allowed bounds. That’s what bounds are for :wink:

Yes, I understand that. However I could not reach fully dimmed state at 128, 0 -> 255 cycle did however work consinstently and from full light to full dimm. I can’t see why that was possible unless code built by cloud was calling timer interrupts twice faster or somthing like that, because eventually same code started to behave differently.