WARNING: Some people try to build this with an optocoupler with zerocrossing coz 'that is better' right? Some are even told in electronics shops it is better to use such an optocoupler. WRONG. This will only work with a random fire optocoupler: NOT igniting at zerocrossing is the principle of this dimmer.

Switching an AC load with an Arduino is rather simpel: either a mechanical relay or a solid state relay with an optically isolated Triac. (I say Arduino, but if you use an 8051 or PIC16F877A microcontroller, there is stuff for you too here.)

It becomes a bit more tricky if one wants to dim a mains AC lamp with an arduino: just limiting the current through e.g. a transistor is not really possible due to the large power the transistor then will need to dissipate, resulting in much heat and it is also not efficient from an energy use point of view.

Phase cutting
One way of doing it is through phase control with a Triac: the Triac then is fully opened, but only during a part of the sinus AC wave. This is called leading edge cutting.
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 after a number of microseconds delay starting from the zero crossing therefore gives a predictable level of dimming.

Pulse Skip Modulation
Another way of doing this is by Pulse Skip Modulation. With PSM, one or more full cycles (sinuswaves) are transferred to the load and then one or more cycles are not. Though effective, it is not a good way to dim lights as there is a chance for flickering. Though it might be tempting, in PSM one should always allow a full sinuswave to be passed to the load, not a half sinus as in that case the load will be fed factually from DC which is not a good thing for most AC loads. The difference between leading edge cutting and PSM is mainly in the software: in both cases one will need a circuit that detects the zero crossing and that can control a triac.

A circuit that can do this is easy to build: The zero crossing is directly derived from the rectified mains AC lines – via an optocoupler of course- and gives a signal every time the wave goes through zero. Because the sine wave first goes through double phased rectification, the zero-crossing signal is given regardless whether the sinus wave goes up through zero or down through zero. This signal then can be used to trigger an interrupt in the Arduino.

It goes without saying that there needs to be a galvanic separation between the Arduino side of things and anything connected to the mains. For those who do not understand 'galvanic separation' it means 'no metal connections' thus ---> opto-couplers. BUT, if you do not understand 'galvanic separation', maybe you should not build this.

The circuit pictured here does just that. 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 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, in line with the sinusoid wave on the mains net. The signal of the 4N25 is fed to an interrupt pin in the Arduino (or other microprocessor). The interrupt routine feeds a signal of a specific length to one of the I/O pins. The I/O pin signal goes back to our circuit and opens the LED and a MOC3021, that triggers the Opto-Thyristor briefly. The LED in series with the MOC3021 indicates if there is any current going through the MOC3021. Mind you though that in dimming operation that light will not be very visible because it is very short lasting. Should you chose to use the triac switch for continuous use, the LED will light up clearly.

Mind you that only regular incandescent lamps are truly suitable for dimming. It will work with a halogen lamp as well, but it will shorten the life span of the halogen lamp. It will not work with any cfl lamps, unless they are specifically stated to be suited for a dimmer. The same goes for LED lamps

If you are interested in an AC dimmer such as this but you do not want to try building it yourself, there is a somewhat similar dimmer available at www.inmojo.com, however, that is a 110 Volt 60Hz version (but adaptable for 220 50Hz), that has been out of stock for a while. You will also find a schedule here.

NOTE! It is possible that depending on the LED that is used, the steering signal just does not cut it and you may end up with a lamp that just flickers rather than being smoothly regulated. Replacing the LED with a wire bridge will cure that. The LED is not really necessary. increase the 220 ohm resistor to 470 then

STOP: This circuit is attached to a 110-220 Voltage. Do not build this if you are not confident about what you are doing. Unplug it before coming even close to the PCB. The cooling plate of the Triac is attached to the mains. Do not touch it while in operation. Put it in a proper enclosure/container.

WAIT: Let me just add a stronger warning here: This circuit is safe if it is built and implemented only by people who know what they are doing. If you have no clue or if you are doubting about what you do, chances are you are going to be DEAD!

