Лето. Жарко. Очень жарко. В один из дней я не выдержал и купил недорогой напольный вентилятор, у которого было два больших минуса:
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 минут.
Видео с работой вентилятора(сори фотика на данный момент нет):
Исходники можно найти здесь.
обязательно сварганю что нибудь подобное
классные колонки у тебя стоят мне нравились
Да, мне они тоже нравятся 🙂
С тобой связаться как нибудь можно?
Да, контакты в разделе “О сайте”
http://diymicro.ru/about
на gmail написал
Уведомление: Remote control for the fan | diymicro.org