Remote control for the fan

It was a hot, really hot, really very hot summer in 2012 in place where I used to live. I bought some cheap fan, though it was quite powerful, but there were two major drawbacks for me:

  1. No remote control
  2. No timer for scheduling switching off, let say at night. And I did not want it to make noise a whole night.
a fan with the remote control

So, what do we have handy:

1. A pic16f628a microcontroller in a soic package;

2. Two 5V couple amps relays;

3. A fan;

Not that bad,we have the stuff which can be unscrewed and I can dig into entrails. Disassembling the fan firstly, inside we have the standard mechanical 4 modes switch: 3 for speed change and 1 for the moving the fan around. One can represent the fan schematic like this:

fan schematic

Do not pay attention to the inductance values, they don’t carry any meaning for our small project.

The task #1 – the load control by the uC, I used the easiest solution – a relay, just I wanted to leave the manual control as well. Putting everything together to the schematic and adding a fuse, just in case.

adding relays for the remote control embedding

The default mode (with uC is switched off) the voltage goes through RL1 to the manual control. When we enable the remote control (IRON = 1), we are bypassing one manual speed with RL2 and controlling on/off state with IRFAN bit. I use just a single speed for remote, since at the moment I had just two relays in my stashes.

Adding the microcontroller and some indicators:

schematic with uC added

I did not show the crystal oscillator and IR TSOP1738 receiver IC (the application diagram can be viewed in this article) . The D7 LED serves as an indicator of entering to the remote control mode. Other 4 LEDs represent timer value in the binary form. All we have left to do is to connect some power supply to power the remote interface device. I found some old mobile supply charger which worked pretty well.

Time to disclose the code I wrote for this.

#include <htc.h>
#include <stdio.h>
#include "usart.h"
 
#define _XTAL_FREQ 4000000
#define ON RA0                     //пин включения реле для питания
#define IRpin RB0                  //пин Ик
#define FAN RA1                    //пин включения вентилятора
 
volatile static bit direction;     //1 - rising, 0 - falling
volatile unsigned char IRbyte;     //принятый байт
volatile bit togglebit;            //бит переключалка
volatile bit oldtogglebit;         //хранение старого значения бита-переключалки
volatile bit buffer;
volatile unsigned char bytecount;
volatile unsigned char i=0;
volatile unsigned short long tick = 0;
volatile unsigned short long tickCount = 0;
volatile unsigned short long time = 0;
 
__CONFIG(MCLRDIS & LVPDIS & WDTDIS & UNPROTECT & XT);
 
void StartTimer(void);              //инициализация таймера 0
void StartTimer2(void);             //инициализация таймера 2
 
void main() {
 
unsigned int delta = 4596;         //Переменная дельта для промежутка таймера - 4596 ~ 5 минут
CMCON = 0x07;                      //Аналоговые функции не нужны
TRISA = 0x00;
TRISB = 0b00001001;                // Порт В на выход
PORTB = 0x00;                      // Выключаем все выходы порта В
PORTA = 0x00;
init_comms();                      //Инициализация уарта
GIE = 1;
PEIE = 1;
 
buffer = 0;
IRbyte = 0;
bytecount = 0;
direction = 0;
INTEDG = 0;
INTE = 1;
printf("Starting done! \r\n");
SLEEP();                           //Все настроено, засыпаем чтобы не жрать зря энергию
for (;;)
 { // Запускаем бесконечный цикл
 
   //---------------Обработка ИК команд---------------
   if (bytecount>13)
      {
       GIE = 0;
         if (oldtogglebit != togglebit)
            {
              printf("\r\nPressed button is %d", IRbyte);
              switch(IRbyte)
              {
                 case 31 : ON = !ON;
                           if (!ON)
                           {
                             time = 0;
                             FAN = 0; //Если выключено электронное управление, то выключаем реле вентилятора
                             PORTB &= 0b00001111;
                             TMR2ON = 0; TMR2IE = 0;
                             SLEEP();
                            }
                            break;
                 case 15 : if ((time < 16)&&(ON))
                           {
                             FAN = 1;
                             time++;
                             unsigned char temp = time << 4;
                             tickCount = delta*time; //примерно 5 минут * на нужный промежуток
                             printf("Tickcount %d", tickCount);
                             PORTB &= 0b00001111;
                             PORTB |= temp;
                             tick = 0;
                             StartTimer2();
                           } else if (ON)
                                  {
                                   time = 0;
                                   PORTB &= 0b00001111;
                                  }
                           break;
                 case 37 : time = 0;
                           PORTB &= 0b00001111;
                           break;
                 case 23 : if (ON) FAN = !FAN;
                               else FAN = 0;
                           break;
            }
       }
       IRbyte = 0;
       bytecount=0;
       INTEDG = 0;
       buffer = 0;
       oldtogglebit = togglebit;
       GIE = 1;
 }
//---------------Конец обработки IR команд---------------
 
if ((tick%delta == 0)&&(tick>0))                //Гасим светодиоды в обратном порядке
{
  unsigned char temp = (time - (tick/delta)) << 4;
  PORTB &= 0b00001111;
  PORTB |= temp;
}
 
}
 
}//for(;;)
 
