[Из песочницы] Реле с дистанционным ИК управлением на ATtiny13a
Привет, Хабр! Появилась необходимость выключения старой, но вполне рабочей акустической системы с пульта от телевизора, не вставая с дивана. Подумав, я решил использовать ИК приёмник, некогда выкрученный со старого телевизора. ИК приёмник оказался без опознавательных знаков. Определив выходы методом тыка выяснил, что он из серии 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 или совместимый; 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 на второй версии, пришлось его перенести на проводки и закрепить клеем (позже просто прикрепил к корпусу).Вторая плата сбоку: Вторая плата сверху (ик датчик перенес): Вторая плата снизу: Конечное устройство:
Исходники и прошивка на яндекс диске. Используемые материалы
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, код читалки кодов пульта который я взял за основу.