AC Light Dimming [success]

Nice work! Is this useable to control fan speed etc.?

I am going to make a PCB and test it out soon. Really nice to have the hard work done already! 8)

For inductive load check out moc3020 datasheet: http://www.micropik.com/PDF/moc3020.pdf :slight_smile:

Here's a silly question.. I had wondered if it would be possible to do the phase sync and timing in a different way.. by using a feedback system. Remember, I only know enough to be dangerous. I just don't see why dimmer circuits aren't.. "smarter".

What I mean is that in my mind, you could initially switch the TRIAC on at any point, and "place" in the timing of the phase could be determined with a (adding a zener? to shunt the voltage) diode feeding a voltage back. One half of the cycle, there's a voltage passed back, measure that duration and you know both the frequency and the phase timing. Since the frequency is calculated from the timing, and the phase switching is done scaled accordingly, wouldn't that remove line frequency as a variable? In addition, if you are able to monitor the voltage, you can measure the magnitude.. and therefore calculate desired output voltage switching.. removing source voltage as a variable (within reason). I guess I'm just describing a switching-regulated power supply aren't I.... but what exactly is the difference? It just seems to me that all these isolators and such ought not to be necessary, if the dimmer is capable of intelligently modifying the timing based on sensed output.. and the resulting device would be more flexible than a device which is locked in for a particular source voltage and frequency.

