AC dimmer Timer Interupt

I am using the below code for a AC dimmer

int AC_pin = D5;    
Timer timer(75,dim_check);
volatile boolean zero_cross=0;
int dim = 0;                 
int inc=1; 
volatile int i=0;  
void setup()
{
    timer.start();
  pinMode(AC_pin, OUTPUT);// Set AC Load pin as output
  attachInterrupt(A0, zero_crosss_int, RISING);  // Choose the zero cross interrupt # from the table above
}


void zero_crosss_int()  //function to be fired at the zero crossing to dim the light
{
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);   // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
}
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH); // turn on light       
      i=0;  // reset time step counter                         
      zero_cross = false; //reset zero cross detection
    } 
    else {
      i++; // increment time step counter                     
    }                                
  }                                  
}                       


void loop() {          
   
  dim+=inc;
  if((dim>=128) || (dim<=0))
    inc*=-1;
  delay(18);
}

I have implemented the AC dimmer using Photon without using the timer (using delaymicroseconds) it is working perfectly fine.But i am trying to implement it with timer but using above code but it is not working.What might be the problem?


I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~@Moors7

1 Like

@UmangChheda, when you say it “is not working”, do you mean the timer callback is not firing? You need to explain a little more. Are you using the web IDE, CLI or DEV?

I noticed you code has 2 loop() functions and I’m not sure why this compiled! Are you compiling for version 0.4.7 and is your Photon system firmware at 0.4.7?

Hi,
i have edited the code.It has only one loop.
I the photon is running on 0.4.7 firmware and i am using the web IDE.
I guess the timer callback is not working.
Is there any issue with the code?

Have you checked if your ISR is firing?

Just to be sure try adding a pinMode(A0, INPUT); (with or without pull-resistors, depending on your signal source) before attachInterrupt().
Did this work without pinMode() on 0.4.7 and your delay aproach?

1 Like

Hi,
Sorry for the late reply.
Ya it worked without the pinMode and with delay function on 0.4.7
I guess the ISR isn’t firing.

@UmangChheda, is the software timer firing as expected? You could add code to toggle the D7 LED in zero_crosss_int() to see if it’s firing. Just add:

in setup()

pinMode(D7,OUTPUT);
digitalWrite(D7, LOW);

in zero_crosss_int():

digitalWriteFast(D7, !pinReadFast(D7));

You can also mode the toggle code to dim_check() to see if the software timer is firing. :smile:

@UmangChheda I was also trying dimming on PHOTON and found that Timer will only work for millis where as it should be microsecs so I used SparkIntervalTimer (here) library which accepts timer with microseconds and dimming is working fine.

#include "SparkIntervalTimer.h"

SYSTEM_MODE (MANUAL);

volatile int i = 0;               // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross = 0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = D1;                // Output to Opto Triac
int dim = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff
int inc = 1;                      // counting up or down, 1=up, -1=down

int freqStep = 75;    // This is the delay-per-brightness step in microseconds.
                      // For 60 Hz it should be 65
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.

void zero_cross_detect();
int PIN_ZERO_CROSS = D2;
volatile int zeroCross = 0;
IntervalTimer timer;

void setup()
{
  Serial.begin(9600);
  pinMode(PIN_ZERO_CROSS, INPUT);
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  timer.begin(dim_check, freqStep, uSec, TIMER5);
  attachInterrupt(PIN_ZERO_CROSS, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
}

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

// Turn on the TRIAC at the appropriate time
void dim_check() {
  //Serial.println("DIM CHECK");
  if(zero_cross == true) {
    if(i>=dim) {
      digitalWrite(AC_pin, HIGH); // turn on light
      i=0;  // reset time step counter
      zero_cross = false; //reset zero cross detection
    }
    else {
      i++; // increment time step counter
    }
  }
}

void loop() {
  dim+=inc;
  if((dim>=128) || (dim<=0))
    inc*=-1;
  delay(18);
}

Reference : http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/?ALLSTEPS

2 Likes

@blackadmin, fantastic! If you use the new digitalWriteFast() instead of plain digitalWrite(), the ISR will be serviced even faster!

1 Like

@peekay123 Ok great, was not knowing this, will use this from now onwards, but can digitalWriteFast be used anywhere at place of digitalWrite or only in case of ISR ?

Thankyou. :smile:

@blackadmin, ever since v0.4.5 of the Photon firmware, pinSetFast(), pinResetFast(), pinReadFast() and digitalWriteFast() have been available. They can be used anywhere in your code with the understanding that pinMode() needs to be run first to configure the pin. Also understand that these functions don’t do any conflict checking like digitalWrite() so if you write to an analog output pin instead of digital output pin, the code won’t reject the request! However, the functions will run in 40ns versus 2us!!

1 Like

Hey @blackadmin Thanks alot for the code,I tried it today and is working perfectly Thank You :smile:

1 Like

Hi Guys,I want to implement a 2 channel AC dimmer can anyone suggest me how it can be done?
(I am still novice in Programming so kindly bare with me :smile: )

What do you mean with two channel dimmer?

If you are using one AC line (single phase - neutral) you can use the same zero-cross-detection interrupt and just run two seperate “valves”.
But if you intend to have seperate AC lines with different phases (three phase system - with or without neutral) you’d need two seperate ZCDs.

And you need to adhere to you local safety regulations in connection with high (>65V) voltage AC!!!

@ScruffR,

Did you mean Electrical Code (HVAC = Heating, Ventilation and Air Conditioning)?

Nope - I thought this stands for High Voltage Alternating Current - does it not? :blush:
(removed the acronym)

@ScruffR, lol!!! I guess it depends where you live but Wikipedia says:

:stuck_out_tongue_winking_eye: