Fan speed controller

I dreamed up an extractor fan speed controller for my greenhouse using PWM, an integrator and a staircase comparator driving SSRs. It looks a bit naff but might provide three settings - slow, medium and normal.

Then I bought an extractor fan with a speed controller. Opening up the controller I see it is just a lash-up with a triac and a potentiometer (not even safe in a greenhouse!) THEN i did the research and it seems that although almost everyone recommends the use of a triac the really knowledgeable say what is needed is frequency control.

I understand the frequency argument but cannot find an arduino controlled variable frequency circuit. Am I wasting my time? Does a triac or even an SSR work well enough for my purposes?

There is loads of code for triac control out there some mind boggling complicated and one or two using too many pins on my Nano but I include a simpler version because I don't want to be put right for not including pictures or code. This code can be found at Arduino Playground - HomePage

I'd like some real advice here, preferably based on experience :slight_smile:

// AC Control V1.1
//
// This Arduino sketch is for use with the heater 
// control circuit board which includes a zero 
// crossing detect function and an opto-isolated TRIAC.
//
// AC Phase control is accomplished using the internal 
// hardware timer1 in the Arduino
//
// Timing Sequence
// * timer is set up but disabled
// * zero crossing detected on pin 2
// * timer starts counting from zero
// * comparator set to "delay to on" value
// * counter reaches comparator value
// * comparator ISR turns on TRIAC gate
// * counter set to overflow - pulse width
// * counter reaches overflow
// * overflow ISR turns off TRIAC gate
// * TRIAC stops conducting at next zero cross


// The hardware timer runs at 16MHz. Using a
// divide by 256 on the counter each count is 
// 16 microseconds.  1/2 wave of a 60Hz AC signal
// is about 520 counts (8,333 microseconds).


#include <avr/io.h>
#include <avr/interrupt.h>

#define DETECT 2  //zero cross detect
#define GATE 9    //TRIAC gate
#define PULSE 4   //trigger pulse width (counts)
int i=483;

void setup(){

  // set up pins
  pinMode(DETECT, INPUT);     //zero cross detect
  digitalWrite(DETECT, HIGH); //enable pull-up resistor
  pinMode(GATE, OUTPUT);      //TRIAC gate control

  // set up Timer1 
  //(see ATMEGA 328 data sheet pg 134 for more details)
  OCR1A = 100;      //initialize the comparator
  TIMSK1 = 0x03;    //enable comparator A and overflow interrupts
  TCCR1A = 0x00;    //timer control registers set for
  TCCR1B = 0x00;    //normal operation, timer disabled


  // set up zero crossing interrupt
  attachInterrupt(0,zeroCrossingInterrupt, RISING);    
    //IRQ0 is pin 2. Call zeroCrossingInterrupt 
    //on rising signal

}  

//Interrupt Service Routines

void zeroCrossingInterrupt(){ //zero cross detect   
  TCCR1B=0x04; //start timer with divide by 256 input
  TCNT1 = 0;   //reset timer - count from zero
}

ISR(TIMER1_COMPA_vect){ //comparator match
  digitalWrite(GATE,HIGH);  //set TRIAC gate to high
  TCNT1 = 65536-PULSE;      //trigger pulse width
}

ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW); //turn off TRIAC gate
  TCCR1B = 0x00;          //disable timer stopd unintended triggers
}

void loop(){ // sample code to exercise the circuit

i--;
OCR1A = i;     //set the compare register brightness desired.
if (i<65){i=483;}                      
delay(15);                             

}

If you want to use a (mains) AC motor, a triac is almost the only way to control it. For safe connection an opto-coupled triac can be used. Speed can not be controlled directly, you only can specify a certain duty cycle, like a PWM signal. For only slow/medium/normal operation three duty cycle values should be sufficient. But unless ordinary PWM, the output signal must be synchronized to the AC zero crossing.

I'm not sure how the triac gate is connected. In general it's required to trigger the triac, some time after zero crossing, and to remove the trigger before the next zero crossing. The lower the pre-trigger delay, the faster the motor turns. Also take care to catch both negative and positive zero crossings.

For testing purposes you can send the delay (OCR1A value) from Serial monitor, to find out which values yield the desired fan speed.

Are you advising me that a variable frequency controller for the usual synchronous motor is a no-no? That would explain the absence of circuits.

Another problem I have is whether it is better (and cheaper) to use discrete triacs rather than an SSR which does not include a zero crossing detector.

The link I gave previously should have read [http:/playground.arduino.cc/Main/ACPhaseControl]. It includes a simple circuit diagram which I don't seem to be able to attach here.

What I suppose I am really asking is for someone to explain the code which is by far the simplest I have come across and I know some helpful person will tell me I should be able to do that after 129 posts! However, I am working on it.

I don't know how to build a variable frequency controller for mains voltage, and whether it's usable with your fan. If you want to use a SSR instead of a triac, it may work as well.

You'll have to know about timers and interrupt service routines (ISR). The first ISR starts timer 1 at every zero crossing interrupt, the second one (compare match) triggers the triac after OCR1A timer ticks, and sets the timer to 4 ticks (pulse width) before overflow. The third (timer overflow) interrupt resets the triac trigger and stops the timer.

There's not really a good way of converting AC power to a different frequency except rectifying it and putting it into an inverter.

TRIAC control isn't really the right term for it. Your link has it right: it is phase control.