As I understand (and it's more than possible I misunderstand), dimmers function by switching the power off and on at appropriate times, effectively making them voltage regulators with a Bipolar PWM output of a sort. Other than finding the duration of the phase and the timing of the phase, I would think pretty much anything else is a matter of switching at the appropriate time. Am I off base?

I really haven't researched TRIACS all that well, and maybe have misinterpreted how these beasties are used. Seems like you have gotten a good grasp of how these work and what is required for them to do the job.. mainly a bit of me being too lazy at the moment to research why I ought to know better...

In short : no, You can not.

And a little more elaborate : the TRIAC can only be switched on, and it will switch off itself when the voltage over it is 0 (or very close).
What You are describing can be done with an IGBT, but also in this case a 0-crossing detector is used. That is what sometimes is called a "soft dimmer". This works so that the IGBT is switched on at 0 volts and switched off depending on the level wanted. This way the big current surge when switching on a triac middle-phase is avoided because switching on is done at 0 volts.

Ahh.. so the TRIAC will stay on until the voltage crosses zero, making it impossible.

I'm going to guess that the prohibitive factor in that is the transistor type turns out to be very expensive, right?

I could have sworn I saw a data sheet for a Solid State Relay (the boxy kind that has the 4 screw terminals that is about the width and length of an Arduino Uno) that supported PWM for dealing specifically with dimming AC voltages. Wish I could find it again.

macharborguy:
I could have sworn I saw a data sheet for a Solid State Relay (the boxy kind that has the 4 screw terminals that is about the width and length of an Arduino Uno) that supported PWM for dealing specifically with dimming AC voltages. Wish I could find it again.

I know there are solid state relays, but those are DC 12V, have never seen AC 220V Solid State relays with PWM!

Hi all! I have built the circuit from here:http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/15 -

And it works, except for then the dimming value gets low. It works great when close to 100 (dim) to 30 (75% bright) range, but it stays at about 75% bright all the way down to a value of 0. If I just turn the Arduino pin to HIGH, then I do get full brightness.

Any ideas? I have checked and rechecked my layout and it seems like if there was a wiring problem it just wouldn't work at all.

techie:
Hi all! I have built the circuit from here:http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/15 -

And it works, except for then the dimming value gets low. It works great when close to 100 (dim) to 30 (75% bright) range, but it stays at about 75% bright all the way down to a value of 0. If I just turn the Arduino pin to HIGH, then I do get full brightness.

Any ideas? I have checked and rechecked my layout and it seems like if there was a wiring problem it just wouldn't work at all.

Your link is not working here...

FYI, this AC SSR can be controlled with variable DC input (PWM):

http://www.alliedelec.com/images/products/datasheets/bm/CRYDOM_CO/70130557.pdf

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.

Hi,

I am from Singapore, Our mains are 230V 50Hz, question is what do I need to change in my circuit to suit conditions?

Secondly what is the component B1 in you circuit?

Lastly, what is the Arudino board that you're using? Im using an Arduino Uno.

For the 220V 50Hz circuit, provided by op, is it absolutely necessary to use 45K ohm resistors? I can't seem to find the given value at local or online electronic retailers. The closest values I have found for 1/2W resistors is 43K and 47K ohm.

I was thinking perhaps connecting 3 15k ohm resistors in series but wouldn't the cumulative tolerances make the difference with using 43K and 47K ohm resistors trivial?

Would appreciate it if someone could point me in the right direction

1cecream:
is it absolutely necessary to use 45K ohm resistors?

Hi there, I've used two 47k resistors of 1/2W. If you check the datasheet of the 4n35 you can find the maximum current and typical voltage from which you can compute the minimum size of your resistors. Then compute the power that it will dissipate and increase resistance until the power is below the rating of the resistor.

I've built the circuit and it works good for all dimming levels. However when I connect the circuit to the mains, there seems to be a current peek or something, making the lamp flash. It also seems to have an effect on the arduino controlling the moc3023 as an interrupt is triggered unexpectedly. Someone can help me to overcome this effect? Is this due to "inrush current" or "snubbing" of the triac?

Many thanks!

As there was a question on the necessity of exactly 45 k resistors (that has been answered already), I just want to make a general remark about the resistors in a zero crossing circuit like this: Obviously you do not want to make them too small and burn out your optocoupler, but in a circuit like the one discussed here ( http://fleck.rullz.lv/acdimmer/ac_dimmer_220V_circuit.png ), The intention is too keep the optocoupler in saturation until the zero crossing. If one cooses the resistors too big, upon appraoching the zero crossing the voltage might already have dropped too much to maintain enough current through the optocoupler to get a positive spike on the secundary site of the optocoupler circuit. Your interrupt therefore may be triggered a bit before the actual zerocrossing, which may screw up yr timing. In principle it is possible that if you want full power of yr lamp and you would switch it on before yr zerocrossing, thinking you have switched it on immediately after your zerocrossing, your lamp would in fact be immediately turned off again

Fleckz:
OK, here is another success story for AC Light Dimming.
I was reading this topic,
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/30
ppl there asked about 220V AC Light Dimming, also, I was interested in making this, so I did. this works perfectly for 220V 50Hz mains.

First of all - basics, you can't just use MOC3020 (or similar) to dim AC light, because of sync problem, you need to tell arduino when to turn triac on and when off, if not in time, light will just blink. To do that, in old forum you see opto-coupler H11AA1, it has two LEDs inside, easy to use for AC, thou, H11AA1 are not available here at local stores, so i had to use 4N35 and bridge rectifier!
In this way you just let arduino know, when the phase changes in mains and use that info to toggle opto-triac!

OK, here are the files for this project: Index of /acdimmer
circuit, arduino code and Lazarus Project to control light! :slight_smile:

For those with 60Hz mains, you have to change number "34" in line:
delayMicroseconds(34*(255-dim));
My guess would be around 27 for 60Hz, but as i don't have 60Hz mains here, i can't try! If somebody can, let me know, i will update post etc...

Also all comments are welcome, bad and good...

Hi,

I do it and plugged 220V. Also i uploaded your code to the Arduino Uno. Then i checked LOAD pins with multimeter but there is no voltage. Do i need anything for voltage?

This project runs very well on an UNO.
Is it possible to port the sketch over to ATTiny45 or ATTiny85?
If so, how would one go about handling the timing as the UNO runs at 16MHz and the ATTiny runs at 8MHz?

I used this this device to control Virbation machine in industrial area with 110V 50hz. It has feature to adjust iteslef to work on 220v 60hz. Based on description perfectly fine for light dimming and fan speed control.

http://www.amazon.com/Programmable-Controller-Arduino-Raspberry-Compatible/dp/B01B783Q5O/ref=sr_1_2?ie=UTF8&qid=1454907075&sr=8-2&keywords=ac+dimmer+arduino

if you looking to better tools working with 110V/220 As well with easy and safe to connect and simple to program i recommend you to see this

this device allowing you to control AC voltage "on off or even as dimmer " simply by sending PWM rather than right a complex code which allow you to integrate it with more advance project.

http://www.sugarworld.net/