Привет, Хабр! Возникла необходимость отключить старую, но вполне рабочую акустическую систему с пульта от телевизора, не вставая с дивана.
Подумав, я решил использовать ИК-приемник, который когда-то снял со старого телевизора.
ИК-приемник оказался без маркировки.
Определив наугад выходы, я выяснил, что это из серии TSOP4xxx, судя по картинке:
Погуглив и потренировавшись на Arduino UNO, используя этот код и убедившись, что датчик работает, я перешел к переписыванию кода на ATtiny13. Перейдя на него, я понял, что очень ограничен в ресурсах, как во флеше, так и в оперативной памяти.
Поначалу у меня были трудности с оптимизацией под размер прошивки, контроллер всё равно не работал, а когда я понял, что памяти в коде используется гораздо больше, чем 64 байта, пришлось специально браться за оптимизацию.
В итоге я с огромным горем оптимизировал код и собрал прототип на макетке.
Я был рад как ребенок! Он мигал светом так, как мне было нужно.
Общая форма: Макет
Схема: Спойлер
Пришло время перевести весь макет в текстолит. Плата изготовлена методом ЛУТ.
Первый блин, как говорится, комом.
Сделав первую схему, распечатав и собрав, я понял, что ничего не работает. Я неправильно подключил LM317T. К тому же, сломав пятаки и оторвав несколько слишком тонких следов, я решил сделать вторую плату.
Я сделал в нем дорожки 0,7мм и за счет увеличения пятаков как-то справился с некоторыми проблемами.
Здесь тоже были некоторые проблемы, так как я снова неправильно подключил LM317T, и даже в предыдущей версии платы я сжег приемник, подав на него 12В.
Кстати, эта штука питается от 12В (у меня был маломощный трансформатор, поэтому я использовал его).
Выбор напряжения также определялся имеющимся реле на 12В.
Для снижения напряжения на микроконтроллере до 5В используется стабилизатор LM317T, а для управления реле - имеющийся в наличии npn транзистор КТ819.
Итоговая плата в SprintLayout: Спойлер
Используемые детали:
- Микроконтроллер ATtiny13A;
- Резисторы номиналами 470, 1300, 2х330 и 90 Ом;
- Транзистор КТ819;
- Стабилизатор LM317T;
- 2 светодиода красный и зеленый;
- Приемник серии TSOP4XXX или совместимый;
- Конденсатор примерно 200-220мкФ;
- Диод 1N4001 или аналог.
Исходная версия была очень «тяжелой» и не могла работать на ATtiny13. Пришлось избавиться от тяжелого двумерного массива.
Код был очень странный: «низкие» импульсы тоже записывались, но они никак не использовались.
В общем, двумерный массив я выбросил и это освободило минимум 64 байта ОЗУ.
Я рассчитывал сигналы на лету, но этого было недостаточно и после добавления функционала таймера пришлось максимально урезать переменные.
Код для Arduino IDE
Теги: #Сделай сам или Сделай сам #arduino #реле #IR #attiny13 #remote #attiny13a #IRDA #tsop#define IRpin_PIN PINB #define IRpin 2 #define rLedPin 3 #define gLedPin 4 #define relayPin 1 #define MAXPULSE 5000 #define NUMPULSES 32 #define RESOLUTION 2 #define timeN1 1800000 #define timeN2 3600000 #define timerInterval 500 bool relayState = false; unsigned long timer = 0; unsigned long shift = timeN1;//30 min timer by default unsigned long previousMillis = 0; bool timerN = false; byte i = 0; void setup() { //default states DDRB |= (1<<relayPin); DDRB |= (1<<rLedPin); DDRB |= (1<<gLedPin); PORTB &= ~(1<<relayPin);//relay off PORTB &= ~(1<<rLedPin);//red led off PORTB |= (1<<gLedPin);//green led on /* //for debug Serial.begin(9600); Serial.println("Start | "+String(millis())); //*/ /* //for debug without ir receiver pinMode(5, INPUT); pinMode(6, INPUT); //*/ } void shutDown(){ relayState = true; PORTB |= (1<<relayPin); PORTB &= ~(1<<gLedPin); PORTB |= (1<<rLedPin); //Serial.println("turining off |"+String(millis())); } void startUp(){ relayState = false; PORTB &= ~(1<<relayPin); PORTB |= (1<<gLedPin); PORTB &= ~(1<<rLedPin); //Serial.println("turining on |"+String(millis())); } void loop() { unsigned long irCode = listenForIR(); // Wait for an IR Code //Serial.println("ir code: "+String(irCode)); if(irCode == 3359105948){//green button //Serial.println("Pressed green btn |"+String(millis())); if(timer == 0){//on off mode if(relayState == true){ startUp(); }else{ shutDown(); } }else{//cancel timer mode timer = 0; PORTB &= ~(1<<rLedPin);//turn off red led //Serial.println("timer canceled |"+String(millis())); } }//end green btn if(3359101868 == irCode){//red btn //Serial.println("pressed red btn |"+String(millis())); if(timer == 0){ if(relayState == 0){ timer = millis(); //Serial.println("timer started |"+String(millis())); }/*else{ Serial.println("already shutdown |"+String(millis())); } //*/ }else{//changing time mode timerN = !timerN; if(timerN){ //Serial.println("change 30sec |"+String(millis())); shift = timeN1;//30 min }else{ //Serial.println("change 60sec |"+String(millis())); shift = timeN2;//60 min } } }//end red btn } // loop end void checkTimer(){ unsigned long time = millis(); if(time - previousMillis >= timerInterval || previousMillis > time ) { previousMillis =time; timer1(); } } unsigned long listenForIR() {// IR receive code byte currentpulse = 0; // index for pulses we're storing unsigned long irCode = 0; // Wait for an IR Code irCode = irCode << 1; while (true) { unsigned int pulse = 0;// temporary storage timing //bool true (HIGH) while (IRpin_PIN & _BV(IRpin)) { // got a high pulse (99% standby time have HIGH) if(++i > 150){//check timer every 150 iterations (high frequency break ir code timing) i = 0; checkTimer(); } pulse++; delayMicroseconds(RESOLUTION); if (((pulse >= MAXPULSE) && (currentpulse != 0)) || currentpulse == NUMPULSES ) { return irCode; } }
-
Преимущества Компьютерных Разъемов
19 Oct, 24 -
Как Получить Срочную Помощь По Uc Browser
19 Oct, 24 -
Рассказал Историю - Получи Самогон
19 Oct, 24 -
Лидер С Двумя Головами
19 Oct, 24 -
Текстовые Редакторы Против Ide
19 Oct, 24