Controlling fan speed with Photon and FET transistor

@mohitagnihotri, @Omer’s fan is DC whereas your ceiling fan uses AC so the circuits will be vastly different. His design can’t be applied to your fan.

Hi @peekay123,

Thank you for telling me. I want to control AC fan speed. I found many post related with fan speed in the community but didn’t find any working solution for me.

Can you please guide me here? I did following thing but it is not working ultimately. Can you find, why is it not working?

My schematic is

My code is

//Code is based on 220V 50Hz AC

int AC_LOAD = A4;   // 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(A4, zero_crosss_int, RISING);  // 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 = (75*dimming);       
  delayMicroseconds(dimtime);    // Wait till firing the TRIAC
  digitalWrite(AC_LOAD, HIGH);   // Fire the TRIAC
  delayMicroseconds(10);         // triac On propogation delay 
  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 <= 128; i++){
    dimming=i;
    delay(10);
   }  
}

Thanks!

@mohitagnihotri, the code is not working because your hardware does not match the code! The code is expecting a zero-crossing signal which generates an interrupt. Your circuit does not have that zero-crossing detector. Did you find the code in this forum? What about the circuit?

You may want, for the sake of safety and simplicity, to look at this board on Tindie:

https://www.tindie.com/products/bugrovs2012/1ch-ac-dimmer-module-controller-board/?pt=full_prod_search

It will do exactly what you want, is compatible with the Photon and the code is essentially idential to the one you posted. :wink:

Hi @peekay123, Thank you so much :smile:

I found the code and schematic from here: http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/?ALLSTEPS

I think, if I would choose the following the circuit then it should work. Is it compatible with the Photon and their code too?

@mohitagnihotri, yes the circuit will work and the code will also with minor modifications. I caution you that working with 220V can be fatal if not done properly.

@peekay123, thanks again. Definitely, I’ll do with proper attention.
I’ll notify you here, if I succeed.

I'm going to second that. If you're not comfortable with working with mains, then please, do not attempt to DIY it. It may cost you more than you bargained for, and that's just not worth it.
Unless you can guarantee proper and safe practice around working with mains, hire a professional. Mains is not something to be messed with and will kill you if handled improperly.
Depending on where you're located you might also be subjected to a variety of regulations prohibiting you from tampering with mains unless certified. If you fail to meet these, you may get fines, and insurances might not cover you in case of accidents.
Thread carefully.

1 Like

@peekay123 I did it :smile: Thank you so much!

Now, it is working with Fan and Bulb both.

Check here: https://goo.gl/MMBp7f

2 Likes

I am also working on similar thing. do you mind sharing the final circuit and code?

Thank you

Hi @ketan_r

The circuit is same as above and final code is:

volatile int i=0;               // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = A4;                // Output to Opto Triac
int dim = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff
int inc=1;                      // counting up or down, 1=up, -1=down

int freqStep = 75;    // This is the delay-per-brightness step in microseconds.
                  // For 60 Hz it should be 65
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want. 
// 
// Realize that there are 2 zerocrossing per cycle. This means
// zero crossing happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply. 

// To calculate freqStep divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps. 
//
// (120 Hz=8333uS) / 128 brightness steps = 65 uS / brightness step
// (100Hz=10000uS) / 128 steps = 75uS/step
Timer timer(0.075, dim_check);

void setup() {                                      // Begin setup
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  attachInterrupt(A0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  timer.start();                                   // Initialize TimerOne library for the freq we need
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is 
  // the right time to fire the triac.  This function 
  // will now run every freqStep in microseconds.                                            
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);       // turn off TRIAC (and AC)
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
if(i>=dim) {                     
  digitalWrite(AC_pin, HIGH); // turn on light       
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
} 
else {
  i++; // increment time step counter                     
}                                
  }                                  
}                                   

void loop() {                        
  dim+=inc;
  if((dim>=128) || (dim<=0))
inc*=-1;
  delay(18);
}

This will not work as you expected since software timers have a minimum resolution of 1ms (the time is defined as an unsigned integer!). I'm not sure why the compiler didn't flag that. I'm also not sure what happens when you pass a zero value. You would need a SparkIntervalTimer to create an interrupt that will run that fast.

1 Like

Thank you :slight_smile: