Вкратце смысл ТЗ.
Устройство излучает сигнал ИК-светодиодом и принимает этот сигнал приемником типа TSOPxx.
Наличие или отсутствие приема вызывает переключение логического уровня на выходе устройсва.
Реагирует только на свой сигнал. Сигналы от других источников не воспринимаются.
Можно применять:
в общем - как детектор при пересечении луча каким-либо препятствием, либо при отражении луча от препятствия.
в частности:
в охранных системах, в качестве датчика приближения,присутствия. Автоматическое включение,отключение света. И других системах, где необходим дистанционный контроль.
Немного погуглив эту тему, было найдено пару проектов некоего подобного. Но реализованы они как-то коряво. Передается не пойми-что, и принимается не пойми-как. Один даже додумался при помощи АЦП !!! измерять уровень сигнала с TSOPа.
В общем решил написать своё, правильное.
В итоге получился вот такой код
- Код: Выделить всё
/****************************************************
made slav0n
Chip type : ATtiny13
9.6 MHz
фузы заводские, только снять галку CKDIV8
;Hfuse FF
;Lfuse 7A
****************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h> /* for _delay_ms() */
//#include "m8_128.h"
#define out_36kHz PB1
#define swch_36_38 PB4
#define out_1 PB0
#define out_2 PB2
#define TSOP PB3
#define SimbInPaket 15 //определяем длину пакета
#define PeriodPaket 64 //определяем период пакета
#define MaxErrPaket 0 //определяем ко-во допустимых ошибок
volatile unsigned char flg_err;
ISR(SIG_OUTPUT_COMPARE0B)
{
static unsigned char timer_strob;
static unsigned char timer_paket;
static unsigned char cnt_err_paket;
timer_strob++;
if(timer_strob==66)//середина пачки
{
if(timer_paket < SimbInPaket) //находимся-ли в теле пакета?
{
//проверяем принял-ли TSOP сигнал и считаем ошибки в пакете
if(PINB&(1<<TSOP) && TCCR0A&(1<<COM0B0))cnt_err_paket++;
TCCR0A ^= (1<<COM0B0); //изменяем сигнал на противоположный
}
}
else
if(timer_strob==66+66) //достигли конца периода пачки
{
timer_strob =0; //обнуляем счетчик импульсов
timer_paket++;
if(timer_paket == PeriodPaket+1) //достигли конца периода пакета
{
timer_paket =0; //обнуляем счетчик периода пакета
if(cnt_err_paket > MaxErrPaket)flg_err =1;//были-ли ошибки в пакете?
else flg_err =0;
cnt_err_paket =0; //сбрасываем счетчик ошибок в пакете
}
if(timer_paket < SimbInPaket) //находимся-ли в теле пакета?
{
//конфигурация Галуа, рандомгенератор
static unsigned char Q = 1;
Q = (Q>>1) ^ (Q&1 ? 0b11010111 : 0);
if(Q&1)TCCR0A |= (1<<COM0B0); //передача единцы
else TCCR0A &=~(1<<COM0B0); //передача нуля
}
else TCCR0A &=~(1<<COM0B0); //откл выход если пауза периода пакета
}
}
//============================================================
int __attribute__((naked)) main(void)
{
PORTB = (1<<swch_36_38)|(1<<TSOP);//подтяжка
DDRB = (1<<out_36kHz)|(1<<out_1)|(1<<out_2);//выходы
TCCR0A = (1<<COM0B0)|(1<<WGM01); //на выходе меандр. сброс при совпадении
TCCR0B = 1; //предделитель 1, запуск таймера
//TCCR0B = 0; //стоп таймер
TIMSK0 = (1<<OCIE0B);//разрешаем прерывание по совпадению В
if(PINB & (1<<swch_36_38))OCR0A = 124; //38khz
else OCR0A = 131; //36khz
sei();
while(1)
{
if(flg_err)
{
PORTB |=(1<<out_1);
PORTB &=~(1<<out_2);
//длительность импульса сигнала ошибки
//если не надо удлинять то закомментировать
_delay_ms(500);
}
else
{
PORTB &=~(1<<out_1);
PORTB |=(1<<out_2);
}
}
}
##############################################################################
Ну, а теперь посмотрим весь процесс создания сего устройства сначала:
Пока сигнал идет непрерывно. Чуть позже думаю сделаю передачу случайного кода
фузы заводские, только снять галку CKDIV8
;Hfuse FF
;Lfuse 7A
- Код: Выделить всё
/*
Chip type : ATtiny13
9.6 MHz
фузы заводские, только снять галку CKDIV8
;Hfuse FF
;Lfuse 7A
****************************************************/
#include <avr/io.h>
//#include <util/delay.h> /* for _delay_ms() */
#include "m8_128.h"
#define out_36kHz PB1
#define swch_36_38 PB4
#define out_1 PB0
#define out_2 PB2
#define TSOP PB3
//============================================================
int __attribute__((naked)) main(void)
{
PORTB = (1<<swch_36_38);
DDRB = (1<<out_36kHz)|(1<<out_1)|(1<<out_2);
TCCR0A = (1<<COM0B0)|(1<<WGM01); //на выходе меандр. сброс при совпадении
TCCR0B = 1; //предделитель на 1, запуск таймера
//TCCR0B = 0; //стоп таймер
while(1)
{
if(PINB & (1<<swch_36_38))OCR0A = 125; //38khz
else OCR0A = 132; //36khz
if(PINB & (1<<TSOP)){PORTB |=(1<<out_1);PORTB &=~(1<<out_2);}
else {PORTB |=(1<<out_2);PORTB &=~(1<<out_1);}
}
}