Multichannel Wireless Light Dimmer

40,942

276

66

Introduction: 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 - "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 !!

      Lights Contest 2017

      Participated in the
      Lights Contest 2017

      1 Person Made This Project!

      Recommendations

      • Puzzles Speed Challenge

        Puzzles Speed Challenge
      • "Can't Touch This" Family Contest

        "Can't Touch This" Family Contest
      • CNC Contest 2020

        CNC Contest 2020

      66 Discussions

      0
      rama17
      rama17

      Question 2 days ago

      Hi,
      Nice work.
      I think there is a small change in ZCD. as it always be always low and hign when ZCD detected. As the GPIO is Pulledup but As the is Sinosoidal signal Opto will be on so Signal will be ground and when the ZCD is present we get high

      0
      AnoopPadmanabhan
      AnoopPadmanabhan

      Question 13 days ago on Step 6

      Hi, Does this work with regular LED drivers? Does the LED flicker ?

      0
      Minura Manudewa
      Minura Manudewa

      3 months ago

      In your circuit load's neutral goes through the MOSFETS. is the other way possible. The live wire goes through the MOSFETS and then goes through the load??? And also if we supply 12v to the gate (using the 4n35 ) can we connect the grounding resistor at gate of the MOSFET negative of the 12v supply instead of the source and drain pins of the MOSFETS???????

      0
      IvanÁ99
      IvanÁ99

      Question 8 months ago

      Thank You for great project.
      Im thinking, if is possible to do with Nodemcu, old Christmas lights to automatically dimming and lightening. By Wifi set up the level of light, and dimming effect. Does anybody help?

      0
      IvanÁ99
      IvanÁ99

      Answer 8 months ago

      when I do http request for dimming, I would like to stay inside procedure while, where is dimming to zero and after achieving, grows back to high, infinity loop.
      waiting inside in this tube for another request to turn off device.
      Offcourse with zero detection. But NodeMCU automatically detect failure in running of program and reset itself.

      0
      Voter1234567
      Voter1234567

      Tip 8 months ago

      Hi, Great project.
      I am going to build this very shortly.
      I have decided to cut down the part count in couple of areas, for instance the zero cross over parts are now replaced with H11A1and two resistors.
      Once again excellent work, looking forward to purchasing the parts and programming my esp32.

      0
      modicon1
      modicon1

      Question 9 months ago on Step 4

      Hello. What are the voltage ratings of capacitors C1 and C2?

      Thanks for the great project.

      0
      FelizA1
      FelizA1

      11 months ago

      Hello, Excellent post and great project.
      I uploaded the code exactly as I downloaded it, just change wifi info. And it doesn't work, I only have WDT resets, can you help me?

      0
      ryan141298
      ryan141298

      Question 1 year 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?

      0
      paul-k
      paul-k

      Answer 1 year ago

      Once a triac has been fired you cannot turn it of but have to wait for the voltage flowing through it drops to zero. So it is not possible to do trailing edge phase cutting with a triac

      0
      ryan141298
      ryan141298

      Reply 1 year ago

      So what's the problem with using leading edge?

      0
      paul-k
      paul-k

      Reply 1 year ago

      Depends on your use case:
      Leading-edge could be used for: inductive loads (e.g. magnetic low voltage transformers), resistive loads (e.g. incandescent).

      Trailing-edge could be used for: capacitive loads (e.g. electronic low voltage transformers, LED drivers), resistive loads (e.g. incandescent).

      More details on the different phase cutting methods can be found using google ;-)

      E.g:
      https://www.lyco.co.uk/advice/dimmers-trailing-vs-leading-edge/

      0
      kumaran512
      kumaran512

      Question 1 year ago

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

      0
      paul-k
      paul-k

      Answer 1 year ago

      If it is a single phase AC motor it should work. The level of control in regards to the RPM will probably be within certain limits though (not complete linear regulation from 0 to max RPM).
      Also you need to make sure not to exceed the power ratings of the MOSFET/IGBT used.

      0
      paul-k
      paul-k

      1 year ago

      Great tutorial. Could you explain how you calculated the 66k resistor for the zero crossing circuit? You stated that the same circuit would also work with 120 V so I am just wondering if this applies for all resistor values. If I calculated it correctly with 66K at 120V there would be about 2 mA flowing thought the optocoplers LED. Couldn’t find the right part in the data sheet about the minimum current that needs to be applied

      0
      KevinP295
      KevinP295

      2 years ago

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

      0
      paul-k
      paul-k

      Reply 1 year ago

      Yes, you can use IGBTs, but you need to refer to the data sheets to check to go for a low RDS on value and maximum load as well as the needed voltage level on the gate for full on state.

      0
      1502santosh
      1502santosh

      Question 2 years 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);
      Serial.begin(9600);
      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
      while(digitalRead(14)==0)
      {
      }
      digitalWrite(0, LOW); // triac Off
      }
      }
      void loop() {
      Blynk.run();
      }
      BLYNK_WRITE(V12) //Button Widget is writing to pin V12
      {
      dim=param.asInt();
      }

      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 ( "" );
      //InitInterrupt(do_something);
      // 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 );
      server.begin();
      Serial.println ( "HTTP server started" );
      }

      void loop ( void ) {
      server.handleClient();
      }


      void InitInterrupt(timercallback handler,int Step )
      { Step=dimming*Step;
      timer1_disable();
      timer1_isr_init();
      timer1_attachInterrupt(handler);
      timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
      timer1_write(Step);//max8388607//75*5
      }

      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
      //
      // }
      }
      timer1_disable();
      }


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

      zero_cross = true;
      i=0;
      //InitInterrupt(do_something);
      digitalWrite(AC_LOAD, LOW);
      InitInterrupt(do_on_delay,freqStep);

      }


      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();
      detachInterrupt(AC_ZERO_CROSS);
      delay(7);
      Serial.print("Light switched via web request to ");
      Serial.println(state_sw);
      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 ");
      Serial.println(state_led);
      }
      // 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 ");
      Serial.println(state_dimmer);
      dimming =127-state_dimmer;
      //delay(10);
      if(dimming>=120)
      {
      detachInterrupt(AC_ZERO_CROSS);
      delay(7);
      digitalWrite(AC_LOAD, LOW);
      //Serial.print("dim grater than 10 ");
      }
      else if(dimming<=10)
      {
      detachInterrupt(AC_ZERO_CROSS);
      delay(7);
      digitalWrite(AC_LOAD, HIGH);
      Serial.print("dim less than 10 ");
      }
      else
      {
      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);

      }
      cabb6325fde34af9.jpg
      0
      paul-k
      paul-k

      Answer 1 year ago

      triacs can not be used for trailing edge phase cutting. Can only perform leading edge phase cutting with triacs

      0
      jon123456
      jon123456

      Question 2 years 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.