4N25 €0.25 or H11AA1 or IL250, IL251, IL252, LTV814 (see text in the next step)
Resistor 10k €0.10
bridge rectifier 400 Volt €0.30
2x 30 k resistor 1/2 Watt (resistors will probably dissipate 400mW max each €0.30
1 connector €0.20
5.1 Volt zenerdiode (optional)

Lamp driver
LED (Note: you can replace the LED with a wire bridge as the LED may sometimes cause the lamp to flicker rather than to regulate smoothly)
MOC3021 If you chose another type, make sure it has NO zero-crossing detection, I can't stress this enough DO NOT use e.g. a MOC3042
Resistor 220 Ohm €0.10 (I actually used a 330 Ohm and that worked fine)
Resistor 470 Ohm-1k (I ended up using a 560 Ohm and that worked well)
TRIAC TIC206 €1.20 or BR136 €0.50
1 connector €0.20

Piece of PCB 6x3cm
electric wiring

That is about €3 in parts

Step 1: Arduino controlled light dimmer: The PCB

You will find two pictures for the PCB: my first one, that I leave here for documentation purposes and a slightly altered new one. The difference is that I left out the zenerdiode as it is not really necessary and I gave the LED itś own (1k) resistor: it is no longer in series with the Optocoupler, that now has a 470 Ohm resistor. I made the PCB via direct toner transfer and then etched it in a hydrochloric acid/Hydrogenperoxide bath. There are plenty of instructables telling how to do that. You can use the attached print design to do the same. Populating the print is quite straightforward. I used IC feet for the opto-couplers and the bridge rectifier.
Download the print here.
Note: You need Fritzing for this. For the direct toner transfer, the printed side of the printed pdf file, goes directly against the copper layer for transfer. Once it is transferred, you will be looking at the ink from the other side and thus see the text normal again. I made slight alterations in thePCB: I removed the zenerdiode and the LED is no longer in series with the optocoupler.

I used a TIC206. That can deliver 4 amperes. Keep in mind though that the copper tracks of the PCB will not be able to withstand 4 Amperes. For any serious load, solder a piece of copper installation wire on the tracks leading from the TRIAC to the connectors and on the track between the two connectors.

In case it is not clear what the inputs are: from top to bottom on the second picture:
Interrupt signal (going to D2 on arduino)
Triac signal (coming from D3 on Arduino)

If you have an H11AA1or IL 250, 251 or 252 opto-coupler then you do not need the bridge rectifier. These have two anti-parellel diodes and thus can handle AC. It is pin compatible with the 4N25, just pop it in and solder 2 wire-bridges between R5 and + and R7 and -. The LTV814 is not pincompatible

<p>Hey diy_bloke, quick question. I'm using a isolation transformer as the 120v source, I noticed it hums when I turn the dimmer low. Is that normal or am I introducing some weird harmonics into the mainline?</p>
<p>it may depend on what is normal. I cant exclude harmonics but I am not sure. Meaning I am not sure it introduces harmonics (it may) and I am not sure if that is the cause.<br>However since the humming arises due to action of the dimmer thats very likely the culprit. If it is harmonics ofcourse one immediately thinks 'filter'</p>
<p>I've been thinking about the software. We're interrupting at the start of each half-wave cycle (8ms~ in US). If dimming is set to 0 we will delayMicroseconds almost the full duration of the half-wave cycle, this is problematic as other interrupts then queue and eventually a long queue may lead to an undesirable phase shift. Later today I will try testing a method where the interrupt just sets global volatile vars which used in loop method to achieve the same effect using delay instead of delayMicroseconds which should free up time for other firmware interrupts. I will report on the characteristics of this second approach once achieved.</p>
<p>you are right, but let me stress that the first program is just a simple example. It is usually not good to use 'delay'. In the program in question the microcontroller is most of the time busy waiting. That is why I also provided a program with a timer, but there are other methods as well, e.g.set a startpoint with micros() and then poll the time with an if or case statement.<br>I would be very interested to see any solution you come up with</p>
<p>Moving the logic into delay didn't work, I think the phase was getting out of sync. At the bottom of zero_crosss_int we do a short delay and set ac load pin to low, the comment states that the next zero crossing will switch the triac off but why would it not switch the triac off at the time of the digitalWrite? </p>
<p> The state of the gate is irrelevant once it is open.<br>Only a lack of current flowing will close the TRIAC.<br>So the reason for the digitalWrite(gate,LOW) is merely to avoid that the Triac will open immediately again when the voltage goes up</p>
<p>I meant to say 'moving the logic into *loop* didn't work' :)</p>
<p>I really don't know why, but this code dind't work correctly for me, cuz my light turn on and off rapidly some times... any advice?</p>
<p>Also double check the bridge is fully rectified and not half wave which I imagine (but am not sure) would result in visible on/off pulsing of the lamp.</p>
<p>Finallly, I found the problem: the delay of 10us was so small for my triac, so I use 100us and now it works perfectly</p>
<p>That's great because single phase was correct rectifier. I believe this is the datasheet for the diodes used in diy_bloke's circuit: http://www.goodexcel.com/new/download/SPEC2008_RoH...</p><p>Here's the one I used: <a href="http://www.jameco.com/Jameco/Products/ProdDS/103042.pdf" rel="nofollow">http://www.jameco.com/Jameco/Products/ProdDS/10304...</a></p><p>You should post pictures of your circuit if you have time.</p>
<p>good u have found it 100us will definitely do it, but I think it could be shorter, try 16 or 20us<br>regardless, you got it to work</p>
<p>Assuming you wired everything up correctly there could be two possibilities that come to my mind. 1) Your power supply is not providing enough current which could lead to the interrupt being slow and unresponsive. 2) Noise on the crossover signal line causing a false positive on the voltage rise trigger. If you have a scope you should graph the +5v line, the interrupt signal line and triac signal line to try and isolate the fault.</p>
<p>Gregory, thanks for your input. Noise can be an important factor. A 'dirty' PSU for the arduino sometimes leads to extra pulses as well.<br>In this case it turned out to be trigger period that was too short . :-)</p>
<p>I have provided several programs but I presume you mean the first program.<br>Well as the program is OK (it has been used many times) and the circuit as well (has been rebuilt many times), The only answer is that there is a mistake in your circuit or in your copy of the software.<br>What I like you to do is the following.<br>remove your arduino from the circuit - what does it do? is the lamp off or does it flickr as well?<br>Connect 5Volt to the input. is your lamp on?<br>Please try that and let me know. Also... are you using a regular incandescent lamp?</p>
<p>I used the code described on step 3.</p><p>When I connect the input from the moc3021 to 5V, the lamp is on.</p><p>Also, I used the <a href="http://playground.arduino.cc/Main/ACPhaseControl" rel="nofollow">code provided by arduino's web</a> and it work correctly.</p>
<p>I presume you nean step 4 as there is no working code in step 3.<br>Nevertheless I am happy you solved the problem already. The program in the link you provided triggers the triac for 16us, whereas mine does it for 8.3-10us.<br>Goed to know that that might be a tad short.<br>Just out of curiosity... which Triac are you using?</p>
<p>I made it with Android Phone via Bluetooth And Ir Remote </p>
<p>looks great Abdulazziz. I always enjoy seeing what people made of my ibble. I am really impressed.<br>Your android app looks fantastic. What package did u develop that in?</p>
<p>Hi, great project, in-depth, well written and very informative. Congratulations!</p><p>I now understand zero-crossing and phase control - thanks.</p><p>Could the Arduino code be ported to an ATTiny45?</p>
<p>thanks. In principle it could. Not really a big problem, but I am not sure if the code is small enough for a 45. It may well be.it is not that big</p>
<p>Thanks for the reply.</p><p>Would I only need to change the ports to match those of the ATTiny45?</p><p>ATTiny45 runs 3.3V @ 8MHz - would this be OK, or would the timing need to be changed?</p>
<p>Darn, my reply disappeared, ok lets try again.</p><p>With regard to the interrupt, it depends on what core you use. If you use the <a href="https://code.google.com/p/arduino-tiny/ ">'tiny' core</a>, you can use the constant EXTERNAL_INTERRUPT_0 for INT0 at physical pin 7.<br>If you use pinchange interrupts, that might be a problem coz they react to both the rising and the falling flank.<br>No need to alter the timing as the 'delay()' function works correct on the tiny core as far as I know</p>
<p>Xamarin </p>
<p>tnx. iwill give that a try</p>
<p>Hi, great project, in-depth, well written and very informative. Congratulations!</p><p>I now understand zero-crossing and phase control - thanks.</p><p>Could the Arduino code be ported to an ATTiny45?</p>
<p>seemy reply on yr other post :-)</p>
diy_bloke good luck man :)
<p>Hi, I want to control the speed of a ceiling fan (80w 220v) using my arduino. There's already a manual dimmer in placed to control the speed, but I want to control it using my arduino. Can anybody suggest me what things I need to build a circuit to control my ceiling fan? <br>Also, in that manual dimmer, I noticed this Triac (BT134-600D) with a capacitor and couple resistors. Can I use these parts when building a circuit controlled by arduino?</p>
<p>Practically the only part you can ise is the TRIAC, but as TRIAC's are cheap I wouldnt take the manual regulator apart but just get a new TRIAC.<br>The problem with Inductive loads on dimmers is that the latter are not really optimally suited to regulate inductive loads as there is a phase shift between voltage and curent.<br>If you want an arduino to regulate your fan/dimmer then most likely you will end up with a circuit as in this instructible.<br>Another possibility is to use the circuit as in yr manual dimmer, replace the potentiometer with an LDR that you put in a lighttight tube with an LED. Regulate the intensity of the LED with PWM on yr computer.<br>If you would be satisfied with just say 3 or 4 settings of speed, I would advise to have a look here: </p><p><a href="http://txapuzas.blogspot.nl/2010/06/regulador-de-potencia-por-triac-para.html">http://txapuzas.blogspot.nl/2010/06/regulador-de-p...</a></p><p>Yet another possibility is to attach a servomotor to the knob of your manual control</p>
<p>Ok thanks a lot for such valuable suggestions. I will try these whatever is easier and make sense in my case. Thanks.</p>
<p>hello, I made something like this and its working pretty nice.</p><p>I want to slowly turn on the light and then slowly turn it off. but I have a little problem. </p><p>here is my arduino code:</p><p>int AC_LOAD = 16; // Output to Opto Triac pin</p><p>int dimming,dimtime;</p><p>int b;</p><p>void setup(){</p><p> pinMode(AC_LOAD, OUTPUT); // Set the AC Load as output</p><p> attachInterrupt(0, zero_crosss_int, RISING); // Choose the zero cross interrupt # </p><p> }</p><p> void zero_crosss_int(){</p><p> dimtime=(78*dimming);</p><p> delayMicroseconds(dimtime);</p><p> digitalWrite(AC_LOAD, HIGH);</p><p> delayMicroseconds(10);</p><p> digitalWrite(AC_LOAD, LOW);</p><p> }</p><p> void loop(){</p><p> b=120;</p><p> for(b;b&gt;=5;b--){</p><p> dimming=b;</p><p> delay(20); </p><p> }</p><p> for(b;b&lt;=120;b++){</p><p> dimming=b;</p><p> delay(20);</p><p> }</p><p> }</p><p>the problem is when the light is fully turned on it flicker once then slowly turn off like i want. i don't want to flicker at all. i try to modify the code but no luck.</p><p>can someone please help me? or tell me what i am doing wrong.</p><p>thanks</p>
<p>a flicker only once at full brightness is often caused by a zerocross signal that is a bit dirty or spikes on the Arduino supply line.<br>With regard to the zero crossing signal, I have explained that in the article and insome of my replies. The core is that the zerocross signal may start a tadd before the actual zerocross and still be active a tadd after the true zerocross.<br>Also the 78us do not fully cover the full sine period. I am not sure what you already tried to get to a solution but you could play a bit with the value of 5. qnd you could try to change your interrupt in 'FALLING'<br>Make sure there isnt much noise on yr Arduino Vcc. Test it with a battery if necessary</p>
<p>This might come handy: http://www.ebay.com/itm/APTINEX-Dual-Channel-Triac-Module-MOC3061-BT139-600V-16A-/181818408224</p>
<p>Thanks. It is a nice thing but totally unsuited for this application.<br>1- it is two channels, only need one<br>2- it doesnt have a seperate zerocrossing circuit, so you would need to add that anyway.<br>3-the MOC3061 has zerocrossing detection which makes it absolutely unuseable for this application, check my warning in bold at the beginning of my ibble.<br><br>It is therefore only suitable to switch 2 lamps ON and OFF </p>
<p>Awesome instructable, thanks for sharing, I learned a lot understanding triacs.</p><p>But I still have a problem, you might help me in. Before I start all over with the project and replicate your stuff I ask your advice:</p><p>I built box letters with 120 small 12V/1.2W bulbs for my friend, that should be dimmed (144W in total) hooked onto a 12V/16.7A toroid transformer, not rectified).</p><p>I bought an AC dimmer modul, driven by a microcontroller from a smartphone via bluetooth, which should drive the transformer's primary side.</p><p>(Yes, a rectified 12V line with a strong PWM seems more easy, but that direction failed because of the disturbing humming noise of the transformer...)</p><p>It all worked fine during long hours on full throttle and dimmed also, but at the last test the triac in the module just broke, overheated possibly because of the closed case. Stable 230V, on output pin, not dimming.</p><p>It has a T1235T-6I triac (Igt4Q=25mA) and a MOC3022 onboard. The gate resistor is 511Ohms.</p><p>I've replaced the triac with a BTA140-800 (Igt=35mA), but it doesn't work properly. On the output at 50% dim I measure ~60V on full throttle about 40V...<br><br>I would really appreciate if you could share your ideas what could've gone wrong.</p><p>Thank you in advance.</p>
<p>OK, it looks I've damaged the connection between the opto-coupler and the gate. Now it's working fine with the new triac.</p>
<p>OK, good I read your follow up before I started to reply your first post. I am happy you got your stuff working again</p>
<p>sir can i use 250v and 1a bridge rectifier? thanks..</p>
<p>yes u can use a 300 watt lamp</p><p>you can also use 250 volt</p><p>the circuit currently has a bridge rectifier so i am not sure what u mean</p>
<p>I'm trying to dim a 300 watts halogen lamp. is it ok?</p>
<p>I have few stupid questions (I know it's basics but I can't find answers and I have not anyone who can help me with this) ...How does &quot;zero<br>crossing detector&quot; works? What happend if the Voltage is 0? What<br>happend if Voltage is more than 0? Where current flows in this two<br>cases (left side of 4N25) and what Voltage value is there?</p><p>I understand this in this way: when Voltage is 0<br>the current flows the green way and when it has some Voltage &ndash; red<br>way. But in that case why 10k resistor? Voltage will not be very low...? </p>
<p>if the voltage is zero, that is when the zero is detected. The optocoupler blocks and no or only a small current will flow through the transistor: Therefore the voltage on the collector will rise to close to the Vcc<br>If the AC voltage is not 0, the transistor in the optocoupler will be triggered and go into conduction therefore the collector will be pulled close to 0</p><p>With regard to yr question about the value of the 10k resistor and 'will the voltage not be very low' Well.. which voltage, the voltage when there is no conduction or the voltage when there is conduction? Maybe that already answers yr question: The value is somehat irrelevant. The voltage only needs to be high or low. <br>Theoretically that resistor could even be 100 MegaOhm because if there is no current flowing, the Voltage on the collector will still be 5Volt.<br>The reason why i dont make it 100MOhm is because in practice a small current will flow into the input pin, but even then 100MOhm might still give a HIGH when needed.<br></p>
<p>Thanks, that helped me, but now I have new questions :) Why there is 30K resistors? This is because the bridge or 4N25 can't stand 220V? And here my second question: what does '400V' under bridge mean? Is this max voltage of it? And the last one: why 1k resistor is conected to MOC3021? I tried understand this by reading datasheets, but I'm not so good at it...</p>
<p>It is the 4n25 whose current needs to be limited, hence the 30k resistors<br>400 Volt is the max rating of the bridge<br>The 1k is there to limit the Gate current</p>
<p>I need your help again. I build the circuit, I upload photos and schema. I use BT136 triac and MOC3021. Now the problem: the bulb is on only a short part of time when I plug or unplug: https://youtu.be/_EshGUidjB0 at 17s you can see that nothing happend, bulb is off. I connect wire direcly to triac and then bulb is on so triac is working fine. I change MOC3021 to another MOC3021 and that's change nothing. Zero crossing detection is working fine. What can be wrong here? I can show you my code, but i use STM32F0DISCOVERY instead of Arduino</p>
<p>well if yr triac circuit works and yr zerocrossing also works, the problem must be in your software. And as I dont know your code, there isnt much i can do other than to advise you to really check your code</p>
<p>I bought another MOC3021, at the begining everything was good light is on but then MOC3021 become very hot ... what can be a reason?</p>
<p>Then I start to think you may have made a faulty wiring in your circuit</p>

About This Instructable


327 favorites


Bio: I am a physician by trade. After a career in the pharmeceutical world I decided to take it a bit slower and do things I ... More »
More by diy_bloke: Using 433MHz Remote Controlled Switches on Arduino Make an Android App to control via Bluetooth an Arduino Controlling your house via RF, all with AppInventor Simple EEPROM Module for Arduino or other microcontroller
Add instructable to: