ESP8266 wifi light dimmer

Inexpensive ESP8266 wifi light dimmer.

Similar projects worth following
I working on creating a light dimming module based on the ESP8266 wifi module. I'm hoping to keep the cost down by running the code native on the ESP8266. I believe the units could be made for $8-10 each in quantities of 10.

I'm using the dimming circuit found here:

I have received all components and have a working breadbord prototype. My code is currently on the ESP8266 Arduino-compatible IDE.

  • 1 × ESP8266
  • 1 × BT136 TRIAC Opto and Fiber Optic Semiconductors and ICs / Optocouplers and Optoisolators
  • 1 × MOC3021 Optoisolators Triac Driver
  • 1 × 4N25 Optoisolators Transistor

View all 12 components

  • Success with Arduino for ESP

    Ryan04/06/2015 at 05:50 0 comments

    After reading the Arduino IDE support for the ESP8266 article on the HAD blog, I decided to write up some quick example code to see if it also exhibited the same flickering issue as NodeMCU. I was very happy to see smooth dimming and have now ported the code I had for NodeMCU to Ardiuno.

    Code and Fritzing schematic I've been working on are now available on GitHub. Both are for 110v and will need adjusted timings in code and 30k resistors to the bridge rectifier for 220v.

    Next up will be trying to fit all components on my perfboard. I've ordered some 4A 250V pigtail fuses and am waiting to see if I can squeeze it on my board (I will need to shift things around). If not, I will use an inline fuse holder. I'm also hoping to add a low temp (< 100c) AC thermal fuse for peace of mind.

    Here is what its looking like with all components in place (except fuse). Nothing is soldered yet.

  • Flickering with NodeMCU firmware

    Ryan04/06/2015 at 00:59 0 comments

    My initial code was running on NodeMCU firmware. Unfortunately, when wifi was enabled there was a slight flickering (something like 5% or so) when dimming was enabled. I believe this was due to the wifi CPU cycles causing the TRIAC trigger delay to vary. If NodeMCU ever ports their code to the RTOS SDK, I will be curious to see if that corrects this issue.

View all 2 project logs

Enjoy this project?



Priyank C wrote 04/18/2017 at 04:05 point


Where do you find the power supply it seems it has 4 output 3.3 to 24 V. I could not find it online if you have a link please share.

Thanks, Priyank

  Are you sure? yes | no

Ryan wrote 05/09/2017 at 01:48 point

It looks like its now called an 'HLK-PM03' and is available on Ali-express. There is only one output. Depending on the model you get hey are supposed to mark the appropriate box (mine had no boxes marked). The one I got is 3.3v. It looks like they also make 'HLK-PM01' for 5v and 'HLK-PM12' for 12v.

  Are you sure? yes | no

Priyank C wrote 05/09/2017 at 02:05 point

Tnaks Ryan, meanwhile I ordered '1PCS AC-DC 5V 700mA 3.5W Precision Buck Converter AC 220v to 5v DC step down Transformer power supply module for Arduino' from AEx, lets see how it turns. 

  Are you sure? yes | no

John Magill wrote 04/03/2017 at 08:05 point

Hi Ryan

Have you any experience of OTAupdate? I have had success using it but with your sketch it fails every time. It doesn't seem to be related to sketch size as I have other much bigger ones which work. If I comment out the 2 lines......

hw_timer_init(NMI_SOURCE, 0);

hw_timer_set_func(dimTimerISR);                then the otaupdate will work. Sorry I'm out of my depth.



  Are you sure? yes | no

Ryan wrote 04/05/2017 at 04:03 point

I've noticed the same thing on my sketches since using the NMI source. Unfortunately, I haven't found a solution yet so OTA is broken at the moment.

  Are you sure? yes | no

abhishek.konale wrote 03/08/2017 at 21:34 point

Hi Ryan,
I am trying to make a multi-channel dimmer module,but i have been stuck at getting the hw_timer to work,in non-autoload mode it fires the interrupt even when the timer is unarmed..,
I am using Arduino ide 1.6.4,ESP 01 module,git version of esp board.
Any help would be greatly appreciated,
Thank you,
Abhishek Konale

  Are you sure? yes | no

Ryan wrote 03/10/2017 at 05:26 point

That's odd. Are you using the same hw_timer files I am? Does it happen even with a single channel? I'm running Arduino 1.6.9 w/ esp8266 2.2.0 and ESP-12.

  Are you sure? yes | no

