Универсальный ИК-Пульт

Универсальный Мини ИК-Пульт на ATTiny13

Сразу стоит оговориться – универсальный он только для протокола NEC.

Сделан для управления цифровой приставкой, у которой отсутствовал пульт:

-Прошиваем DVB-T2 приставку через консоль, без выпаивания микросхемы

-Как переключать каналы на приставке без пульта, любым телефоном

 

Команда для ик-приемника представляет из себя последовательность нулей и единиц, которые осуществляются разной длительностью импульсов на частоте 38 кГц и завершаются в конце отправкой нуля.В начале отправляется сигнал для синхронизации приемника и передатчика и для усиления сигнала.

Ноль передается таким импульсом – включением ик-диода на 562.5 мс , после этого паузой, в виде выключения на 562.5 мс.

Логическая единица передается включением ик-диода на 562.5 мс, а после соответственно паузой, в виде выключения на 1687.5 мс.Естественно то, что допустимы некоторые погрешности в длительности импульсов.

Включение должно осуществляться на частоте 38кГц, то есть в момент включения ик-светодиод должен со скоростью 38 000 раз в секунду включиться и выключиться, итого 38 000 включений, 38 000 выключений(это не значит, что он должен это делать целую секунду!), благодаря такой высокой частоте инфракрасный светодиод может выдерживать импульсные токи силой в 1 Ампер.

Принципиальная схема:

 

 

В функцию send_IR_cmd() пишете код своих команд от пульта, в формате HEX.

К примеру вместо

send_IR_cmd(0x00fdd827);

пишете

send_IR_cmd(0x02fdb24d);

Коды для пультов телевизоров и прочих устройств:

ircodes

 

#define F_CPU 9600000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
 
 
/*Макросы для 4-х кнопок-
 
режим, ок, влево, вправо и
 
выход на ик-диод
 
*/
 
#define MODE PB0
#define OK PB4
#define LEFT PB3
#define RIGHT PB1
#define OUTLED PB2
 
#define LED_ON PORTB |= (1<<OUTLED);//Макрос для включения ик-диода
#define LED_OFF PORTB &= ~(1<<OUTLED);//Макрос для выключения ик-диода
 
#define wait_ms 99 //макрос для паузы при обработке кнопок
 
 
uint8_t mode=0; //переменная для изменения режима
 
 
 
/*функция импульса длительность 550 мс,это близко к 562 мс
 
1 000 000 микросекунд \38 000=26,31 микросекунда -
 
длительность импульса частотой 38 кГц, в результате чего
 
включаем светодиод на 5  микросекунд,
 
выключаем на 20 микросекунд - и так 22 раза - получаем импульсное
 
включение на 550 микросекунд,
 
все в пределах допустимых погрешностей
 
*/
 
void runpulse()
{
 
// 25us *22 раза в цикле=550
for (char i=0; i<22; i++) {
LED_ON;
_delay_us(5);
LED_OFF;
_delay_us(20);
}
 
}
 
 
 
//отправляем импульс, которые представляет из себя логический 0
 
void s0()
{
runpulse();
LED_OFF;
_delay_us(560);
 
}
 
 
 
//отправляем импульс, которые представляет из себя логическое 1
 
void s1()
{
runpulse();
LED_OFF;
_delay_us(1682);
}
 
 
 
//функция отправки команды, которая принимает команду в HEX-формате напрямую
 
void send_IR_cmd(uint32_t hex_code) {
 
//Стартовая передача для настройки передатчика и приемника
 
//длительностью 550*16=8800 микросекунд
for(int i=0;i<16;i++)
{
runpulse();
}
 
LED_OFF;
_delay_us(4491);
//считываем значение 32-ух битов с конца(положение, смещение первого бита - 32 ) до начала
 
for (int i = 31; i > -1; i--)
{
 
uint8_t bit = (hex_code >> i) & 1U;
 
//если бит в единице отправляем единицу
 
if ( bit == 1 )
{
s1();
}
 
//иначе отправляем 0
else
{
s0();
}
 
}
 
//отправка конечного нуля
s0();
 
}
 
 
 
//главная функция
 
int main(void)
{
 
DDRB |= 1<<OUTLED;//Выход ик-светодиода
LED_OFF;
 
DDRB |= 0<<MODE;//Вход кнопки mode
DDRB |= 0<<LEFT;//Вход кнопки <
DDRB |= 0<<OK;//Вход кнопки Ok
DDRB |= 0<<RIGHT;//Вход кнопки >
 
//включить pull up резисторы
PORTB |= (1<<MODE);
PORTB |= (1<<LEFT);
PORTB |= (1<<OK);
PORTB |= (1<<RIGHT);
 
while (1)
{
 
switch(mode)
{
 
/*
 
режим 0 - кнопки LEFT, RIGHT(Ножки, пины
 
определены в макросах)- как вправо, влево
 
*/
 
case 0:
 
//OK
if( ! (PINB & (1 << OK))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << OK)))
{
 
send_IR_cmd(0x00fd58a7);//<
 
}
 
}//mode push
 
_delay_ms(99);
 
//<
if( ! (PINB & (1 << LEFT))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << LEFT)))
{
 
send_IR_cmd(0x00fd5aa5);//<
 
}
 
}//mode push
 
_delay_ms(99);
 
if( ! (PINB & (1 << RIGHT))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << RIGHT)))
{
 
send_IR_cmd(0x00fdd827);//<
 
}
 
}//mode push
 
_delay_ms(99);
 
;break;
//режим 1 - кнопки LEFT,RIGHT работают как вверх, вниз
case 1:
 
//OK
if( ! (PINB & (1 << OK))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << OK)))
{
 
send_IR_cmd(0x00fd58a7);//<
 
}
 
}//mode push
 
//вверх
if( ! (PINB & (1 << RIGHT))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << RIGHT)))
{
 
send_IR_cmd(0x00fd609f);//<
 
}
 
}//mode push
 
//Вниз
if( ! (PINB & (1 << LEFT))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << LEFT)))
{
 
send_IR_cmd(0x00fd6897);//<
 
}
 
}//mode push
 
break;
 
}
 
//MODE, изменение режима
if( ! (PINB & (1 << MODE))) {
_delay_ms(wait_ms);
 
if( ! (PINB & (1 << MODE)))
{
 
mode++;
_delay_ms(500);
 
if (mode>1)
{
mode=0;
}
 
}
 
}//mode push
 
}//while
 
}//main

Скомпилированная прошивка в HEX:
IR_Sender