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 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 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 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 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 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.