Multichannel Wireless Light Dimmer




About: Curious and Passionate about Electronics.

Save Energy Beautifully !!

By using a light dimmer in one’s living room, it’s possible to completely alter the mood and ambience of a room at the drop of a hat.
The Internet of Things is set to disrupt the way we live and work. Smart homes filled with connected products are loaded with possibilities to make our lives easier, more convenient, and more comfortable.

With Wi-Fi connectivity present in the dimming controller, the above benefits get reflected in this module. However, this actually carries with it a host of less obvious but equally favorable benefits such as reduced energy consumption and improved longevity - longer the bulbs are dimmed, lesser the energy they use and longer they last.

This project aims to

● Control the intensity of the dimmable lighting appliances via a trailing edge dimmer.

● Provide the user , ability to control lightsindependently and wirelessly over the Wi-Fi network and the Internet!

Step 1: Specifications

  • 2 channel dimmer module for indoor lighting applications (# channels can be easily expanded as per need)
  • Can be easily setup in Trailing Edge/Leading Edge configuration with some small variations in the software,hardware remains the same!!
  • Rating: 200 W/channel
  • No minimum load on any channel (True 3 wire dimmer!!)
  • Wireless control via Wifi (Uses the popular NodeMCU module)
  • Web Interface for controlling dimmer settings
  • Can be controlled from any device with browser support (Chrome, Firefox)
  • Supports OTA(Over the air programming) for software updates

Nice..,isn't it you too can make one for yourselves!!,I have spent a few months understanding and making this dimmer module.

You will find all the source files,step by step instructions and things I experienced while making this project compiled in this instructable.

I hope you would learn a lot and enjoy as you proceed further!!

Step 2: Understanding Light Dimmers

There are two main categories of traditional AC dimmers (also known as 'phase-cut' dimmers)

  • Leading Edge Dimmers
  • Trailing Edge Dimmers

These vary the brightness of the lighting appliance by varying the rms voltage applied to the load.

This design uses a Trailing Edge Dimmer

They provide a 'soft start', increasing the voltage to the lamp relatively slowly.

With incandescent lamps, this almost eliminates 'thermal shock' - that brief period at switch-on where the lamp draws around 10 times the normal operating current.
By including the soft-start feature lamp life is increased, but it doesn't help CFLs or LED lamps much.

Trailing edge dimmers commonly use a MOSFET, as these require almost no control current and are rugged and reliable.

Another option is to use an IGBT (insulated gate bipolar transistor), which combines the advantages of both MOSFET and bipolar transistor. These are generally more expensive than MOSFETs.

Step 3: System Block Diagram

Step 4: Components

  • ESP8266(NodeMCU) - 1
  • 4N35 - 3(Optocoupler IC)

  • 1N4148 - 4

  • HLK-PM01 - 1 (Mains to 5v dc conversion module)

  • IRF740 - 4 (N-MOSFET)
  • Fuse (2 A) ,SH22 Type Fuse Holder - 1

  • BA159 (Fast Switching Rectifiers) - 2
  • R 33K ½ W - 2

  • R 10K ⅛ W - 3

  • R 15K ½ W - 4

  • R 430 ⅛ W - 2
  • R 100 ⅛ W - 2

  • C 47uF - 4

  • C 10uF - 1

  • Zener Diodes(12 V) - 2
  • 6 pin IC Holders - 3 (For 4N35)
  • Female Header Pins (For ESP8266)
  • Incandescent Bulbs
  • Plastic Switch-box

Step 5: Schematic(The Trailing Edge Dimmer)

(Refer pdf version for better resolution)

Each subsection of the schematic has been explained in detail further.

Step 6: Zero Crossing Detection Unit

  • Diodes D3,D4,D5,D6 form a bridge rectifier.
  • U2 is an optocoupler(4N35), and its LED is powered via R6 and R7, and then from the bridge rectifier.
  • The interrupt signal is provided to NodeMCU via pin D6.
  • R8 is a pull-up resistor.
  • The zero crossing detector, gives a negative-going pulse when the mains voltage is close to zero.
  • This is used to synchronize the mcu to the mains, and is really the heart of the circuit.
  • A series string of 33K resistors is used instead of 66K resistor to divide the total of 1W power dissipation.

Step 7: 12V DC Supply

To minimize the switching losses in the mosfet IRF740, the gate control signal from the mcu is scaled to 12V.

Note: Each Channel needs it’s own dc supply.

  • A Fast switching diode BA159 is used to rectify the AC input.
  • D2 is a 12V zener diode

Step 8: MOSFET Driver

  • The AC switch is formed by two N-Mosfets in a series configuration
  • 4N35 IC provides the necessary isolation from the mains
  • The control signals from the MCU are fed to the optocouplers U1,U3

DC supply to MCU is provided by 220V AC to 5V DC 3W PCB Mounted Plastics Enclosed Isolated Switching Step-Down Power Supply Module (HLK- PM01) having compact form factor.

Step 9: Putting Everything Together

After understanding each of the sub units,functioning of the entire circuit is illustrated here.

Step 10: Programming the ESP8266 !!

Arduino IDE is used to program the NodeMCU ESP8266 module.

  • To use ESP8266 with arduino IDE follow the steps given below,
    • Start Arduino and open Preferences window.

    • Enter - "" into Additional Board Manager URLs field.

    • Open Boards Manager from Tools > Board menu and install esp8266 platform

    • Select NodeMCU 1.0 (ESP 12E module) board from Tools > Board menu after installation

    • Install WebSockets library by markus sattler from Sketch > Include Library > Manage Libraries
  • Please refer following link for getting started with Arduino IDE for ESP8266

  • Download the source code from the link provided,

  • The Source contains following files

    • Trailing_Edge_Dimmer_v5.ino
    • dimmer.h
    • hw_timer.c
    • hw_timer.h
  • Using long delays is highly discouraged while using ESP8266 as there is a lot of code that needs to run on the chip besides the sketch when WiFi is connected which may lead to frequent WDT resets.Hence we use hw_timers to save ourselves from this trouble.

  • The hw_timer.c,hw_timer.h files provide necessary functions to use hardware timer present in ESP8266.
    • hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req) function initializes the timer of ESP8266, if req argument is 0 the timer would start in non-auto load mode else it would start in auto load mode.
    • hw_timer_set_func(void (* user_hw_timer_cb_set)(void)) function sets the isr for handling the timer interrupt.

    • hw_timer_arm(u32 val) starts the timer with appropriate timing interval.

  • dimmer.h

