A place to put your YouTube video that is ESP8266 related.

User avatar
By freedom2000
#38323 Schematics are on page one of this thread.
Source code :

Code: Select all#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

Browse to IP of ESP. Use GET variables to configure settings:
b = brightness (0-200)
ex1: View current settings (json): http://ip.of.esp/
ex2: Set brightness to 50% : http://ip.of.esp/?b=100

const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

const byte zcPin = 2;
const byte outPin = 13;

int curBrightness = 0;
int dimDelay;

ESP8266WebServer server(80);

void setup(void)
  pinMode(zcPin, INPUT);
  pinMode(outPin, OUTPUT);

  digitalWrite(outPin, 0);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {

  Serial.print("\nConnected: ");
  server.on("/", []()
    if (server.arg("b") != "")
      curBrightness = (byte) server.arg("b").toInt();
      if (curBrightness > 200) curBrightness = 200; //more and the light will flick...
      dimDelay = (200-curBrightness)*40;     //50Hz = 20000µs per period.... 10000 µs per half period
    String s = "{\n   \"b\":";
    s += curBrightness;
    s += "\n}";
    server.send(200, "text/plain", s);
  Serial.println("HTTP server started");
  attachInterrupt(zcPin, zcDetect, FALLING);  //falling edge has the more delay, so easier to synchronize than rising edge...

void loop(void)
  server.handleClient();              //Do Wifi stuff

void zcDetect()                       // Interupt routine to handle zero crossing
    if (curBrightness == 0)
      digitalWrite(outPin, 0);        //fully shut down the triac
    else if (curBrightness == 200)
      digitalWrite(outPin, 1);        //fully open the triac
      delayMicroseconds(dimDelay);    //wait "delay" for first half period
      digitalWrite(outPin, 1);        //generate the pulse for the MOC input
      digitalWrite(outPin, 0);
      delayMicroseconds(9900);        //jumpt to the second hald period
      digitalWrite(outPin, 1);        //generate the pulse for the MOC input
      digitalWrite(outPin, 0);

Quite simple by the way !

User avatar
By bkrajendra
#38388 Thanks a lot @freedom2000 for sharing the Code.

I'm also working on AC dimmer, I've tried lot of option for this with ESP. Basically my designs were based on ESP interrupt. But I found it to be very sensitive to noise and false triggering may create problems. also i found it really difficult to avoid flicker.
I'll definitely give try to your code. But the problem is as you are not using any interrupt your code is continuously bzy in reading input. This will interfere with WiFi or webrequest. Or may bay if webrequest stucks, it will disrupt the Triac trigger.
Basically I was planning to have 8 channel AC dimmer for Resistive and Inductive loads used for Home appliances. Managing different timing for triac trigger is challenging.

I think using dedicate microcontroller for this dimer may solve the issue....!
Let me know if you have any though over this.

Take a look at code im using for single channel dimmer:
Code: Select allint AC_LOAD = 3;    // Output to Opto Triac pin
int dimming = 128;  // Dimming level (0-128)  0 = ON, 128 = OFF

void setup()
  pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
  attachInterrupt(0, zero_crosss_int, FALLING);  // Choose the zero cross interrupt # from the table above

//the interrupt function must take no parameters and return nothing
void zero_crosss_int()  //function to be fired at the zero crossing to dim the light
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms
  // Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle)
  // For 60Hz => 8.33ms (10.000/120)
  // 10ms=10000us
  // (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65

  int dimtime = (78*dimming);    // For 60Hz =>65   
  delayMicroseconds(dimtime);    // Wait till firing the TRIAC
  digitalWrite(AC_LOAD, HIGH);   // Fire the TRIAC
  delayMicroseconds(10);         // triac On propogation delay (for 60Hz use 8.33)
  digitalWrite(AC_LOAD, LOW);    // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC

void loop()  {
  for (int i=5; i <= 125; i++){

User avatar
By freedom2000
#38431 Hi,

I do use interrupt for the zero detection of the first half of the sine wave
After I do stay into the interrupt routine and I leave time (enough) for the wifi task to be done at the end of this interrupt routine.

I believe that with the same code you can easily drive more triacs as a single zero detect will work for all of them.
You just have to sort the delays and trigger the outputs accordingly

But keep some time at the end of the routine for wifi tasks !
BTW, the end of the sine carries only a very limited part of the main power. So you can "cut" this end without seeing anything. This does the trick

Beware also that I wanted to use two interupts (one for each alternance) but the opto I gave used is definitively not symetrical...
That's also the reason why I use one single intrupt, and when synchronized I do the rest of the job with delays.

Beware also that the timings in my code are for European Mains... 50Hz
Must be tuned for 60Hz :mrgreen: