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:
- No remote control
- No timer for scheduling switching off, let say at night. And I did not want it to make noise a whole night.
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:
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.
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:
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: