loading

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

  • R 33K ½ W - 3

  • R 10K ⅛ W - 2

  • R 500 ⅛ W - 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 - "http://arduino.esp8266.com/staging/package_esp8266com_index.json" 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
    https://github.com/esp8266/Arduino

  • Download the source code from the link provided,https://github.com/agkonale/Multichannel-Wireless-Dimmer/tree/master/Arduino

  • 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 ZERO_CROSSING_INT_PIN 12
#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;
    }
    delay(1000);
    DEBUG_PRINT(".");
    i++;
  } 
  DEBUG_PRINTLN("");
  DEBUG_PRINTLN("Connected to ");
  DEBUG_PRINTLN(ssid);
  DEBUG_PRINTLN("IP address: ");
  DEBUG_PRINTLN(WiFi.localIP());
  
  return 0;
}

-

-

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

// WebSocket Connection

void WebSocketConnect() 
{
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

-

-

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; 
          
          NumHandled++;
          if(NumHandled == NumActiveChannels)
          {    
            zero_cross = 0;     
          }
        } 
        else if(isHandled[i] == 0)
        {
          Lvl_Counter[i]++;                     
        }          
     }
   }
  }
}

-

-

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)
  {
    NumActiveChannels++;
  }
  else if(State[Channel_Number] == 1 && ON_OFF == 0)
  {
    NumActiveChannels--;
  }
  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:
      break;
    case WStype_CONNECTED:
      {
        IPAddress ip = webSocket.remoteIP(num);
        lastChangeTime = millis();
        isSynced = 0;
        DEBUG_PRINTLN(ip);
      }
      break;
      
    case WStype_TEXT:
      {
        String text = String((char *) &payload[0]);
        lastChangeTime = millis();
        isSynced = 0;
              
        if(text.startsWith("a"))
        {
          String aVal=(text.substring(text.indexOf("a")+1,text.length())); 
          int Lvl_0 = aVal.toInt();
          Dimming_Lvl[0] = Lvl_0;
          DEBUG_PRINTLN(Lvl_0);
        }
  
        if(text.startsWith("b"))
        {
          String bVal=(text.substring(text.indexOf("b")+1,text.length())); 
          int Lvl_1 = bVal.toInt();
          Dimming_Lvl[1] = Lvl_1;
          DEBUG_PRINTLN(Lvl_1);
        }

	if(text=="ON_0")
        {
          Update_State(1,0);
          DEBUG_PRINTLN("Channel 0 ON!!");         
        }
          
        if(text=="OFF_0")
        {
          Update_State(0,0);
          digitalWrite(Drive_Pin[0], LOW);
          DEBUG_PRINTLN("Channel 0 OFF!!");
        }
         
        if(text=="ON_1")
        {
          Update_State(1,1);
          DEBUG_PRINTLN("Channel 1 ON!!");        
        }
          
        if(text=="OFF_1")
        {
          Update_State(0,1);
          digitalWrite(Drive_Pin[1], LOW);
          DEBUG_PRINTLN("Channel 1 OFF!!");
        }    
      }
      //webSocket.sendTXT(num, payload, length);
      //webSocket.broadcastTXT(payload, length);
      break;

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

-

-

timer_init() function:

void ICACHE_FLASH_ATTR timer_init(void)
{
  //FRC1_SOURCE/NMI_SOURCE
  hw_timer_init(FRC1_SOURCE, 1);
  hw_timer_set_func(dimTimerISR);
  hw_timer_arm(STEP_TIME);
}
  • Trailing_Edge_Dimmer_v5.ino file
#include "hw_timer.h"

#include "dimmer.h"

void setup() 
{
  Serial.begin(115200); 
  pinMode(ZERO_CROSSING_INT_PIN,INPUT);
  
  for(int i=0; i<NUM_CHANNELS, i++)
{
  pinMode(Drive_Pin[i],OUTPUT);<br>  digitalWrite(Drive_Pin[i],LOW);
}
  connectToWiFi();  
  WebSocketConnect();
  MDNSConnect();
  HTTPUpdateConnect();

  noInterrupts();  
  timer_init();
  attachInterrupt(ZERO_CROSSING_INT_PIN,Zero_Crossing_Int,RISING);   
  interrupts();
}