abhishek.konale wrote 03/12/2017 at 06:44 point

To test it,I used a simple counter inside the timer isr in non autoload mode,it increments even when the hw_timer is unarmed,
My initial strategy was to sort the dimming levels of all the channels in ascending order then fire each pin successively which i thought would require minimum cpu usage,but unfortunately the timer wasn't working well.
The second approach was to use the timer in autoload mode with period of T/N,for N levels, use a counter for each channel and check in every period,which worked but causes resets..
Any views on this issue?
Abhishek Konale

  Are you sure? yes | no

John Magill wrote 02/20/2017 at 11:25 point


You mention adjusting of timings in code for 230V 50Hz operation. Can you give me any pointers as to how to do that. Thanks

  Are you sure? yes | no

Mikecay wrote 06/22/2016 at 14:27 point

Hi Ryan,

I have been following your project and, like most, I have had random problems with flickering and wdt crashes, likely due to timing.  Are you using timer0 for the timing?

Thank you,


  Are you sure? yes | no

D Khazz wrote 05/22/2016 at 21:47 point

Hey, just checking in to see if you've played around with this any more...6 months since last post.

  Are you sure? yes | no

Ryan wrote 05/25/2016 at 02:42 point

I have and I'm due for a new post. I've now got 100% stable dimming by using the ESP's hardware NMI timer (a recent patch made this timer stable). I've also started working on adding a PIR sensor and status LED, so once I'm farther along with those I'll update my github and create a new post.

  Are you sure? yes | no

v1ckdesigns wrote 12/29/2016 at 01:02 point

Can you share which timer did you use? i found plenty of them and none of them can operate with such short interwals ( microseconds ) 

  Are you sure? yes | no

ronb8 wrote 12/07/2015 at 01:41 point

Hi Ryan - did some further study this weekend on your original code.  Found that I could not get it to run continuously for more than about 20 mins maximum. It would crash, with a wdt failure. I moved all the code to the main routine, and just set a flag in the ISR, which executes the triac code only if the flag is set. It's now been running for hours without failure.  I do notice a little flicker however from a connected LED (triac's not yet arrived).

I speculate an issue with executing timers in the ISR. Took a look at your new code, but need more info to understand it. I notice you also moved the pin assignment around a bit, why?

  Are you sure? yes | no

Ryan wrote 12/07/2015 at 02:25 point

I got my FTDI yesterday and did some playing around as well. I tried moving the delay out of the ISR and it corrected the crash issue for me as well. The downside is that the light will flicker anytime something else is using the CPU (HTTP, MQTT, etc).

The pin assignments changed when moved from ESP07 to ESP12.

Try using the 'Team Messaging' button above. I haven't used it before but it seems like it would be a better way for us to send thoughts/ideas back and forth.

  Are you sure? yes | no

ronb8 wrote 12/06/2015 at 04:44 point

I've done some investigating: It appears delayMicroseconds() is OK, but delay() is not see:

My latest challenge is that I can set a brightness value, all works fine, but after several mins or so at a any brightness, system reverts to brightness=0. I can resend the brightness value and all is ok for another several minutes. Perhaps we should just set a flag in the ISR, and create the delay in the main routine, dependent on the flag setting?

  Are you sure? yes | no

ronb8 wrote 12/05/2015 at 22:32 point

Removing the double trigger fix corrected it! Thank you.

  Are you sure? yes | no

ronb8 wrote 12/05/2015 at 20:46 point

Ryan, while waiting on my Triacs, I used a sig gen to send in the ZCD signal at 120Hz, and triggering from that on CH1, looked at CH2. It appears on my setup the Triac output is only triggering on every other cycle. However, each alternate cycle is varying correctly between 0-8.3ms in duration, depending on brightness. I saw you included code to avoid "double trigger". Did you actually scope your signals? Is your dimmer full range? I also though I read somewhere that you cannot use delays in Interrupt service routines, because the timers use interrupts themselves? 

  Are you sure? yes | no

Ryan wrote 12/05/2015 at 22:17 point

Try removing the double trigger fix (or using the newest version on github). This was required initially, but was no longer needed after moving from my breadboard/ESP-07 to perfboard/ESP-12 (I had also updated the Arduino for ESP code, which may have also resolved it). I believe my code is pretty close to full range for 60hz and I did use a scope when working through the delay calculation (its a cheap usb logic analyzer/scope, so nothing fancy).

