You are on page 1of 9


com/dimming-230v-ac-with-arduino-2/ by PANTELIS k on 08/02/2014 • 0 Comments I am going into the point immediately.The proper way to control dimming 230v AC, is through phase control with a Triac: the Triac then is fully opened, but only during a part of the sinus AC wave.

One could let an Arduino just open the Triac for a number of microseconds, but that has the problem that it is unpredictable during what part of the sinus wave the triac opens and therefore the dimming level is unpredictable. One needs a reference point in the sinus wave. For that a zero crossing detector is necessary. This is a circuit that tells the Arduino (or another micro controller) when the sinus-wave goes through zero and therefore gives a defined point on that sinus wave. Opening the Triac for a number of microseconds delay starting from the zero crossing therefore gives a predictable level of dimming. I have discover two ways so that to dimm a incadence 230V bulb using Arduino. Both uses a triac but the main difference is how arduino should understand the zero cross detection of AC. This method is called AC phase control. It is the method used in many light dimmer and heater and motor power control circuits. For a better understanding we will name the first way software way and the second analog way .

Software Way Let‟s explain in details the operation.

The method for power control is shown in the diagram below. It will turn off if the gate voltage is zero the next time the ac wave crosses zero. The net result here is that we “chop” parts of the . All we need to do is to ensure that the triac gets turned off inside of the period of ½ wave (t3). Once turned on. The longer this time is. Once the “off time”. the triac remains off for a controlled amount of time (t1) . t1 has elapsed. the microcontroller turns on the triac by applying a voltage to the gate (shown in red). The duration of the gate pulse (t2) is determined by a minimum requirement of the traic. If this pulse is too short. the less power the ac circuit receives.The zero-crossing detection circuit provides a 5v pulse every time the ac signal crosses zero volts. the triac will remain on even after the gate voltage has been removed. We detect this with the Arduino and leverage interrupts to time the trigger circuit precisely in synchronization with these zero-crossing events. we do not need to take care to turn the triac off when the ac signal crosses zero again. Because of this. Once a zero crossing is detected. the traic will not fire Once the second zero crossing occurs. the triac remains off until triggered again in the next ½ cycle. sice there is no voltage on the gate.

The period (length of time this takes) is 1/50 or 0. This is t3 in the figure above. crosses zero. What this means is that the AC signal crosses zero. The AC signal is 50 Hz. reaches peak negative voltage and returns to zero 50 times each second. .02 seconds (20 milliseconds).wave out resulting in lower average power. We will be using interrupts and the arduino timer to precisely control the timing of the triac gate. A half cycle (the time between two zero-crossings) occurs in 10 milliseconds. reaches peak positive voltage. This is essentially how one accomplishes “PWM” control of an AC wave.

It consists of an additional resistor and capacitor. Should you chose to use the triac switch for continuous use.2kΩ. that triggers the Opto-Thyristor briefly. The signal of the 4N25 is fed to an interrupt pin in the Arduino (or other microprocessor). the LED will light up clearly. Mind you though that in dimming operation that light will not be very visible because it is very short lasting. You can modify the circuit for controlling motors too. The interrupt routine feeds a signal of a specific length to one of the I/O pins. The mains 220Volt voltage is led through two 30k resistors to a bridge rectifier that gives a double phased rectified signal to a 4N25 opto-coupler. The I/O pin signal goes back to our circuit and opens the LED and a MOC3021.The circuit pictured here does just that. in line with the sinusoid wave on the mains net. reduce the resistor from 2.4kΩ to 1. The LED in this opto-coupler thus goes low with a frequency of 100Hz and the signal on the collector is going high with a frequency of 100Hz. providing more current to drive the triac and increase the capacitor to 200nF. The . This snubber circuit is there to protect the triac from the high voltage generated from an inductive load. If you are using a less sensitive triac to control the inductive load. The gate current is below 15mA. The LED in series with the MOC3021 indicates if there is any current going through the MOC3021.

Ok. In Europe we have 50 Hz 50Hz is 50 waves per second. the lamp will only burn at half power. As we are using TRIACs. The small leakage can be significant enough to turn on small load (for example a lamp). If it sends that pulse at 5ms.After the zero crossing is detected the program needs to wait for a specified amount of time and then switch on the TRIAC. let‟s to software stage now What the software needs to do is to detect the zero crossing. what the software needs to do is to wait for the zero point at the sinuscurve. Interrupt driven: .feedback may cause some problem for non-inductive load. We will use an interrupt to tell the program that there was a zero crossing. Each sinus wave thus takes 1000ms/50=20ms (miliseconds) As there are 2 sinuspeaks in a wave that means that after every zero detection there is a 10ms period that we can regulate. take note of that and then wait a specified amount of time within that 10ms period to send a pulse to the TRIAC. This t3 at the diagram. and then wait for a set amount of time on that sinuswave to switch on the TRIAC.