void loop() 
{
  if(millis() - lastConnectivityCheckTime > 1000)
  {
    if(WiFi.status() != WL_CONNECTED) 
    {
      connectToWiFi();
      WebSocketConnect();
      MDNSConnect();
    }  
    lastConnectivityCheckTime = millis();
  }

  else 
  {
    webSocket.loop();
    //yield();
    
    //OTA
    if (millis() - lastTimeHost > 10) 
    {
      httpServer.handleClient();
      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;
    }
  }
}

Note:

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

      http://www.whatimade.today/esp8266-on-websockets-mdns-ota-and-leds/

      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.


      Note:

      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)

      Acknowledgements:

      • Ryan (For many helpful discussions)

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

      <p>Hi, thanks for the project, well explained, I really like :)</p><p>One question, why did you use two N-MOSFET per channel instead of a single TRIAC ?</p><p>Best regards.</p>
      <p>Hi samu-ele,</p><p>The TRIAC based design can only be used for a leading edge dimmer as we can only trigger it to turn ON,while the N-MOSFET design can be configured to work as trailing/leading edge dimmer easily,also trailing edge dimmers have certain benefits over the leading edge ones as highlighted in STEP 2.</p><p>Further the TRIAC needs an impulse to turn on,while the N-MOSFET switch easily follows the control signal.</p><p>Many other colleagues have already made the leading edge dimmers,so I have attempted a new design which can work as both trailing/leading edge dimmer. </p><p>Thanks.</p>
      <p>Thank you for the reply<br>Many thanks ^_^</p>
      <p>Thank you for the project</p><p>Nice project and documentation, keep it up</p>
      <p>Thank you for the appreciation.</p>
      <p>I like the project but unable to download in PDF. There is something wrong with the file.</p>
      I think they allow pdf downloads only for premium membership holders..
      Well, I believe I'm a premium member. I never had problem downloading before.<br>
      <p>I have reported this issue to them,might get resolved soon.</p>
      <p>Much appreciated</p>
      <p>Hi,<br>Good work. I have two questions:<br>1. Can you explain in more detail how MOSFET driver works?<br>2. Can I use this dimmer for LED lamps?<br>Thanks in advance<br><br>Best regards</p>
      <p>1.I agree that the eagle schematic looks slightly unclear(I might have <br>to make better diagrams),so here's more detailed explanation..</p>
      <p>I understood. Thank you very much </p><p>:)</p>
      <p>2.According to my tests in general the answer is no,I was getting some flickering for led lamps because fundamentally many of them have a controlling circuitry to maintain constant current through the leds,hence such methods would prove futile,though one could mod the lamp circuitry to make the dimming work.</p>
      <p>ok. thanks</p>
      <p>Have a closer look at the N-MOSFET diagram attached below.</p>
      <p>Looks like a lot of effort has gone into this. Very well presented.</p><p>This might be just the sort of project that will get me started on using the </p><p>ESP8266. I haven't read it in detail, but with the move away from incandescent lamps to LEDs, I wondered if you had looked at dimming the mains voltage GU10 lamps that are very popular now.</p><p>For what it's worth, some of the wireless commercial LED dimmers that claim to work with LEDs are poor performers. The lamps claim to be dimmable, but in practice the range of dimming is disappointing and far from smooth.</p><p>Personally, I wouldn't attempt to dim commercial GU10s, but would go for a DC low voltage system of lamps which wouldn't have to overcome the GU10 driving innards.</p><p>Thanks for sharing this</p>
      <p>GU10's look interesting,thanks for your appreciation.</p>
      <p>This dimmer works decently for incandescent lamps,yes you are right it <br>performs poorly with led lamps due to the complex controlling circuitry <br>inside.But I feel custom built led lamps could work nicely with trailing<br> edge dimmers.These things aside I actually learnt a lot in this <br>project,Hope it helps others too,thanks</p>
      <p>Beautifully documented project, logical sequence, clean and neat. I work doing stuff like this, congratulations.</p>
      <p>Thank you!!</p>
      <p>Excellent! :)</p>
      Thank you!!
      <p>I would love to have one of these set up for halloween so I could play with the lighting in the house :)</p>

      About This Instructable

      10,362views

      213favorites

      License:

      Bio: Curious and Passionate about Electronics.
      More by abhishek123:Multichannel Wireless Light Dimmer 
      Add instructable to: