[Из песочницы] Реле с дистанционным ИК управлением на ATtiny13a

Привет, Хабр! Появилась необходимость выключения старой, но вполне рабочей акустической системы с пульта от телевизора, не вставая с дивана. Подумав, я решил использовать ИК приёмник, некогда выкрученный со старого телевизора. ИК приёмник оказался без опознавательных знаков. Определив выходы методом тыка выяснил, что он из серии TSOP4xxx, если верить картинке:

734bb332402445dea6eced4ba89458d7.jpgПогуглив и потренировавшись на Arduino UNO, используя этот код и удостоверившись в работоспособности датчика, я перешёл к переписыванию кода на ATtiny13. Перейдя к ней, понял, что очень сильно ограничен ресурсах, как во флеше, так и в оперативной памяти. По началу с трудом оптимизировал по размеру прошивки, контроллер все еще не работал, а когда понял, что памяти в коде используется намного больше 64 байт, пришлось конкретно взяться за оптимизацию. В итоге с горем пополам оптимизировал код и собрал прототип на макетке. Радовался, как ребенок! Оно мигало лампочками так, как мне надо.

Общий вид:

Макетка 467f4e8452804fbdb0d38493f88a1734.JPG Схема: Спойлер b4f16ca91a9d427b9cb98539787f2ddf.png Пришло время переводить всю макетку в текстолит. Плату изготовлял методом ЛУТ. Первый блин, как говорится, комом. Сделав первую схему, напечатав и собрав, понял, что ничего не работает. Я неправильно подключил LM317T. К тому же, поломав пятаки и оторвав некоторые слишком тонкие дорожки, решил сделать вторую плату. В ней сделал дорожки 0,7 мм и, увеличив пятаки, кое как справился с частью проблем. Тут тоже не обошлось без проблем, так как опять неправильно подключил LM317T, да еще и в прошлой версии платы сжег приёмник, подав на него 12В.Кстати, питается это дело от 12В (был у меня маломощный трансформатор, вот его и задействовал). Выбор напряжения был обусловлен так же имеющимся в наличии реле на 12В. Для понижения напряжения для микроконтроллера до 5В используется стабилизатор LM317T, а для управления реле используется имеющийся под рукой npn транзистор КТ819.

Окончательная плата в SprintLayout:

Спойлер 2d9106a5110a4df89a4d8b3201130627.png Используемые детали: Микроконтроллер ATtiny13A; Резисторы номиналом 470, 1300, 2×330 и 90 Ом; Транзистор КТ819; Стабилизатор LM317T; 2 светодиода красный и зеленый; Приёмник серии TSOP4XXX или совместимый; 2 конденсатора для фильтрации по питанию примерно на 200–220 мкФ. Что касается кода.

Исходный вариант был очень «увесистый» и на ATtiny13 ни как не мог работать. Необходимо было избавиться от тяжелого двумерного массива. Код был очень странным: записывались так же «низкие» импульсы, но они никак не использовались. В общем, выкинул двумерный массив и этим освободил как минимум 64 байта оперативной памяти. Высчитывал сигналы на лету, но этого было мало и после добавления функционала таймера пришлось максимально урезать переменные.

Код для Arduino IDE #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<

PORTB &= ~(1<

/* //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<

void startUp (){ relayState = false; PORTB &= ~(1<

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<

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; } }

//make irCode irCode = irCode << 1; if ((pulse * RESOLUTION) > 0 && (pulse * RESOLUTION) < 500) { irCode |= 0; }else { irCode |= 1; } currentpulse++; pulse = 0; //bool false (LOW) while (!(IRpin_PIN & _BV(IRpin))) {//wait before new pulse //checkTimer(); pulse++; delayMicroseconds(RESOLUTION); if (pulse >= MAXPULSE || currentpulse == NUMPULSES) { //Serial.println (irCode); return irCode; } } }//end while (1) }//end listenForIR

//executing every timerInverval void timer1() { if (timer!= 0){ if (timerN == true){//timeN1 or timeN2 PORTB |= (1<

if (timer!= 0 &&(timer+shift < millis() || timer > millis ())){ timer = 0; shutDown (); } }

Видеодемонстрация:[embedded content]

Прошивал ATtiny13 я с помощью Arduino UNO, используя его как программатор, руководствуясь публикацией «Прошивка и программирование ATtiny13 при помощи Arduino». Для прошивки использовал 9,6МГц конфигурацию.

Фотографии почти не делал, но что есть, то есть:

Фото Из за другой распиновки запасного TSOP на второй версии, пришлось его перенести на проводки и закрепить клеем (позже просто прикрепил к корпусу).Вторая плата сбоку:

ad2f16cfe64f40158382273a6328e30d.JPG

Вторая плата сверху (ик датчик перенес):

b513664399534745bd2d72d9175a163e.JPG

Вторая плата снизу:

7f49300c1eb146a1b965fd35e2e77cdd.JPG

Конечное устройство:

226bd9d668484c10bdc23073e1fe6adc.JPG

Исходники и прошивка на яндекс диске.

Используемые материалы myrobot.ru/wiki/index.php? n=Components.TSOP Всё об ИК-приёмнике «TSOP«www.atmel.com/images/doc2535.pdf Даташит по ATtiny13habrahabr.ru/post/234477/ Инструкция по прошивке ATtiny13payalo.at.ua/c_fuse/calc.html? part=ATtiny13A калькулятор фьюзов для ATtiny13github.com/nathanchantrell/TinyPCRemote/tree/master/TinyPCRemote_CodeReader, код читалки кодов пульта который я взял за основу.

© Habrahabr.ru