For the delay in the ISR, I've tried many ways to remove it since I suspect it may be causing the crashes I've started to see (the OS/wifi/etc will hang in a delay), but so far everything I've tried has been unstable or caused inconsistent brightness/flickering. I'm going to experiment with Timer0 and getCycleCount when my programmer arrives.

  Are you sure? yes | no

ronb8 wrote 11/24/2015 at 04:15 point

Thanks Ryan! I look forward to experimenting with your latest code...

  Are you sure? yes | no

ronb8 wrote 11/22/2015 at 22:22 point

Love this project! Be cool if we could use a second ESP to send brightness to the host ESP, by holding down a certain GPIO, and having the lamp cycle from off to full on again over a few seconds, and when the GPIO is let go, it stays at the brightness. A kinda remote dimmer!

  Are you sure? yes | no

Ryan wrote 11/24/2015 at 03:41 point

I have the code to do something similar with the gpio locally on the newest version of the code (tap to toggle, hold to dim+, tap+hold to dim-). I haven't updated git in a while; I'll see if I can clean up my code and get to it this weekend. It wouldn't take much to adopt this to work remotely and push to another switch (its just http calls).

  Are you sure? yes | no

ronb8 wrote 12/02/2015 at 18:40 point

Ryan - still experimenting with your code while waiting on my Traics to arrive. Why in zcDetect did you comment out the attach & detach the Interupt lines, but in switchDetect you applied it?

Also eager to look at the newest code version when you have time to upload it. Great Project!

  Are you sure? yes | no

Ryan wrote 12/03/2015 at 05:04 point

My ESP was crashing with the zero-cross code attaching and detaching the interrupt so many times, so I instead kept track of the state with a variable. I've actually removed it from switchDetect as well in the new code. The attach/detach method may work now that the interrupt behavior seems more stable in the newer versions of the ESP Arduino code.

  Are you sure? yes | no

Ryan wrote 12/03/2015 at 05:25 point

So I didn't get as much as I had hoped finished with the code. My FTDI adapter quit working on me last week, so after a bad HTTP firmware update, I have no easy way to recover my ESP until a new FTDI adapter arrives (a few are on the way from AliExpress). I tried using a TI Lauchpad, but it seems they don't support the 115200 baud needed to reflash the ESP :(.

I've uploaded my code, but I was in the middle of implementing MQTT and fighting stability issues with the ESP crashing after 2-5 minutes with dimming enabled when my FTDI cable quit working.

Adding a new project log on the new features is also on my to-do list once I get the stability/MQTT stuff figured out and do some code cleanup/organization.

  Are you sure? yes | no

Ivo Oude Veldhuis wrote 05/22/2015 at 07:11 point

Is this dimmer suitable for CFL lights and LED lights or only normal incandescent bulbs ?

  Are you sure? yes | no

Ryan wrote 05/23/2015 at 02:11 point

I've tested with incadescent and dimmable LED bulbs. I havent tried with dimmable CFL (I prefer to stay away from CFL for dimming).

  Are you sure? yes | no

Ankit Bhatia wrote 04/03/2015 at 23:50 point

Hi Ryan,

This project looks very cool! Hope you can iron out the kinks soon.

I've been thinking of getting something like this working too! It would be great if you could share you code and schematics.


  Are you sure? yes | no

James wrote 03/14/2015 at 22:13 point

Hi, how are you getting on with this? I have just built the same dimmer and was going to use the Arduino but it would be much more useful with the esp!! Is the code you used avaliable anywhere? Did you managr to resolve any of the issuus you found?


  Are you sure? yes | no

Ryan wrote 04/02/2015 at 04:50 point

Sorry for the late response. I set this project aside for a while after getting nowhere with nodemcu firmware (I tried various things but could not get rid of the flicker) and having issues getting RTOS to compile. 

I just yesterday decided to try using the ESP Arduino firmware recently released after reading a post about it on the HAD blog. To my surprise, the initial test code was very promising. I just spent the evening porting all my code from the NodeMCU firmware and working through some strange interrupt behaviors in the Arduino firmware. After getting those sorted out, I think I have something that works with no flickering.

I still have a few minor bugs to work out, but hopefully I can upload some images, code, and schematics later this week.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates