Управление техникой используя ИК диапазон


Домашняя
Программы
Статьи
Архив схем
Для начинающих
Книги
Гостевая книга
Форум
Найти
Контакты
Сообщество

Управление техникой используя ИК диапазон :)

Потихоньку тикает время, и уже ни для кого не секрет что за рубежом "умный дом" не такое уж и большое шаманство. Но вот будет все это дело стоить очень много денег, которые ты вряд ли захочешь потратить. Сегодня я расскажу тебе как сделать самопальное подобие всей этой штуки (рассмотрим управление светом/магнитофоном/телеком/вообще чем угодно не вставая с дивана). Это же не кажется странным когда современную бытовую технику оборудуют пультами управления. Вот и мы можем в своем доме посадить на пульт розетки и верхнее освещение. Итак, нужно собрать пульт - некое подобие того чем ты щелкаешь свой телек. И приемник сигналов пульта. И в итоге коммутирующее устройство подключающееся к приемнику - которое в свою очередь будет коммутировать домашние электроцепи. Начнем с теории =)). Передача сигналов ведется в ИК диапазоне (наше зрение его не улавливает, что нельзя сказать о полупроводниковых фотоприемниках). Но пердача информации ведется достаточно хитрым способом, который позволяет передавать ее достаточно далеко и безошибочно, не используя никакой оптики. Для этого сигнал передатчика модулируется с достаточно большой частой (36 КГц). В нашей схеме все будет происходить следующим образом: если пульт отправляет единичку то в течении 1800 мкС его излучающий ИК диод "мигает" с частотой 36 КГц (назовем эту частоту несущей), затем следующие 600 мкС излучатель выключается (некая пауза между битами). После паузы передается следующий бит - если это снова единица - то по уже описанному для нее алгоритму, если ноль - то также как и единица, токо длительность составить не 1800 мкС, а всего 600 мкС. После отправки последненго бита в передаваемом пакете следует достаточно большая пауза - 42 млС - она нужна для того чтобы отделять пакеты (определенные наборы последовательноостей битов друг от друга). Затем пульт может передавать пакеты других кнопок - если они были нажаты. Теперь рассмотрим подробно работу приемника ИК пакетов. Его "глазом" является детать TSOP1736. Последние две цифры в маркировке обозначают несущую частоту, к которой наиболее чувсвителен фотоприемник (частота указана в КГц) - теперь становится ясно почему пульт моделирует мерцание излучателя на частоте 36 КГц? Ведь так ;) ? TSOP1736 - сам по себе штучка достаточно умная, и встроенный в нее фильтр от помех упрощает нашу жизнь =). На выходе мы имеем сигнал очищенный от разных там модуляций. В момент приема "1" (ориентируясь на алгоритм передатчика) напряжение на выходе [data] с +5 вольт опустится до 0 вольт в течении 1800 мкС. В момент приема нолика тоже опустится до нуля на 600 мкС. Во время пауз малой и большой напряжение на выходе [data] будет снова возрастать до +5 вольт. См диаграмму:

oscillograph_tsop

 

Из диаграммы видно что пакет данных для каждой кнопки состоит из 10 битов, первые 7 из которых - это биты идентифицирующие модель пульта (придуманы мной чисто от башки - да и вообще весь протокол придуман по принципу работает и ладно - все временные интервалы тоже изначально придуманы - и в итоге к ним все подстраивается). Последние три бита обозначают номер кнопки - у нас модель пульта простенькая - всего три кнопки. Вообще реализовать приемник на стандартных логических микросхемах громоздко и трудно, поэтому воспользуемся новинками техники - микроконтроллерами - я сконструировал и пульт и приемник на базе одного и того же контроллера - AT90S2313-10PI. Это вполне доступный и недорогой экземпляр. Итак, для тех кто в танке - микроконтроллер это с виду та же микросхема только внутри у нее имеется память - в данном случае 2 КБайта, в которой распологается программа на ассемблере, которая предварительно(перед началом использования микросхемы в устройстве прошивается с помощью программатора соединенного с компьютером). Итак, чем же хороши микроконтоллеры? А тем что для реализации достаточно сложных логических функций на плате устройства можно разместить всего одну микросхемку-микроконтроллер - а все тонкости учесть при написании программы для него. Модель микроконтроллера, который я использую имеет 15 программируемых линий ввода/вывода (из них два входа использующих IRQ[прерывание]), 2 таймера(тоже с IRQ), UART [IRQ], компаратор [IRQ] и многое дугое. Но нам понадобятся только линии ввода вывода использующие прерывания и оба таймера - для приемника. Для передачика из всего этого набора не понадобилось IRQ линий ввода/вывода. Схемы пульта и приемника(на схеме приемник уже скомбинирован с коммутатором) приведены ниже:

приемник
reciever

Обратите внимание на схему приемника - синим выделены элементы коммутатора(к транзисторам подключены реле, рассчитанные на 25 вольт). Красным обозначен блок ручного включения/выключения выбранного канала - при нажатии кнопки произойдет включение/выключение соответствующего канала. Если не хотите, то можете не собирать то что выделено красным - при этом выводы контроллера просто оставить неподсоединенными. При нестабильности работы(хаотичное переключение каналов) советую оставить резисторы(выделены красным) подсоединенные к плюсу и вывыодам контроллера - кнопки при этом можно не подключать.

передатчик
tranciever

Советую взять излучатели ИК диапазона следующих марок TSAL5100,TSAL6200. Короче, чем мощней, тем лучше. Можете соединить последовательно два излучателя - хуже не будет. Транзистор использовался КТ315г. Подойдет также и КТ3102. Распиновка деталей указана ниже:

 

Если схемы кажутся слишком сложными или громоздкими, то предлагаю две фотографии - на одной приемник, на другой передачик в собранном виде:

приемник
real_rx

Полезный совет - в качестве дополнительного ИК фильтра можно использовать обычную фотопленку. =)

передатчик
real_tx

Итак, предположим, что схемы вы собрали и осталось только прошить программу в микроконтроллер. Для этого я использовал программу ICProg. Как правило они все похожи, и для программирования микроконтроллера он подключается к ПК через параллельный (LPT) порт. Советую использовать на платах кроватки для микросхемы-контроллера что существенно облегчает процедуру вставки/извлечения микросхемы. Файлы прошивки для приемника и передатчика находятся здесь. После прошивки контроллеров вставляйте их на места - не спутайте только их друг с другом - контроллер с программой для приемника вставьте в плату приемника ;) ну вообщем вы поняли. И еще хочу обратить внимание на кварцы для контроллеров. Не используйте кварцы других номиналов нежели указаны мной на схеме - иначе работать не будет - все коэффициенты в программах приемника и передатчика ориентированы на частоту кварца. В приемнике кварц на 10.000МГц, в передачике на 4.000МГц. Теперь вкратце о том как все это работает - нажимаете на пульте кнопку (одну из трех) и просходит переключение на канале коммутатора - если соответствующий какнал до подачи сигнала был выключен, то он включится и наоборот. Правильно собранная схема в отладке не нуждается. Но если будут вопросы - можете написать мне на мыло.

Ниже приведены исходные коды программ для микроконтроллеров приемника и передатчика.
Язык: Си (ImageCraft)

приемник
// SIRR - 1b (Sash's Infra Red Reciever)
// Author: Sash <sash_g87@mail.ru>
// Target : Atmel AT90S2313-10PI
// Crystal: 10.000Mhz

#include <io2313v.h>
#include <macros.h>

#define TRUE 1
#define FALSE 0

//Here we see the code "up side down"
const unsigned char Code1[10]={0,0,1,0,1,1,1,0,0,1};
const unsigned char Code2[10]={0,1,0,0,1,1,1,0,0,1};
const unsigned char Code3[10]={1,0,0,0,1,1,1,0,0,1};


unsigned int TimerN=0;
unsigned char MakroTimerN=0;
unsigned char WasFallingEdge=0;
unsigned char cycle;
unsigned char Container[10];
unsigned char CompareFlag1;
unsigned char CompareFlag2;
unsigned char CompareFlag3;
unsigned char Signal1=FALSE;
unsigned char Signal2=FALSE;
unsigned char Signal3=FALSE;
unsigned char CountSignal1=0;
unsigned char CountSignal2=0;
unsigned char CountSignal3=0;
unsigned char SignalRecieved=FALSE;


void TranslateCode(void)
{
CompareFlag1=TRUE;
CompareFlag2=TRUE;
CompareFlag3=TRUE;

for(cycle=0;cycle<10;cycle++)
{
if(Container[cycle]!=Code1[cycle])CompareFlag1=FALSE;
if(Container[cycle]!=Code2[cycle])CompareFlag2=FALSE;
if(Container[cycle]!=Code3[cycle])CompareFlag3=FALSE;
}

if(CompareFlag1==TRUE)Signal1=TRUE;
if(CompareFlag2==TRUE)Signal2=TRUE;
if(CompareFlag3==TRUE)Signal3=TRUE;

}


AddValueToContainer(unsigned char Param)
{
for(cycle=9;cycle>0;cycle--)
Container[cycle]=Container[cycle-1];

Container[0]=Param;
}


void ChangeBitOnExit(unsigned char Param)
{
if((PORTB & BIT(Param))==0)PORTB|=BIT(Param);else PORTB&=~BIT(Param);
}

 


void port_init(void)
{
PORTB = 0x70;
DDRB = 0x07;
PORTD = 0x00;
DDRD = 0x00;
}

//TIMER0 initialisation - prescale:1024
// desired value: 10mSec
// actual value: 9,933mSec (0,7%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop timer
TCNT0 = 0x9F; //set count
TCCR0 = 0x05; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:7
void timer0_ovf_isr(void)
{
//TIMER0 has overflowed
TCNT0 = 0x9F; //reload counter value

//if we have not signal more then 0.5 sec after button unpressed
if((MakroTimerN>=50)&&(SignalRecieved==TRUE))
{
MakroTimerN=0;
SignalRecieved=FALSE;
CountSignal1=0;
CountSignal2=0;
CountSignal3=0;
}

if(MakroTimerN<=50)MakroTimerN++;


if(Signal1==TRUE){CountSignal1++;Signal1=FALSE;MakroTimerN=0;}
if(Signal2==TRUE){CountSignal2++;Signal2=FALSE;MakroTimerN=0;}
if(Signal3==TRUE){CountSignal3++;Signal3=FALSE;MakroTimerN=0;}

if(SignalRecieved==FALSE)
{
if(CountSignal1>=3){ChangeBitOnExit(0);SignalRecieved=TRUE;}
if(CountSignal2>=3){ChangeBitOnExit(1);SignalRecieved=TRUE;}
if(CountSignal3>=3){ChangeBitOnExit(2);SignalRecieved=TRUE;}
}

 


}

//TIMER1 initialisation - prescale:1
// desired value: 50uSec
// actual value: 50,000uSec (0,0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop timer
TCNT1H = 0xFE; //set count value
TCNT1L = 0x0C;
OCR1H = 0x01; //set compare value
OCR1L = 0xF4;
TCCR1A = 0x00;
TCCR1B = 0x01; //start Timer
}

#pragma interrupt_handler timer1_ovf_isr:6
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xFE; //reload counter high value
TCNT1L = 0x0C; //reload counter low value

if(WasFallingEdge==TRUE)TimerN++;
}

#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
//external interupt on INT0 [FallingEdge]
TimerN=0;
WasFallingEdge=TRUE;
}

#pragma interrupt_handler int1_isr:3
void int1_isr(void)
{
//external interupt on INT1 [RisingEdge]
WasFallingEdge=FALSE;

/*0*/if((TimerN>=5)&&(TimerN<=19))
{
AddValueToContainer(FALSE);
TranslateCode();
}

/*1*/if((TimerN>=20)&&(TimerN<=52))
{
AddValueToContainer(TRUE);
TranslateCode();
}



}

//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();
timer1_init();

MCUCR = 0x0E;
GIMSK = 0xC0;
TIMSK = 0x82;

SEI(); //re-enable interrupts
//all peripherals are now initialised
}

