Site icon Меандр — занимательная электроника

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#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 минут.
Видео с работой вентилятора(сори фотика на данный момент нет):

Источник: diymicro.ru

Exit mobile version