ИК управление для вентилятора

Лето. Жарко. Очень жарко. В один из дней я не выдержал и купил недорогой напольный вентилятор, у которого было два больших минуса:

1. Нет удаленного управления.

2. Нет таймера на отключение (а я не хочу, чтобы он гудел всю ночь).

Итак, что есть под рукой:

1. Микроконтроллер pic16f628a в soic корпусе;

2. Два реле 5В на несколько ампер;

3. Вентилятор;

Неплохо, вроде бы есть где развернуться. Начнем с препарирования вентилятора.

Внутри стандартный механический переключатель на 3 режима + 1 на свет, никаких предохранителей нет, кнопки тоже кривые. Схему вентилятора можно изобразить примерно в таком виде:

Номиналы индуктивностей естественно никакой смысловой нагрузки в данном случае не несут.

Первая задача – это управление нагрузкой с помощью мк, здесь я пошел по простому пути и решил использовать реле с одной оговоркой, что ручное управление тоже должно оставаться. Добавляем сюда нашу силовую часть и заодно зафигачим предохранитель, мало ли что.

Добавили пред и реле

Как видно из схемы, в режиме по умолчанию (при выключенном контроллере) напряжение проходит через реле RL1 на ручное управление, в случае переключения управления на дистанционку (IRON = 1) напряжение перекидывается на реле RL2, которое в свою очередь управляется битом IRFAN. Да еще, в моем случае я выбрал только одну скорость вентилятора, частично из-за того, что у меня на данный момент было только два реле, частично из-за того, что я по большому счету не замечал разницы между всеми этими режимами.

Добавляем микроконтроллер и простейшие средства индикации:

На схеме не показан кварц, а также ИК приемник на TSOP1738 (схему подключения можно посмотреть в этой статье). Светодиод D7 служит в качестве индикатора работы удаленного управления. Остальные 4 светодиода образуют индикацию значения таймера в микроконтроллере (в двоичной системе). Ну вот, со схемой практически все, осталось подвести питание, я не стал загоняться и взял старый зарядник от мобильника на 7 вольт, втыкнул по его выходу один диод, чтобы понизить напряжение до приемлемого и все – компактный блок питания готов.

Но тут меня ждала большая зад.. засада. Этот гад – блок питания грелся как сковородка на огне, удобность удобностью – а безопасность дороже – взял другой блок питания побольше и воткнул в корпус вентилятора разъем, да получилось не слишком удобно, но зато можно спать спокойно 🙂

Все готово, можно переходить непосредственно к коду, который будет рулить всем этим добром.


#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; // Запуск таймера!
}

Таким образом я получил вентилятор с ИК управлением, индикатором включения удаленного управления, двоичным индикатором значений таймера. За базовый промежуток взят отрезок равный примерно 5 минутам. Максимальное время равно 5*2^4 = 80 минут.
Видео с работой вентилятора(сори фотика на данный момент нет):

Исходники можно найти здесь.

ИК управление для вентилятора: 7 комментариев

  1. Уведомление: Remote control for the fan | diymicro.org

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.