void delay_ms(unsigned int Choice)//Millisecond delay for XTAL=10MHz
{
unsigned int a,c;
for(c=0;c<Choice;c++)
for(a=0;a<1420;a++)asm("nop\n");
}

void main(void)
{
init_devices();

while(1)
{
if((PINB & BIT(4))==0)Signal1=TRUE;
if((PINB & BIT(5))==0)Signal2=TRUE;
if((PINB & BIT(6))==0)Signal3=TRUE;
delay_ms(100);
}

}

 

передатчик
// SIRT - 1b_NoPDM (Sash's Infra Red Transiver [No PowerDownMode =(])
// Author: Sash <sash_g87@mail.ru>
// Target : Atmel AT90S2313-10PI
// Crystal: 4.000Mhz

#include <io2313v.h>
#include <macros.h>

unsigned char on=0;
unsigned char count=0;
unsigned char KeyCode;

///////////////////////////////////////////////////////////////

const unsigned char Key1Code[32]={255,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0};
const unsigned char Key2Code[32]={255,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0};
const unsigned char Key3Code[32]={255,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,0};

////////////////////////////////////////////////////////////////

 


void port_init(void)
{
PORTB = 0xE0;
DDRB = 0x00;
PORTD = 0x00;
DDRD = 0x01;
}

//TIMER0 initialisation - prescale:1
// desired value: 71KHz
// actual value: 71,429KHz (0,6%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop timer
TCNT0 = 0xC8; //set count
TCCR0 = 0x01; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:7
void timer0_ovf_isr(void)
{
//TIMER0 has overflowed
TCNT0 = 0xC8; //reload counter value

//Modulation...
if(on==1)
{
if((PORTD & BIT(0))==0)PORTD|=BIT(0);else PORTD&=~BIT(0);
}
else PORTD&=~BIT(0);

}

//TIMER1 initialisation - prescale:1
// desired value: 600uSec
// actual value: 600,000uSec (0,0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop timer
TCNT1H = 0xF6; //set count value
TCNT1L = 0xA0;
OCR1H = 0x09; //set compare value
OCR1L = 0x60;
TCCR1A = 0x00;
TCCR1B = 0x01; //start Timer
}

#pragma interrupt_handler timer1_ovf_isr:6
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xF6; //reload counter high value
TCNT1L = 0xA0; //reload counter low value

if(count<30)
{
if(KeyCode==1){if(Key1Code[count+1]==1)on=1;else on=0;}
if(KeyCode==2){if(Key2Code[count+1]==1)on=1;else on=0;}
if(KeyCode==4){if(Key3Code[count+1]==1)on=1;else on=0;}
}
else on=0;

count++;
if(count>=100)count=0;

}

 

//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();
timer1_init();

MCUCR = 0x00;
GIMSK = 0x00;
TIMSK = 0x82;
SEI(); //re-enable interrupts
//all peripherals are now initialised
}

void delay_ms(int Choice)//Millisecond delay for XTAL=4MHz
{
int a,c;
for(c=0;c<Choice;c++)
for(a=0;a<500;a++)asm("nop\n");
}

 


void main(void)
{
init_devices();

PORTD&=~BIT(0);


while(1)
{

KeyCode=0;
if((PINB & BIT(5))==0)KeyCode=KeyCode+1;
if((PINB & BIT(6))==0)KeyCode=KeyCode+2;
if((PINB & BIT(7))==0)KeyCode=KeyCode+4;

if((KeyCode==1)||(KeyCode==2)||(KeyCode==4))
{
while(((PINB & BIT(5))==0)||
((PINB & BIT(6))==0)||
((PINB & BIT(7))==0))
{
delay_ms(300);
}

}

}
}

 

 

Sash
sash_g87@mail.ru


Домашняя | Программы | Статьи | Архив схем | Для начинающих | Книги | Гостевая книга | Форум | Найти | Контакты | Сообщество

 Сведения о владельцах и авторских правах.
По вопросам, связанным с этим веб-узлом, обращайтесь по адресу radiolla@bigmir.net.
Последнее обновление: 08.02.2006.

Hosted by uCoz