interrupt isr() {
//-------------------IR decoding-------------------
if (INTF)
{
 
 if (bytecount<1)
  {
    direction = 1;
    INTEDG = 1;
    StartTimer();
    bytecount++;
  } else
      {
         direction = !direction;
         if (direction==buffer)
         {
            StartTimer();
            bytecount++;
         }
         INTEDG = direction;
      }
INTF = 0;
 
}// if INTF
else
{
  if (TMR1IF)
   {
     buffer = IRpin;
     TMR1ON = 0;
     TMR1IF = 0;
     if (bytecount==2) togglebit = buffer;
     if ((bytecount>7)&&(bytecount<14)) //забираем только команду
       {
         IRbyte <<= 1;
         IRbyte |= buffer;
       }
 
   }
}//else
if (TMR2IF)
{
 GIE = 0;
 if (tick < tickCount)
 {
   tick++;
   TMR2IF = 0;
   StartTimer2();
 }
 else
 {
   tick = 0;
   FAN = 0;
   ON = 0;
   TMR2ON = 0;
   TMR2IE = 0;
   tickCount = 0;
   time = 0;
   PORTB &= 0b00001111;
 }
 TMR2IF = 0;
 GIE = 1;
 
}
}
//--------------------End interrupts---------------------
 
/* ---------------------------------------------Функции--------------------------------------------*/
void StartTimer(void)
{
 T1CKPS1 = 0;
 T1CKPS0 = 0;
 
 T1OSCEN = 0; //выключаем внутренний генератор
 TMR1CS = 0; // Fosc/4
 TMR1IE = 1; // прерывание по переполнению TMR1
 TMR1H = 0b11111011; TMR1L = 0b00010110; //1.257ms
 //TMR1H = 0b00000000; TMR1L = 0x00;
 TMR1ON = 1; // включаем таймер
}
 
void StartTimer2(void)
{
 //printf("\r\nStart timer");
 TMR2 = 0x00; //стартуем с 0
 PR2 = 0xFF; //считаем по 255*16 мкс
 T2CKPS0 = 1; T2CKPS1 = 1; //1 делитель максимум
 TOUTPS2 = 1; TOUTPS1 = 1; TOUTPS3 = 1; TOUTPS0 = 1; //2 делитель максимум
 TMR2IE = 1;
 TMR2ON = 1; // Запуск таймера!
}

Thus, I got the fan with the remote control, with indication of the entering to remote mode and with binary indicators of the timer value. The base time delay count equals to 5 mins, so the max possible timer value is 5*(2^4) =80 minutes.

There is a short video how the thing works:


The sources

Leave a Reply

Your email address will not be published.