Step 5: Arduino Controlled Lightdimmer: The Software II

I found another piece of Software that allows controlling the lamp via the serial port. I have not tested it myself yet, but I see no reason why it should not work. It triggers on the falling edge of the zero-crossing signal, so the timing is a bit different.

int AC_pin = 3;//Pin to OptoTriac
byte dim = 0; //Initial brightness level from 0 to 255, change as you like!

void setup() {
  pinMode(AC_pin, OUTPUT);
  attachInterrupt(0, light, FALLING);//When arduino Pin 2 is FALLING from HIGH to LOW, run light procedure!

void light() {
  if (Serial.available()) {
    dim = Serial.read();
    if (dim < 1) {
      //Turn TRIAC completely OFF if dim is 0
      digitalWrite(AC_pin, LOW);

    if (dim > 254) { //Turn TRIAC completely ON if dim is 255
      digitalWrite(AC_pin, HIGH);

  if (dim > 0 && dim < 255) {
    //Dimming part, if dim is not 0 and not 255
    digitalWrite(AC_pin, HIGH);
    digitalWrite(AC_pin, LOW);
void loop() {

Even more software <a href="http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/AC_Dimmer_Circuit.html" rel="nofollow">here</a>
<p>Can this circuit be use for dimmable leds?</p>
<p>it depends on the LED's some are dimmable, others are not</p>
<p>I have a dimmable LED, and I was thinking of using 4 with only one switch.<br>what modification do I need to do, to achieve that?</p>
<p>I am not sure what you mean with 'using 4 with only one switch. You mean just put them parallel?<br>What sort of modifications are you then thinking off? If one led works most likely putting 4 in parallel will also work provided these are 220 or 110 Volt dimmable ACleds</p>
<p>Sorry forgot to put &quot;parallel&quot;, <br>it is as you said 4 in parallel</p>
<p>What changes in the code </p>&quot;Step 7: Software To set level using up and down buttons&quot;, and in the circuit to 120V?
<p>Changes for the 120 Volt do not depend on the software so that is the same for all steps.<br>So, for 120 Volt half the resistors.<br>If it is not only 120 Volt but also 60Hz then make: </p><p>int freqStep = 75;<br>into:<br>int freqStep = 65;</p>
<p>Changes for the 120 Volt do not depend on the software so that is the same for all steps.<br>So, for 120 Volt half the resistors.<br>If it is not only 120 Volt but also 60Hz then make: </p><p>int freqStep = 75;<br>into:<br>int freqStep = 65;</p>
Can this circuit be used to control speed of a ceiling fan. If not why?
<p>somehow i get that question a lot and there is no clear answer. In principle the answer is YES it can, but then again TRIACS are not the optimal devices to regulate inductive loads. However it is possible, but depending on your fan it may or may not be a smooth process.<br>The reason why Triacs are not optimal for an inductive load is because of the current being out of phase with the voltage in an inductive load.. But I use the expression 'not optimal', I am not saying 'not possible' </p>
<p>Hi, very nice project.</p><p>Just a quick question before I start. </p><p>What would be the total limit of the Wattage for the loads in this project? </p><p>Does it depend only on the source?</p>
<p>It depands on the TRIAC you are using. If that is say a 6 amp TRIAC, the Wattage is 6x220=1320 Watt if it is a 10 amp the max load is 2200 Watt, all provided you have sufficient heatsinking</p>
<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>

About This Instructable


330 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: Reading the BMP180 Pressure sensor with an Attiny85 and add a DHT11 too 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
Add instructable to: