AC Dimmer and SparkInterval Library Help

Hi all,

As the title says, im coding an AC Dimmer using the SparkInterval Library. The test code is as follows:


     SYSTEM_THREAD(ENABLED);
    // This #include statement was automatically added by the Particle IDE.
    #include "SparkIntervalTimer/SparkIntervalTimer.h"
    
    int AC_PIN = D3;                  // Output to Opto Triac
    int PIN_ZERO_CROSS = D2;
    
    unsigned int dimmerLevel = 5000;
    
    IntervalTimer timerOn;
    IntervalTimer timerOff;
    
    void zero_cross_detect();
    
    void setup()
    {
      Serial.begin(9600);
      
      pinMode(AC_PIN, OUTPUT);                          // Set the Triac pin as output
      
      timerOn.begin(turnOn, dimmerLevel, uSec);
      timerOn.interrupt_SIT(INT_DISABLE);
      timerOff.begin(turnOff, 9500, uSec);
      timerOff.interrupt_SIT(INT_DISABLE);
      
      pinMode(PIN_ZERO_CROSS, INPUT);
      attachInterrupt(PIN_ZERO_CROSS, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
    }
    
    void zero_cross_detect() {
      timerOn.resetPeriod_SIT(dimmerLevel, uSec);
      timerOn.interrupt_SIT(INT_ENABLE);
      timerOff.resetPeriod_SIT(9500, uSec);
      timerOff.interrupt_SIT(INT_ENABLE);
    }
    
    void turnOff() {
        digitalWrite(AC_PIN, HIGH);       // turn off TRIAC (and AC)
        timerOff.interrupt_SIT(INT_DISABLE);
    }
    
    
    void turnOn() {
        digitalWrite(AC_PIN, LOW); // turn on light
        timerOn.interrupt_SIT(INT_DISABLE);
    }
    
    
    void loop() {
    }

The main idea is that once the zero cross is detected i restart and enable a timer that will be called X usec after, acording to the dimming level i want. The maximum value, for 50Hz, is 10000 usec so i will set a maximum of 8000 and leave the last 2000 usec for other stuff.
Also when the zero cross is detected i restart another timer on a fixed time of 9500 usec that will turn off the AC_PIN before a new zero cross appears.

Now, i need a way of detecting and fixing losses of the zero cross, so something i was thinking about was using a third timer, also fired when a zero cross is detected and using a fixed time over 10000. So, as the timer is restarted with every zero cross, then it should never be fired unless the zero cross is not detected.
Something like this:

    void setup()
    {
      Serial.begin(9600);
      
      pinMode(AC_PIN, OUTPUT);                          // Set the Triac pin as output
      
      timerOn.begin(turnOn, dimmerLevel, uSec);
      timerOn.interrupt_SIT(INT_DISABLE);
      timerOff.begin(turnOff, 9500, uSec);
      timerOff.interrupt_SIT(INT_DISABLE);
    
      **timerZeroCrossFix.begin(zeroCrossFix, 10050, uSec);**
      
      pinMode(PIN_ZERO_CROSS, INPUT);
      attachInterrupt(PIN_ZERO_CROSS, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
    }
    
    void zero_cross_detect() {
      timerOn.resetPeriod_SIT(dimmerLevel, uSec);
      timerOn.interrupt_SIT(INT_ENABLE);
      timerOff.resetPeriod_SIT(9500, uSec);
      timerOff.interrupt_SIT(INT_ENABLE);

    timerZeroCrossFix.resetPeriod_SIT(10050, uSec);
    }

    /************************************************************************/   
    void zeroCrossFix(){
      timerOn.resetPeriod_SIT(dimmerLevel, uSec);
      timerOn.interrupt_SIT(INT_ENABLE);
      timerOff.resetPeriod_SIT(9500, uSec);
      timerOff.interrupt_SIT(INT_ENABLE);
    
      timerZeroCrossFix.resetPeriod_SIT(10000, uSec);
    }
    /************************************************************************/

But im having problems with this last code.
I would like to know if im doing something wrong.

  • Am i using the timers correctly? Any ideas?
  • Is there any delay when i restart the timers?
  • Is there a problem with restarting a timer from the function called by that timer?
  • Any considerations to take into account when using 3 timers at the same time¿?
  • A better way of doing all this stuff?

I need the dimmer to be very precise, i cant see any blinking on the lights!

Thanks all in advance!

@alexgrauer, if I understand correctly, you want to adjust for +/- variations in the zero-cross timing. One approach is to use a micros() based timer at the end of each zero-cross interrupt. When the next interrupt occurs, read the current micros() and subtract the previously set value to get the difference and calculate the drift value (difference between expected and actual). From that, you can correct the timing values of the on/off timers as required. Hope that makes sense!

That makes a lot of sense @peekay123, thanks!

The thing is, i guess the 50Hz grid frequency is variable, right¿? (50 +/-x)… so its imposible to avoid flickers 100%, am i right?

@alexgrauer, timing will always be variable, whether caused by the grid frequency or delays in the processing within the Photon. Adjusting for those timing differences is the easiest way to minimize or remove their impact.

@peekay123, but if im using leading edge, as i never know when the next zero cross will come, it is impossible to adjust the times, right?
Lets say i want to turn on the light to 50%. When the zero cross comes, the TRIAC will turn off the light and i will turn it on 5000 usec after that. But that cycle has 50 HZ + 0.5, so the light will be on for more than 5000 usec.
But the next cycle has 50 Hz - 0.5, so now the light will be on for less than 5000 usec.

Is there a solution for this?

@alexgrauer, you can only assume a fixed period and adjust timing within each cycle. Look around on the forum as I believe other members have done dimming using Photons.

I think the difference will not be very noticable with a frequency of 50.5Hz your half wave will be 9900µs instead of 10000µs.
Also because that won't be an isolated event but the frequency will be slowly moving so your "flicker" would be more like a slow change (if at all).
There are other factors that would trip such a dimmer far more (e.g. audio frequency control systems that impose a 1kHz control signal that even trips consumer dimmers).

I don't know how the net quality is in your location, but in European UCTE net the max. acceptable variance is 200mHz (49.8 ~ 50.2Hz) and that's already near blackout conditions.
Standard deviation is about 25mHz
http://www.mainsfrequency.com/verlauf_en.htm

1 Like