Controlling two AC devices, device turning on incorrectly

I am making use of the code below to control the speed of an AC fan and the intensity of an AC Lamp with an Uno.

The problem I am having is that, when I set the lamp intensity to low or medium, the fan turns on at a very low speed as well, and I cannot turn it off even when setting the fan to off.

Also if I turn the lamp on and then off, the fan (which is still set as off), will spin slowly for a second or two in random intervals.

For troubleshooting purposes, I did separate this program into two programs, controlling each device and its circuit separately, and it works perfectly, but when I combine them, I get the above problem.

Any assistance in troubleshooting or ideas to solve this would be appreciated. Haven't attempted AC control before.

int PWM = 3;
int FAN = 4;
int dimming;

void setup()
{
  Serial.begin(9600);
  Serial.println("Serial connection started, waiting for instructions…n0 =     Offn1 = 25%n2 =50%n3 = 75%n4 = 100%");
  pinMode(PWM, OUTPUT);
  pinMode(FAN, OUTPUT);

  attachInterrupt(0, zero_crosss_int, RISING);
}

void zero_crosss_int()
// function to be fired at the zero crossing to dim the light
{
  int dimtime = (75 * dimming);  // For 60Hz =>65
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(FAN, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
  //(for 60Hz use 8.33)
  digitalWrite(FAN, LOW);    // triac Off
}


void loop ()
{
  if (Serial.available()) {
    char ser = Serial.read(); //read serial as a character


    switch (ser)
    {

      /* Lamp Control  */

      case '0':
        analogWrite(PWM, 0);  //lamp Off
        break;
      case '1':
        analogWrite(PWM, 50);  //lamp low
        break;

      case '2':
        analogWrite(PWM, 130); //lamp medium
        break;

      case '3':
        analogWrite(PWM, 255); //lamp high
        break;

      /* Fan Control  */


      case '4':
        dimming = 128;  //fan off
        break;

      case '5':
        dimming = 90; //fan low
        break;

      case '6':
        dimming = 65; //fan medium
        break;

      case '7':
        dimming = 35; //fan high
        break;

      default:
        Serial.println("Invalid entry");

    }
  }
}

The circuits it controls is based on these:

Lamp

Fan

The code and the circuits are based on these posts:

Lamp Dimmer

Fan Dimmer

It sounds more like a hardware issue than a software issue.
There is probably a "crosstalk" between the AC lines caused by the control circuit you
are using causing the triac to turn on. The control circuit is turning an inductive load connected
to an AC line on when there is a high voltage on it which can cause the issues you are facing.

If you have long wires connected to the fan and lamp and these wires are close to each other
you have to separate them or add some sort of filtration.
Also, a triac can be turned on by high voltage peaks on its inputs.
Read this thread for more details about triacs: http://www.avrfreaks.net/forum/triac-photocoupler-or-without-zero-crossing

If the lamp is disconnected, I still get the same problem. Disconnecting the lamp circuit completely from the Arduino, I still get the fan randomly spinning for a short burst if I set the lamp to turn on at low or medium with the code. It's almost as if the PWM signal is controlling the fan or interfering.

post the combined program.

I assume your wiring is totally separate so that the pin for the light and the pin for the fan output are not sharing any circuitry.

I would also add the request of a photo of the wiring.
alternatively your hand drawn schematic of how you have things connected

is your indicating LED lighting up for the MOC3051 ??

imo92:
If the lamp is disconnected, I still get the same problem. Disconnecting the lamp circuit completely from the Arduino, I still get the fan randomly spinning for a short burst if I set the lamp to turn on at low or medium with the code. It's almost as if the PWM signal is controlling the fan or interfering.

considder a way to pull down the signal hard on the opto

dave-in-nj:
post the combined program.

I assume your wiring is totally separate so that the pin for the light and the pin for the fan output are not sharing any circuitry.

I would also add the request of a photo of the wiring.
alternatively your hand drawn schematic of how you have things connected

is your indicating LED lighting up for the MOC3051 ??

I may have been confusing, but what I posted is the combined programming. I commented showing the part that controls the lamp, which uses PWM.

The circuits were followed exactly as I posted. I could provide a picture soon if I get a moment.

Yes, the wiring is totally separate, although both circuits share the same ground and 5v from the Arduino, although I doubt that makes a difference.

The output for the fan uses pin 4. The output for the Lamp uses pin 3.

The problem is in the use of delay(). The computer can't do anything during delay, especially when the delay is in an interrupt routine, something you should avoid at all costs.

So, with two devices, the best you can do is hit every other zero crossing per device, and get only half the power.

In your case the interrupts are probably stacking, which means that they execute consecutively and the timing for the second triac firing is completely wrong.

You need a completely different approach.

If the lamp is disconnected, I still get the same problem. Disconnecting the lamp circuit completely from the Arduino, I still get the fan randomly spinning for a short burst if I set the lamp to turn on at low or medium with the code. It's almost as if the PWM signal is controlling the fan or interfering.

Are you saying that with no lamp circuit and nothing attached to pin 3 that if you put a pwm signal on pin 3 you will get an interaction with pin 4 and the fan control?

What happens if you put the fan on pin 12?

cattledog:
Are you saying that with no lamp circuit and nothing attached to pin 3 that if you put a pwm signal on pin 3 you will get an interaction with pin 4 and the fan control?

What happens if you put the fan on pin 12?

That's exactly it, I completely removed the lamp circuit and all connections to the Arduino, but for some reason, triggering the PWM signal (pin 3 for the lamp) for low or medium intensity, randomly jolts the fan at times. Just moved it to pin 12 and it did the same. I don't know if there's some strange interaction between the PWM signal and AC control of the fan.

I believe my circuits are wired correctly, as I wouldn't be able to control the lamp intensity and the fan speed correctly, when testing both circuits individually with their individual code.

This makes me think it's a coding issue but I cannot crack it. I feel it's something to do with the Zero cross detection and the dimming value.

Then again these are just my assumptions. Still working on it.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

A complete circuit diagram, including your 220Vac wiring and fan and lamp please.
Also a picture of your project will help us to see your component layout.

Thanks.. Tom.. :slight_smile:

I feel it's something to do with the Zero cross detection

See reply #6

Hi,
How are you powering the control circuit?

Tom... :slight_smile:

jremington:
See reply #6

I see what you are saying. I actually did read that you shouldn't use a delay() in an interrupt routine somewhere in this forum, but lacked the confidence or knowledge to make changes to the code. Any idea on a method I could implement or look into?

TomGeorge:
Hi,
How are you powering the control circuit?

Tom... :slight_smile:

I will try to upload a picture soon, however I followed the circuits I attached in the opening post exactly as they are. Each circuit has its own power cable supplying 220v AC.

5v and GND is supplied from the Arduino.

The dimmer signal goes to pin 4 on the Arduino.
The zero cross goes to pin 2 on the Arduino.

The PWM signal goes to pin 3 on the Arduino

Any idea on a method I could implement or look into?

You simply cannot use delay() in this application, if you have more than once AC device to control.

Study the "blink without delay" example that comes with the Arduino, or how to do several things at once to see timing is done in a real time application such as yours. You will need to use micros() to read out the time in microseconds and make decisions. Use unsigned long variables for times.

It is not simple to control two AC devices with one zero crossing detector. My own approach would be to program one of the timers to give two or more different "compare match" interrupts at the appropriate time, in one AC line timing cycle. Then the computer could be doing other things entirely.

I don't think that @imo92 is using the zero cross with the lamp circuit.

Is he even running the lamp with AC, given the diode bridge and the pwm to the power mosfet?

Can someone explain the lamp circuit?

Still, if he removes the lamp circuit entirely, but runs pwm to an open pin3 he states that the fan will turn on.

cattledog:
I don't think that @imo92 is using the zero cross with the lamp circuit.

Is he even running the lamp with AC, given the diode bridge and the pwm to the power mosfet?

Can someone explain the lamp circuit?

Still, if he removes the lamp circuit entirely, but runs pwm to an open pin3 he states that the fan will turn on.

Try this link,

The control can be PWM and not synched to the AC.

Tom... :slight_smile:

So I was advised to make this change to my zero cross detection:

void zero_crosss_int()
// function to be fired at the zero crossing to dim the light
{
 if (dimming > 96) // choose this value experimentally, adding some margin
    return;

  int dimtime = (75 * dimming);
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(FAN, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
  //(for 60Hz use 8.33)
  digitalWrite(FAN, LOW);    // triac Off
}

The design of the zero_crosss_int() ISR is unreliable. After each interrupt it unconditionally turns on the triac, even in the OFF position. Since the dimming value in that case is close to the AC cycle duration, it may miss the current cycle and turn on early in the next cycle. This may happen e.g. due to noise in zero crossing input.

75 us * 128 = 9.6 ms. Assuming 50 Hz AC, cycle duration is 1000 ms / 100 = 10 ms. You only have 4% margin.

You need to avoid turning on the triac close to the end of the AC cycle. Limit the maximum value of dimming variable to, say, 75% of the AC cycle. This will impose a lower limit on the output power. However, you want to do this anyway because motors need a minimum power to start rotating. Adjust the ISR so that in the OFF position it does not send a positive pulse at all.

So you just need to add an if statement to you ISR code

And this solved my problem! Both the lamp circuit and the fan are working together perfectly.

However, the IRF830 MOSFET is over heating, seems like the Drain pin is getting hot.

To be honest I'm still trying to understand why this works or why this new problem comes about, I'm still trying to tinker and figure it out. Any thoughts?

Any thoughts?

Post your combined code, and combined wiring diagram.

Okay guys its working by adding :

if (dimming > 96) 
    return;

To the zero_crosss_int() function.

jremington:
Post your combined code, and combined wiring diagram.

OKAY SO, my combined program is nothing more than my initial program posted, with this new IF statement:

int PWM = 3;
int FAN = 4;
int dimming;

void setup()
{
  Serial.begin(9600);
  Serial.println("Serial connection started, waiting for instructions…");
  pinMode(PWM, OUTPUT);
  pinMode(FAN, OUTPUT);

  attachInterrupt(0, zero_crosss_int, RISING);
}

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

  if (dimming > 96) // choose this value experimentally, adding some margin
    return;

  int dimtime = (75 * dimming);
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(FAN, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
  //(for 60Hz use 8.33)
  digitalWrite(FAN, LOW);    // triac Off
}


void loop ()
{
  if (Serial.available()) {
    char ser = Serial.read(); //read serial as a character


    switch (ser)
    {

      /* THIS CONTROLS THE LAMP USING PWM  */

      case '0':
        analogWrite(PWM, 0);  //lamp off
        break;
      case '1':
        analogWrite(PWM, 50);  //lamp low
        break;
      case '2':
        analogWrite(PWM, 130); //lamp medium
        break;
      case '3':
        analogWrite(PWM, 255); //lamp high
        break;

      /* THIS CONTROLS THE FAN USING DIMMER SIGNAL  */


      case '4':
        dimming = 128;  //fan off
        break;
      case '5':
        dimming = 90; //fan low
        break;
      case '6':
        dimming = 65; //fan medium
        break;
      case '7':
        dimming = 35; //fan high
        break;
      default:
        Serial.println("Invalid entry");

    }
  }
}

As for my circuits, all I did was implement each circuit on its own breadboard (I know not the best option but its all I have available to me), and sent the relevant signals to an Arduino from each circuit. (These circuits are attached in the opening post)

FAN

Dimmer Signal to pin 4 of Arduino
ZeroCross signal to pin 2 of Arduino

Lamp

PWM signal to pin 3 of Arduino.

5v and GND was taken from the Arduino where needed.

Each circuit was supplied with 220v according to the diagram with a power cable from a wall power outlet.
The circuits worked. They faded AC device correctly. I tested them individually, with their own code, which I got from these posts.

Fan AC Dimmer

PWM Dimmer

So the problem was a software issue. The problems arised when I tried to combine these programs into one. The PWM Dimmer signal conflicted with the zero cross detection in some way.

And by adding

if (dimming > 96) 
    return;

They no longer conflict.

I think the MOSFET in the LAMP circuit was always heating up, I just never noticed it before.

I used a LM35dt temperature sensor to monitor the MOSFET, it heated to a temperature of around 60 degrees, but remained operational, and the circuits continued to work fine, so will probably get a heat sink to help with that.

As to why this IF statement fixes my code.. I am still trying to understand that.

@jremington I am still trying to read up on an alternate method to using delays in the ISR, but for now this solution seems to work.