Include the necessary library files.

#include <ESP8266WiFi.h>

#include <WiFiClient.h>

#include <ESP8266WebServer.h>

#include <ESP8266mDNS.h>

#include <ESP8266HTTPUpdateServer.h>

#include <Arduino.h>

#include <WebSocketsServer.h>

#include <Hash.h><br>

Next we define the dimmer module properties.

#define NUM_CHANNELS 2
#define DELTA 4               //(t_zero_crossing - t_interrupt)/STEP_TIME
#define STEP_TIME 78          //for 128 lvls (in uS) (65 for 50 Hz)

//128 lvl brightness control 
int Dimming_Lvl[NUM_CHANNELS] = {0,0}; //(0-127) 

int Drive_Pin[NUM_CHANNELS] = {5,4};
int State[NUM_CHANNELS] = {0,0};

//Wifi Access Point Settings
String ssid = "-----------";
String password = "-----------";

volatile boolean isHandled[NUM_CHANNELS] = {0,0};
volatile int Lvl_Counter[NUM_CHANNELS] = {0,0};

NUM_CHANNELS can be increased as per your need but you will have make necessary replications where ever needed.(This design is scalable to more than 2 channels!!)

STEP_TIME defines the interval over which the timer ISR is called repeatedly.It is calculated as follows:

STEP_TIME: 1/(2*frequency*NumLvls)* 10^6
Default :

frequency = 50 Hz NumLvls = 128

ssid : Network SSID
password : Network Password

Drive_Pin : Array consisting of Pin Numbers of NodeMCU (Please use proper pin numbers) ZERO_CROSSING_INT_PIN : Interrupt Pin

DELTA : There might be some fixed mismatch between the actual zero-crossing and the interrupt,which is removed by this constant.



Next we add a function to connect the ESP8266 module to the WiFi access point.

int connectToWiFi() 
  WiFi.begin(ssid.c_str(), password.c_str());
  int i=0;
  while (WiFi.status() != WL_CONNECTED) 
    if (i == 30) 
      return -1;
  DEBUG_PRINTLN("Connected to ");
  DEBUG_PRINTLN("IP address: ");
  return 0;



