AC Light Dimming [success]

Hi there,

I'm working on a code for dimming based on timer interrupts (Timer1). I'm using right this same circuit, same components, etc. I get a pretty good control of dimming with the code you used but not with first version of mine. I don't know what is going wrong with my code. Here it is:

//initialize and declare variables

#include <TimerOne.h>	// Avaiable from http://www.arduino.cc/playground/Code/Timer1
#define FREQ 50 	// 50Hz power in these parts
#define AC1_Pin 10	// Output pin to control TRIAC


const int dimMax = 100;                     // Maximum value in dimming scale
const int dimMin = 0;                       // Minimum value in dimming scale
int volatile dim1 = 0;                   // Actual dimming value
unsigned long int period = 1000000 / (2 * FREQ);//The Timerone PWM period , 50Hz = 10000 uS
long int offTime = 3000;

void setup ()

{   //set the mode of the pins…
pinMode(AC1_Pin, OUTPUT);
digitalWrite(AC1_Pin, LOW);
attachInterrupt(0, light, FALLING );    //zero-cross detection;
Timer1.initialize(period);
Timer1.disablePwm(9);
Timer1.disablePwm(10);

} //close void setup

void loop ()
{
//nothing yet 
}


void light() //External interrupt (zero-cross) triggers this function
{
    Timer1.restart();
    Timer1.attachInterrupt(nowIsTheTime, offTime); //supposedly starts a timer that will overflow at offTime and when that happens...is the time ..
}


void nowIsTheTime ()//...to fire the TRIAC!
{
      digitalWrite(AC1_Pin, HIGH);
      Timer1.restart();// we have to wait for lowering AC1_Pin
      Timer1.attachInterrupt(nowIsTheTimetoShutDown, 50);
}

void nowIsTheTimetoShutDown ()
{
digitalWrite(AC1_Pin, LOW);//We wait a few microseconds to turn off
Timer1.detachInterrupt();
}

As you can see I'm not dimming, nor getting inputs. I just type the value of the delay in useconds to get the TRIAC fired (offTime variable, in the range from 0, full power, to 10000, null power) before compiling and test a lamp. But the lamp remains full power anytime, no matter what I write in the offTime variable.

In the mean time, I've been working in another version of code based on interrupts. The concept this time is to make a stepper dimmer. I set a scale of dim values to divide the half sine AC wave. Then I trigger a timer interrupt everysingle step. Let's say I decide I'll have 256 levels of dimming. The code will trigger an interrupt 256 times everytime zero-cross is detected (that initializes the timer). If the value of dimming corresponds with the present step then TRIAC is fired and one step later AC pin is lowered. Here's the code:

//This code dims up and down a lamp in a period of time

//initialize and declare variables

#include <TimerOne.h>	// Avaiable from http://www.arduino.cc/playground/Code/Timer1
#define FREQ 50 	// 50Hz power in these parts
#define AC1_Pin 10	// Output pin (TRIAC triggering)

const int DimMax = 100;                     // Max value in dimming scale
const int DimMin = 0;                       // Min value in dimming scale
int volatile Dim1 = 0;                 // Present dimming value
unsigned long int halfSineTime = 1000000 / (2 * FREQ);//The Timerone PWM period, 50Hz = 10000 uS
int rampInterval = halfSineTime/DimMax;                // Time of one step
int rampCounter = DimMax;        //Down counter with present step
int rampPeriod = 5;// For the fading, time in seconds that takes for the half way-up dimming (the same downwards)
int wait = rampPeriod*1000/DimMax;//Delay between increments of dimming
int buffer = 0.1*DimMax;// allows a safety buffer of steps in which results are dirty

void setup ()

{   //set the mode of the pins…
pinMode(AC1_Pin, OUTPUT);
attachInterrupt(0, light, FALLING );    //Zero-crossing detector
Timer1.initialize(halfSineTime);
Timer1.disablePwm(9);
Timer1.disablePwm(10);

} 

void loop ()
{//The main loop just raises and lowers the value of Dim1 in the time specified in wait variable
   int x = 1;
   for (Dim1 = DimMin+buffer; Dim1 > DimMin+buffer-1; Dim1 = Dim1 + x){
      if (Dim1 == (DimMax-buffer)) x = -1;             // switch direction at peak
      delay(wait);
   }
 
}//close void loop



void light() //This function is triggerd at zero-cross
{
    Timer1.restart();//we set timer1 origin
    rampCounter = DimMax;//initialize the steps counter
    if (Dim1 < DimMin+1) 
    {                  //Turn TRIAC completely OFF if Dim1 is 0
      digitalWrite(AC1_Pin, LOW);
    }
    else if (Dim1 > DimMax-1) 
    {                //Turn TRIAC completely ON if Dim1 is 255
      digitalWrite(AC1_Pin, HIGH);
    }
   else  
   {      
   //Dimming part, if Dim1 is not 0 and not 255
    
    Timer1.attachInterrupt(nowIsTheTime, rampInterval); //If we have a value to dim then we trigger a timer interruption
  }
}


void nowIsTheTime ()
{
    if (rampCounter == Dim1)		//In the interrupt we fire the TRIAC only when the actual step (counting backwards) equals the value of Dim1
    {
       digitalWrite(AC1_Pin,HIGH);
    }
    else {
 digitalWrite(AC1_Pin,LOW);//in the next step (and the rest) AC1_Pin remains low
    }
    rampCounter = rampCounter--;//decrease the counter
      
}

This code works fine if we set a number of steps in the range of 50-300. Below 50, it's possible to see the state change in light. The higher the value, the less time you get for computing other things beside interrupt functions.

However, I get a flaw somewhere and I don't know where it is. Once in a while there's a sudden flick in the light, like it missed a zero detection or didn't get on time to fire the TRIAC and missed one sine wave cycle. And the closer you get to the extreme steps (just after and before the zero-cross) you might get unaceptable extreme values for dimming, that's the reason of having a 10% security buffer of steps that are never used (see buffer variable).

Any hint why this is happening?

Thanks.