I am trying to create a phase control AC dimmer. But I am not able to achieve smooth dimming. I am using this guide for the circuit:


On the zero detection part I am able to detect its zero crossing, but the output of the zero detection circuit is not a perfect square wave, it's kinda sinoidal.

So I have created my own code that when it reaches a value above 900 (very close to 0v) it will trigger the triac. I am using an Arduino Micro:

#define TPulse 10
#define SW 7
#define ldr A0
#define zeroDetector A1

int x;
int delayDuration = 100;
long int count = 0;

void setup() {
  pinMode(2, INPUT);
  digitalWrite(2, HIGH); // pull up
  pinMode(TPulse, OUTPUT);
  pinMode(SW, INPUT);
  digitalWrite(SW, HIGH);
  digitalWrite(TPulse, HIGH);

void loop() {

 delayDuration = map(analogRead(ldr), 0, 1024, 0, 9000);

 x = analogRead(zeroDetector);

 if (x <= 900)


void isr () {
  digitalWrite(TPulse, LOW);
  digitalWrite(TPulse, HIGH);

I have calculated that in a 60Hz AC it will cross zero voltage 120 times a second thus the delay should be in range of 0 - 8300 microseconds.

But I am not able to achieve a smooth dimming, I am getting either of, flickering, fading (uncontrolled), and so on.

Is there something wrong with my analogy or am I missing something crucial?

I have replaced the LDR with a trimmer pot so I can easily adjust the resistance.

I trying to not use interrupt as of the moment. I am trying to achieve this type of dimming:

enter image description here

  • you can use a schmitt trigger to make a clean square wave from the analog signal. You might not want to use delays, which can cause sync issues if things get busy.
    – dandavis
    Mar 12, 2019 at 18:27
  • first sir i will agree with you that it works with interrupt. but i wanted to go with an approach without using interupt, i am confident that with 16mhz micro it can detect every zero cross
    – Jack
    Mar 12, 2019 at 18:32
  • @dandavis , i dont think there is a work around to that since i will have to delay for a microsecond to chop the ac voltage
    – Jack
    Mar 12, 2019 at 18:34
  • it depends on your "frame rate"; how many times loop() fires. I would only check the level-setting input 1 in 5 loop()s to keep the lanes open for your zero-cross.
    – dandavis
    Mar 12, 2019 at 18:36
  • I apologize sir i could not get what you mean by your last statement. by check level setting you mean the zero cross right?>
    – Jack
    Mar 12, 2019 at 18:46


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.