we are going to add some functionality to regulate the light level in steps.33) // triac Off digitalWrite(AC_LOAD. delayMicroseconds(dimtime). zero_crosss_int. // Choose the zero cross interrupt } What this says is that the interrupt is attached to interrupt 1. OUTPUT). first we need to set that up. That means that every step is 10ms/128 = 10000us/128=75us (in fact it is 78. it goes to a function called “zero_crosss_int” and it reacts to a rising flank on the pin. LOW). We will also add a bit of functionality. HIGH). which determines our level of dimming. // For 60Hz =>65 // Off cycle digitalWrite(AC_LOAD. We don‟t just want one level set that the lamp burns on. } What happens here is that the program first calculates the dimtime (=time to wait before the triac is fired) It then waits that amount of time. but we are going . The total dimtime then is calculated from 75x(1 to 128).// Set AC Load pin as output attachInterrupt(1. For that I have chosen the fully arbitrary amount of 128 steps. The Triac will switch off again at the following zero crossing. // triac On propagation delay (for 60Hz use 8. we assign to the variable integer „dimming‟ int dimming = 128. but I get to that later). // triac firing delayMicroseconds(10). The number between 1-128. void zero_crosss_int() // function to be fired at the zero crossing to dim the light { int dimtime = (75*dimming). On the Arduino that is as follows: void setup() { pinMode(AC_LOAD. subsequently waits that amount of time and fires the Triac. Interrupt 1 is pin 3 of arduino In the Zero_cross_int function that the program jumps to after the interrupt we determine the time we need to wait before firing the TRIAC. RISING).To use an interrupt.

It‟s only function is to set the time that the Triac is switched on to the value of the variable „dimming‟ In the main loop of the program the actual value of that variable is set . It works as follows: The interrupt function”zero_crosss_int” gets called every time a zero-crossing is detected. We need to wait a bit however to know for sure the TRIAC is on. As discussed in the previous theoretical page. If you want to develop your own software all you need to do is: Wait for the zerocrossing Wait a specific time between 0 and 9090 microseconds (9090=10. at 50 Hz we need the steps to be 75 uS .000-10) switch on yr TRIAC Wait for about 10us (that is the time you need to make sure the TRIAC is on) switch off yr TRIAC (in fact. i <= 128. which is 100times/second. delay(10). so we wait 10us That also is the explanation why I am using 75 rather than 78 for my steptime as 10000-10=75 The only thing then left to do in the main program is to set the level at which we want the lamp to burn: void loop() { for (int i=5. you only remove the triggersignal to the TRIAC. i++){ dimming=i.000uS As the program varies the dimming from Full to Off in 128 steps (that is just a choice that was made. the software is fairly easy. could be 100 steps as well). } What happens here is a simple loop that regulates the lamp up in a 128 steps We can use a timer to determine the amount of time to wait. the TRIAC will stay on till the next zerocrossing) At 50Hz that interrupt is every 10ms or already write a low on the TRIAC pin to avoid accidental ignition in the next cycle.

10us) / 128 = 75 (Approx) For 60Hz =>65 int dimtime = (75*dimming). delay(10). // For 60Hz =>65 // Wait till firing the TRIAC digitalWrite(AC_LOAD. OUTPUT). LOW). 128 = OFF void setup() { pinMode(AC_LOAD. zero_crosss_int. // Fire the TRIAC delayMicroseconds(10). RISING). // triac On propogation delay (for 60Hz use 8. delayMicroseconds(dimtime).000/120) // 10ms=10000us // (10000us . // Output to Opto Triac pin int dimming = 128. // Choose the zero cross interrupt # from the table above } //the interrupt function must take no parameters and return nothing 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 thus: (50Hz)-> 10ms (1/2 Cycle) // For 60Hz => 8. HIGH).33) // No longer trigger the TRIAC (the next zero digitalWrite( AC_LOAD = 3. // Dimming level (0-128) 0 = ON. crossing will swith it off) TRIAC } void loop() { for (int i=5. i <= 128. .33ms (10. i++){ dimming=i.// Set AC Load pin as output attachInterrupt(0.

} } About the software: theoretically in the loop you could let variable „i‟ start from ‟0′.g. . the same goes for 128 (Full off) though that seems to be less critical. 2 to 126 instead of 0-128. However. your range may go from e. Wether ‟5′ or perhaps ‟1′ is the limit for your set up is a matter of trying. since the timing in the interrupt is a bit of an approximation using ‟0′ (fully on) could screw up the timing a bit.