Now to start the WebSocket Connection WebSocketConnect() function is defined.

// WebSocket Connection

void WebSocketConnect() 



Zero_Crossing_Int() is the ISR attached to the ZERO_CROSSING_INT_PIN to detect the zero crossings.

void Zero_Crossing_Int()

  if(NumActiveChannels > 0)
    NumHandled = 0;

    for(int i=0; i<NUM_CHANNELS, i++)
	isHandled[i] = 0;       

	if(State[i] == 1)
        digitalWrite(Drive_Pin[i], HIGH);

    zero_cross = 1; 



dimTimerISR() is the timer ISR which is served every STEP_TIME uSeconds.We maintain counters for each active channel and compare/update them every cycle.

void dimTimerISR()
  if(zero_cross == 1)                     
    for(int i = 0; i < NUM_CHANNELS; i++) 
      if(State[i] == 1)
        if(Lvl_Counter[i] > Dimming_Lvl[i] + DELTA)       
          digitalWrite(Drive_Pin[i], LOW);     
          Lvl_Counter[i] = 0;  
          isHandled[i] = 1; 
          if(NumHandled == NumActiveChannels)
            zero_cross = 0;     
        else if(isHandled[i] == 0)



To manage the state(ON/OFF) of the channels following function is defined.

void Update_State(int ON_OFF,int Channel_Number)
  if(State[Channel_Number] == 0 && ON_OFF == 1)
  else if(State[Channel_Number] == 1 && ON_OFF == 0)
  State[Channel_Number] = ON_OFF;