I don't really know how to do better than the Timing sequence comment block in explaining the code. the only potential confusion I see is the word "comparator"; this is referring to the output compare functionality of the timer, not the analog comparator module. The Timer1 peripheral is used fire the TRIAC, and all of the control is done using interrupts. All you need to do is define the pulse width and set OCR1A to be the firing delay (higher values will result in lower power delivered). If you ever want to stop the TRIAC, you just need to detach the zeroCrossingInterrupt. Attach it again when you want to start up.

So, I would like to try out the code from Arduino playground which I have already mentioned. I am assuming the 'circuit diagram' has a reversed connection at JP3 and Dig Out goes via R4 to the MOC3052.

First of all, there seems to be two new libraries: avr/io and avr/interrupt. HOwever I am having difficulty in finding these.

I understand that D2 on the Nano handles interrupts. I'm not sure what this means (the handling not the interrupt) does this apply to D9 also?

Am I wrong in assuming the triac is continuously controlled? I would prefer that control would only need checking every couple of minutes. Is this immaterial?

I am assuming the 'circuit diagram' has a reversed connection at JP3 and Dig Out goes via R4 to the MOC3052.

No. dig out is from the H11AA1 and is connected to the zero cross interrupt pin of the arduino.

dig in is going to the MOC and is coming from pin 9 of the arduino.

First of all, there seems to be two new libraries: avr/io and avr/interrupt. However I am having difficulty in finding these.

The libraries are part of the IDE. I believe they are included automatically and you may not need the separate #include statements.

I understand that D2 on the Nano handles interrupts. I'm not sure what this means (the handling not the interrupt) does this apply to D9 also?

D2 is an external interrupt pin on the nano. "Handling" means that the code in the interrupt service routine (isr) will respond to the interrupt and perform what needs to be done when the interrupt occurs.
This is the interrupt handler on D2. Output on D9 is 'handled' by two different interrupts on Timer1.

void zeroCrossingInterrupt(){ //zero cross detect   
  TCCR1B=0x04; //start timer with divide by 256 input
  TCNT1 = 0;   //reset timer - count from zero
}
Am I wrong in assuming the triac is continuously controlled? I would prefer that control would only need checking every couple of minutes. Is this immaterial?

I'm not sure what you mean here. Yes, the triac is controlled every ac cycle. If you want to change the control point every couple of minutes that is no problem.

Adrifran39:
So, I would like to try out the code from Arduino playground which I have already mentioned. I am assuming the 'circuit diagram' has a reversed connection at JP3 and Dig Out goes via R4 to the MOC3052.

Correct, the schematic has them backwards.

First of all, there seems to be two new libraries: avr/io and avr/interrupt. HOwever I am having difficulty in finding these.

Don't worry about them. They are automatically included by the Arduino IDE anyway, so there's no need for them to be separately included in the sketch.

I understand that D2 on the Nano handles interrupts. I'm not sure what this means (the handling not the interrupt) does this apply to D9 also?

A Nano is basically just an Uno with a different board shape. D2 and D3 are the interrupt inputs. D9 is an output being controlled by the ISR, it's not triggering the ISR.

Am I wrong in assuming the triac is continuously controlled? I would prefer that control would only need checking every couple of minutes. Is this immaterial?

It is, and it must be, because the gate has to be triggered every half cycle (2x the mains frequency). However, you don't need to do any micromanaging in your sketch. Once you attach the interrupt in setup, it's all handled automatically in the background by the zeroCrossingInterrupt, ISR(TIMER1_COMPA_vect), and ISR(TIMER1_OVF_vect) functions.

Correct, the schematic has them backwards.

I disagree. For some reason, the diagram is written from the perspective of the MOC and the H11AA1 and not the Arduino.

It confused me but when viewed from viewpoint of the H1AA11 and MOC I take the point.

So there is a zero-crossing detector initiating an interrupt, in response to which the Nano sends a switch on signal to the triac via the MOC and the positionof this signal on the sine wave decides how much of the sine wave is used?

If I have this right, then there is one problem left I think. Looking at the loop function in the code, I do notunderstand how the triac on period is controlled,

void loop(){

i--; // what does this mean?

OCR1A=1; //?

if (i<65)i=483;  //?

delay(15);
}

OCR1A is commented as initialising a comparator, what comparator would that be? I looked at the Atmega datasheet and am still recovering!

Please point me to somewhere that simply explains the significance of OCR1A, TIMSK1, TCCR1A and TCCR1B.

OCR1A is commented as initialising a comparator, what comparator would that be?

Squint a little harder!

OCRA1 is the output compare register for the "CTC" mode of the timer. The code is setting delay intervals ranging from 65 to 483 timer counts.

Please point me to somewhere that simply explains the significance of OCR1A, TIMSK1, TCCR1A and TCCR1B.

Here are some summaries.

http://www.avrbeginners.net/architecture/timers/timers.html

Thanks - I'll do a little squinting at the links!!! (I've just had a cataract removed and squinting is the right word!!)

Adrifran39:
If I have this right, then there is one problem left I think. Looking at the loop function in the code, I do notunderstand how the triac on period is controlled,

A TRIAC turns itself off automatically when the current goes below a certain threshold. In fact, it's impossible to turn it off any other way. Removing the gate signal while current is still flowing does nothing.

The only thing you can do with a TRIAC (and its DC cousin the SCR) is turn it on. You have no control over when it turns off. That's why such a fuss is made over measuring the zero crossing and timing the trigger signal to happen at a specific time after that.