webSocketEvent() function develops the communication protocol between the ESP8266 and the clients.

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) 
  switch (type) {
    case WStype_DISCONNECTED:
    case WStype_CONNECTED:
        IPAddress ip = webSocket.remoteIP(num);
        lastChangeTime = millis();
        isSynced = 0;
    case WStype_TEXT:
        String text = String((char *) &payload[0]);
        lastChangeTime = millis();
        isSynced = 0;
          String aVal=(text.substring(text.indexOf("a")+1,text.length())); 
          int Lvl_0 = aVal.toInt();
          Dimming_Lvl[0] = Lvl_0;
          String bVal=(text.substring(text.indexOf("b")+1,text.length())); 
          int Lvl_1 = bVal.toInt();
          Dimming_Lvl[1] = Lvl_1;

          DEBUG_PRINTLN("Channel 0 ON!!");         
          digitalWrite(Drive_Pin[0], LOW);
          DEBUG_PRINTLN("Channel 0 OFF!!");
          DEBUG_PRINTLN("Channel 1 ON!!");        
          digitalWrite(Drive_Pin[1], LOW);
          DEBUG_PRINTLN("Channel 1 OFF!!");
      //webSocket.sendTXT(num, payload, length);
      //webSocket.broadcastTXT(payload, length);

    case WStype_BIN:
      hexdump(payload, length);
      //webSocket.sendBIN(num, payload, length);



timer_init() function:

void ICACHE_FLASH_ATTR timer_init(void)
  hw_timer_init(FRC1_SOURCE, 1);
  • Trailing_Edge_Dimmer_v5.ino file
#include "hw_timer.h"

#include "dimmer.h"

void setup() 
  for(int i=0; i<NUM_CHANNELS, i++)
  pinMode(Drive_Pin[i],OUTPUT);<br>  digitalWrite(Drive_Pin[i],LOW);


void loop() 
  if(millis() - lastConnectivityCheckTime > 1000)
    if(WiFi.status() != WL_CONNECTED) 
    lastConnectivityCheckTime = millis();

    if (millis() - lastTimeHost > 10) 
      lastTimeHost = millis();

    //Update Connected Clients
    currentChangeTime = millis();
    if(currentChangeTime - lastChangeTime> 300 && isSynced == 0) 
      String websocketStatusMessage = "A" + String(Dimming_Lvl[0]) + ",B" + String(Dimming_Lvl[1]) + ",X" + String(State[0]) + ",Y" + String(State[1]);
      webSocket.broadcastTXT(websocketStatusMessage); // Tell all connected clients current state of the channels
      isSynced = 1;


OTA update can be done by accessing IP/update in the browser and uploading the compiled binary file. (Works fine for NumLvls = 64)

Eliminating Flickering and wdt crashes (as there is a lot of code that needs to run on the ESP8266 besides the sketch when WiFi is connected) is a major issue while dealing with the ESP8266.

Managing delays of the independent channels to ensure correct trigger positions for multiple loads could be tried by sorting the delays as well(Please let me know if you are successful with this method as i haven't got reasonable results with it)

Automatic frequency detection can be added to reduce flickering due changes in power line characteristics.

Step 11: Designing the Web App

      • The Web App source is a simple HTML file and uses WebSockets for handling clients.
      • Currently one needs to enter the IP address of the access point to get started (which is saved in the device automatically for future use)
      • The Network SSID and Password are hard coded into the system(You would need to modify the code to dynamically change the network)
      • The Web App Controls channel states (brightness, ON/OFF) via sliders, toggle switches.
      • Can be deployed on any device that has access to browsers like chrome/Firefox and Wi-Fi connectivity. (Note: the sliders are sluggish on android devices,may need some UI improvement)
      • Displays Real Time Channel states.
      • Eliminates the hassles of single remote as any number of users can directly control the settings via smartphones/laptops/tablets.

      Source Code

      The following link gives a good glimpse of using WebSockets with ESP8266

      Step 12: PCB Design, the Fun Part!!

      • Follow these tutorials for setup and basic understanding of EAGLE CAD software:

      -Installation and Setup

      -Using eagle schematic

      -Using eagle board layout

      • The PCB was designed in EAGLE CAD(7.2.0)
      • The EAGLE Files have been provided in this step.


      Please place the components(especially diodes,4N35 and other polarity sensitive components) in proper orientation while soldering.You may want to lay the silkscreen (if possible) for the same.

      Step 13: Caution!!

      Now that the PCB is ready it is extremely important to take the following precautions before testing the module for the first time (Don't be overwhelmed have some patience!!!)

      • Adding 2 - 200W bulbs in series with the test circuit (between the mains power supply and the input terminal of the module) as shown in the image.
      • Covering the PCB with plastic encasing.
      • Please use mounting screws for the PCB.
      • Cover your eyes with glasses to prevent any accidental damage.

      Now you are ready to test the design safely,always remember SAFETY FIRST,especially for newbies..

      (Henceforth, you may remove the series bulbs and test the pcb directly from mains supply)

      If things go fine you have successfully made a dimmer module, Congratulations!!!

      Else check your soldering work again with a DMM.

      Step 14: Final Product!!

      The finished Dimmer module can be used to control the ambience of your room conveniently.

      I have added some videos to demonstrate/explain working of the prototype and an image showing it's installation in my home.

      Now it's time to make yours!!!

      If you happen to do some creative work do let me know.

      Step 15: Simulating Your Design(In Case You Want to Improve the Design and Verify It)

      • LTspice XVII

      LTspice is a high performance SPICE simulator, schematic capture and waveform viewer, and above all it's free!!

      Download Link

      LTspice Tutorials

      (For adding third party models - IRF740,Incandescent Lamp etc.)

      LTspice Project Simulation Files (some of the model files,along with the simulation file used have been provided in this step)


      • Ryan (For many helpful discussions)

      If you like my Instructable please do vote for me in the Lighting Contest !!

      Lights Contest 2017

      Participated in the
      Lights Contest 2017



      • Colors of the Rainbow Contest

        Colors of the Rainbow Contest
      • Growing Beyond Earth Maker Contest

        Growing Beyond Earth Maker Contest
      • Classroom Science Contest

        Classroom Science Contest

      51 Discussions


      Question 5 weeks ago

      Is it possible to use as an fan regulator with snubber circuit attached?


      6 weeks ago

      This project is awesome. It benefits from the use of mosfets instead of triacs for creating a trailling edge dimmer with a lower noise which allows to drive modern dimmable led lamps properly.
      Unfortunately, since ESP8266 Arduino Core version 2.4.0-rc2, the ESP is crashing when the FRC1 timer is initialized [hw_timer_init(FRC1_SOURCE, 1);]. I have gone through many posts trying to solve this issue with no luck. I have also added OTA support to the code, which also does not work when programming this timer. Perhaps I have to stop the timer prior to starting OTA update, but could not manage doing it so far.
      If anybody has managed to doing this, please let me know.




      Question 3 months ago

      Hi, I've been looking up dimmer designs on the web and it seems that all
      I can find are circuits made for 230V 50Hz. I'm in the US where our
      supply is half that and 60Hz. What would I need to change to make this
      work here?

      2 answers

      Answer 3 months ago

      You only need to change the step time in software, no hardware changes needed.


      4 months ago

      Hi abhishek123,

      Thanks for writing this tutorial! There is not a lot of information on trailing edge dimmer circuits on the web.

      It seems that since you have published this piece, a ton of third-party firmware options have been developed for the ESP boards including Tasmota vs ESPurna vs ESPEasy. Searching for various options, it doesn't seem that any of these are able to handle the active logic of looking at the zero crossing input. Is it possible to modify your circuit so that only a PWM signal from the ESP chip can properly drive the dimmer, without the need for the zero crossing input?


      Question 6 months ago

      Why didn't you use a triac. Plus would it have been beneficial if you would have used optocoupler with inbuilt zero crossing detector?


      Question 9 months ago

      What is the factor limiting this design to 200w per channel? The Mosfets seem large enough to handle a higher current. What would be involved in increasing this to something in the range of 500-600 watts.


      Question 10 months ago

      I did this dimmer but without the detection of zero and it works but I do not know why one channel gets darker but the second channel when dimmed at low intensity the bulb apparently flashes which can be the reason.


      Question 11 months ago

      Hi. what voltage are the capacitors, I mean 47uf

      1 answer

      Question 1 year ago

      hi very nice tutorial. is it possible to do the same using blynk application and can we use triac in place of mosfet. I will be very thankful to you if you provide a example with blynk. I don't know coding and depend on genius like you help will be appreciated. I have a code from one of my friend. but I have tried a lot but it is not working. sliding the slider gets on and off only. I am using circuit as attached in file

      here is the code

      #define BLYNK_PRINT Serial
      #include <ESP8266WiFi.h>
      #include <BlynkSimpleEsp8266.h>
      char auth[] = "xxxxxxxxxxxxxxxxxxxxx";
      char ssid[] = "xxxxxxxxxxxxx";
      char pass[] = "xxxxxxxxxxxxxxxx";
      int dim = 0;
      float valeur=0;
      void setup() {
      Blynk.begin(auth, ssid, pass);
      attachInterrupt(digitalPinToInterrupt(2), light, CHANGE);//Interruption lors d'un passage de la tension alternative par 0 .
      pinMode(0, OUTPUT);
      pinMode(14, INPUT);
      void light()
      if (dim < 1) //dim a 0 la lampe est eteinte
      digitalWrite(0,HIGH );
      if (dim > 179) //dim a 180 la lampe est allumé a 100%
      digitalWrite(0, LOW);
      if (dim > 0 && dim < 180) //intensité variable de la lampe avec une resolution de 8 bits 0~179
      delayMicroseconds(39*dim); // Off cycle
      digitalWrite(0, HIGH); // triac firing
      digitalWrite(0, LOW); // triac Off
      void loop() {;
      BLYNK_WRITE(V12) //Button Widget is writing to pin V12

      I have another code I got it in youtube is working fine but not with blynk it is MQTT

      #include <ESP8266WiFi.h>
      #include <WiFiClient.h>
      #include <ESP8266WebServer.h>
      #include <ESP8266mDNS.h>
      #include <Arduino.h>

      const char *ssid = "Armtronix";
      const char *password = "Armtr0nix_1234567890";

      ESP8266WebServer server ( 80 );

      volatile int i=0;
      volatile int dimming =0;
      volatile boolean zero_cross=0;
      int AC_LOAD = 13; // Output to Opto Triac pin
      int AC_LOAD_SSR = 14; // Output to SSR pin
      int AC_ZERO_CROSS = 12; // Output to Opto Triac pin

      int freqStep = 375;//75*5 as prescalar is 16 for 80MHZ

      void handleRoot() {
      String s;
      s = "ARMTRONIX";
      s += "<p><a href=\"/gpio\">Control GPIO</a><br />";
      server.send ( 200, "text/html", s );


      void handleNotFound() {

      String message = "File Not Found\n\n";
      message += "URI: ";
      message += server.uri();
      message += "\nMethod: ";
      message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
      message += "\nArguments: ";
      message += server.args();
      message += "\n";

      for ( uint8_t i = 0; i < server.args(); i++ ) {
      message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";

      server.send ( 404, "text/plain", message );


      void setup ( void ) {

      pinMode(AC_LOAD_SSR, OUTPUT);
      pinMode(AC_ZERO_CROSS, INPUT);
      pinMode(AC_LOAD, OUTPUT);
      Serial.begin ( 115200 );
      WiFi.begin ( ssid, password );
      Serial.println ( "" );
      // Wait for connection
      while ( WiFi.status() != WL_CONNECTED ) {
      delay ( 500 );
      Serial.print ( "." );

      Serial.println ( "" );
      Serial.print ( "Connected to " );
      Serial.println ( ssid );
      Serial.print ( "IP address: " );
      Serial.println ( WiFi.localIP() );

      if ( MDNS.begin ( "esp8266" ) ) {
      Serial.println ( "MDNS responder started" );

      server.on ( "/", handleRoot );
      server.on("/gpio", webHandleGpio);
      // server.on ( "/test.svg", drawGraph );
      // server.on ( "/inline", []() {
      // server.send ( 200, "text/plain", "this works as well" );
      // } );
      server.onNotFound ( handleNotFound );
      Serial.println ( "HTTP server started" );

      void loop ( void ) {

      void InitInterrupt(timercallback handler,int Step )
      { Step=dimming*Step;
      timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);

      void ICACHE_RAM_ATTR do_on_delay()
      //digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED));

      if(zero_cross == true) {
      // if(i>=dimming) {

      digitalWrite(AC_LOAD, HIGH); // turn on light
      // i=0; // reset time step counter
      zero_cross = false; //reset zero cross detection
      delayMicroseconds(10); // triac On propogation delay
      digitalWrite(AC_LOAD, LOW); // triac Off
      Serial.println ( "zcd" );
      // }
      // else {
      // // i++; // increment time step counter
      // digitalWrite(AC_LOAD, LOW); // triac Off
      // }

      void zero_crosss_int() // function to be fired at the zero crossing to dim the light

      zero_cross = true;
      digitalWrite(AC_LOAD, LOW);


      void webHandleGpio(){
      String s;
      // Set GPIO according to the request
      if (server.arg("state_sw")=="1" || server.arg("state_sw")=="0" ) {
      int state_sw = server.arg("state_sw").toInt();
      Serial.print("Light switched via web request to ");
      digitalWrite(AC_LOAD, state_sw);
      else if (server.arg("state_led")=="1" || server.arg("state_led")=="0" ) {
      int state_led = server.arg("state_led").toInt();
      digitalWrite(AC_LOAD_SSR, state_led);
      Serial.print("Light switched via web request to ");
      // if (server.arg("state_dimmer") =="10" || server.arg("state_dimmer")=="20" || server.arg("state_dimmer")=="30" || server.arg("state_dimmer")=="40" || server.arg("state_dimmer")=="90" ) {
      else if (server.arg("state_dimmer") !="") {
      int state_dimmer = server.arg("state_dimmer").toInt();
      //digitalWrite(BUILTIN_LED, state_led);
      // Serial.print("Light switched via web request to ");
      dimming =127-state_dimmer;
      digitalWrite(AC_LOAD, LOW);
      //Serial.print("dim grater than 10 ");
      else if(dimming<=10)
      digitalWrite(AC_LOAD, HIGH);
      Serial.print("dim less than 10 ");
      attachInterrupt(AC_ZERO_CROSS, zero_crosss_int, RISING);
      Serial.print("in zcd ");

      s = "TRIAC is now ";
      s += (digitalRead(AC_LOAD))?"ON":"OFF";
      s += "<p>Change to <form action='gpio'><input type='radio' name='state_sw' value='1' ";
      s += (digitalRead(AC_LOAD))?"checked":"";
      s += ">TRIAC_ON<input type='radio' name='state_sw' value='0' ";
      s += (digitalRead(AC_LOAD))?"":"checked";
      s += ">TRIAC_OFF <input type='submit' value='Submit'></form></p>";

      s += "SSR is now ";
      s += (digitalRead(AC_LOAD_SSR))?"ON":"OFF";
      s += "<p>Change to <form action='gpio'><input type='radio' name='state_led' value='1' ";
      s += (digitalRead(AC_LOAD_SSR))?"checked":"";
      s += ">SSR_ON <input type='radio' name='state_led' value='0' ";
      s += (digitalRead(AC_LOAD_SSR))?"":"checked";
      s += ">SSR_OFF <input type='submit' value='Submit'></form></p>";

      // s += "LED is now ";/// enable for onboard led
      // s += (digitalRead(BUILTIN_LED))?"ON":"OFF";
      // s += "<p>Change to <form action='gpio'><input type='radio' name='state_led' value='1' ";
      // s += (digitalRead(BUILTIN_LED))?"checked":"";
      // s += ">LED_ON <input type='radio' name='state_led' value='0' ";
      // s += (digitalRead(BUILTIN_LED))?"":"checked";
      // s += ">LED_OFF <input type='submit' value='Submit'></form></p>";

      s += "<p>Change to <form name='state' action='gpio' method='get' autocomplete='on' ><input type='range' name='state_dimmer' id='dimInputId' min='0' max='90' step='10' value='0' oninput='showValue()'>" ;
      s += "<output name='dimOutputName' id='dimOutputId'>0</output></form></p>";
      //s += "<input type='submit' value='Submit'></form></p>";//<span id='range'>0</span>
      s += "<script type='text/javascript'>";
      s += "function showValue()";//newValue
      s += "{";
      s += " ";//document.getElementById('range').innerHTML=newValue;
      s += " document.state.dimOutputId.value = document.state.dimInputId.value;";
      s += " document.forms['state'].submit(); }";// document.forms['state'].submit();
      s += "</script>";

      // s += "<p>Change to <form name='state' action='gpio' method='get' autocomplete='on' ><input type='range' name='state_dimmer' id='dimInputId' min='0' max='90' step='10' value='0' oninput='showValue()'>" ;
      // s += "<output name='dimOutputName' id='dimOutputId'>0</output></form></p>";
      // //s += "<input type='submit' value='Submit'></form></p>";//<span id='range'>0</span>
      // s += "<script type='text/javascript'>";
      // s += "function showValue()";//newValue
      // s += "{";
      // s += " ";//document.getElementById('range').innerHTML=newValue;
      // s += " document.state.dimOutputId.value = document.state.dimInputId.value;";
      // s += " document.forms['state'].submit(); }";// document.forms['state'].submit();
      // s += "</script>";
      server.send(200, "text/html", s);


      Question 1 year ago

      Hi Abhishek,

      I have ESP8266 nodemcu and one single channel AC Dimmer Circuit(zero cross detector) i already uploaded picture + Blynk application(slider up & down and bulb dim & full).I did many try in connection and programming but there are some error and not got proper output like bulb on or off and no dimming and flickering means i cant got proper output like please help me on this please share with me full code and connection diagram.i hope u will your best try.


      1 year ago

      Hello, thank you for your project! I have a question, can I use IGBT instead of MOSFET?


      1 year ago

      Hi, thank you for the project, I am thinking of building it but with more channels.

      One question: why can't there be a single 12V supply for all the mosfets triggering?


      2 years ago

      I've started assembling the components to build this and noticed some improvements to the guide. Under step4: components you're missing a few, namely:

      the 2 fast switching BA159 rectifiers (D1,D7)

      you need 2 not 3 33K resistors (R6, R7)

      you need 3 not 2 10K resistors (R5, R8,R13)

      you need 4 15K resistors (R1,R2,R9,R10)

      missing the capacitors 47uF (C1,C2,C3,C4) and 10uF (C5)

      1 reply

      2 years ago

      Also could I replace the IRF740 with a few IRF730's I have lying around? The difference is that the 740 is rated at 10A and then 730 5.5A.

      1 reply

      Reply 2 years ago

      IRF730 also should work fine,just make sure the power requirement is met with it's rating(i.e wattage,number of lamps you intend to use)


      2 years ago

      Great project, thanks for sharing.

      And I have a question too : is the 10uF capacitor really necessary between the GND and VIN? I'm guessing for stability to prevent restarts but if I look at the NodeMCU schematics I see it already has a 1uF already built into its Power converter unit. Do you have bad experiences without adding the additional capacitor?