Наш канал в telegram

Алгоритмы и программы управления для контроллеров ИК-барьера

В этой статье описываются алгоритмы и программы для микроконтроллеров, управляющих излучателем и приёмником ИК-барьера. Как вы помните, излучатель у нас сделан на микроконтроллере PIC12F629, а приёмник — на ATtiny13.

Начнём с излучателя. Он у нас занимается тем, что посылает чередующиеся сигналы «ON» (импульсы на частоте 36 кГц) и «OFF» (отсутствие импульсов). Длительность сигнала «ON» около 500 мкс, а длительность сигнала «OFF» около 1500 мкс.

За основу программы для излучателя возьмём программу, написанную нами ранее для реализации протокола RC-5. Отличие будет только в том, что в RC-5 длительности сигналов «ON» и «OFF» были одинаковы и равны 888,864 мкс. (описание протокола RC-5, реализация RC-5 на PIC12F629)

Переходим к приёмнику. При описанных выше сигналах излучателя, на выходе приёмника будут импульсы с периодом около 2 мс. Причём, поскольку сигнал на выходе фотоприёмника ILMS5360 инвертированный, то у этих импульсов время высокого уровня сигнала будет около 1500 мкс, а время низкого уровня около 500 мкс. Но это так, к слову. На самом деле нам важно не это. Нам важно, что на выходе фотоприёмника будут импульсы, то есть состояние выхода будет меняться не реже, чем 1 раз в 1500 мкс. Именно по этому факту мы и будем судить о том, что сигнал от излучателя не потерян.

В программе мы поступим следующим образом — запустим таймер, настроенный таким образом, что его переполнение произойдёт через время чуть меньше 2 мс (с запасом) и включим прерывание от изменения уровня сигнала на входе от фотоприёмника. При срабатывании прерывания от входа будем перезапускать этот таймер. Таким образом, пока фотоприёмник будет видеть сигнал — таймер не переполнится, а переполнение таймера будет признаком того, что сигнал от излучателя пропал.

Светодиод будет показывать состояние сигнала: гореть при наличии сигнала и не гореть при его отсутствии.

Кнопка нужна для переключения в рабочий режим. При включении, приёмник будет стартовать в настроечном режиме, в котором не будет срабатывать выходное реле (но будет работать светодиодная индикация), а через некоторое время после нажатия на кнопку, контроллер будет переводиться в рабочий режим, в котором уже при пропадании входного сигнала будет срабатывать реле.

Проверкой того, не нажата ли кнопка, контроллер будет заниматься в свободное от всех других дел время.

Ну вот, пожалуй и всё, переходим к алгоритмам:

Алгоритмы работы микроконтроллеров излучателя и приёмника ИК-барьера

Под этим катом - текст программы для контроллера излучателя

 list    p = 12f629
__config 01FE4h
;********* Переменные ***********************************
CBLOCK 0x20	;Начальный адрес блока констант
T_Cr		;таймер несущей
C_imp		;счетчик количества импульсов
ENDC
;******** Константы *************************************
Cr1	equ	.2	; длительность 1 несущей
Cr0	equ	.4	; длительность 0 несущей
NCr	equ	.19	; кол-во импульсов несущей в пакете (500 uS)
MCr	equ	.53	; пауза между пакетами (1500 us)
 
Status	equ	03h	; Регистр выбора банка
GPIO	equ	05h	; Регистр управления защелками порта
Cmcon	equ	19h	; Регистр компаратора
TrisIO	equ	05h	; Регистр выбора направления работы выводов
INTCON	equ	0Bh	; Регистр разрешения(1)/запрета(0) прерываний
OSCCAL	equ	10h	; Регистр хранения калибровочной константы
F	equ	1	; Результат направить в регистр.
;********************************************************
; GP0 - выход на транзистор, GP1, GP2, GP4, GP5 - входы
;********************************************************
 
org 0
;******** КОНФИГУРИРОВАНИЕ КОНТРОЛЛЕРА ******************
start      
;****** Калибровка Генератора ***************************
bsf	Status,5
Call	3FFh		; Загрузить калибровочную константу в w
movwf	OSCCAL
;******** Установка направления работы выводов **********
bcf	Status,5	; перейти в банк 0
clrf	GPIO		; инициализация защелок (везде нули)
movlw	.7		; биты 0..2 поднять
movwf	Cmcon		; компаратор выкл, GP0-GP2 - цифровые
bsf	Status,5	; перейти в 1-й банк
movlw	.62		; Записать конфигурацию GPIO в W
movwf	TrisIO		; Скопировать конфиг. GPIO из W в TrisIO
bcf	Status,5	; перейти в 0-й банк
 
;***** Передача единичного полубита *********************
RCY	movlw   NCr	; поместить константу NCr в аккумулятор
movwf   C_imp	; скопировать W в регистр C_imp
Y_001	movlw   Cr1	; поместить константу Cr1 в аккумулятор
movwf   T_Cr	; скопировать W в регистр T_Cr (таймер несущей)
bsf     GPIO,0	; установить на выходе GP0 единицу
Cr1_Y	decfsz  T_Cr,F	; декремент T_Cr с ветвлением
; если результат не 0, - исполняется
; следующая инструкция,
; иначе - nop вместо неё
goto	Cr1_Y	; переход на метку Cr1_Y
nop
bcf	GPIO,0	; установить на выходе GP0 ноль
movlw	Cr0	; поместить константу Cr0 в W
movwf	T_Cr	; скопировать W в регистр T_Cr
Cr0_Y	decfsz  T_Cr,F
goto    Cr0_Y
decfsz  C_imp,F
goto    Y_001
;***** Передача низкого уровня **************************
RCN	movlw   MCr	; поместить константу MCr в аккумулятор
movwf   C_imp	; скопировать W в регистр C_imp
N_001	movlw   Cr1
movwf   T_Cr
nop		; вместо bsf GPIO (для выравнивания)
Cr1_N	decfsz  T_Cr,F
goto    Cr1_N
nop
nop
nop		; вместо bсf GPIO
movlw   Cr0
movwf   T_Cr
Cr0_N	decfsz  T_Cr,F
goto    Cr0_N
decfsz  C_imp,F
goto    N_001
goto    RCY
;********************************************************
end

[свернуть]
А под этим - текст программы для контроллера приёмника

.device ATtiny13
.include "tn13def.inc"
.list
;-- определяем свои переменные
.def	w=r16		; это будет наш аккумулятор
.def	Flags=r17	; если бит 0=1 - начинаем отсчёт для
; переключения в рабочий режим
.def	TTimer=r18	; для отсчёта времени от нажатия на кнопку
; до переключения в рабочий режим
 
.equ	TTW=15		; начальное значение TTimer
.equ	TTC=180		; начальное значение TMR0
;--------------------------
.equ	IR_IN=2		; вход фотоприемника PB2
.equ	BUTTON=0	; вход кнопка  PB0
.equ	LDIODE=4	; выход светодиод PB4
.equ	RELE=3		; выход реле PB3
 
;-- Используемые регистры
; SPL - указатель вершины стека
; ACSR - управление компаратором
; DDRB - направление работы ног
; PORTB - выходы порта
; GIMSK - общее разрешение прерываний от ног
; PCMSK - выбор от каких ног разрешить прерывание
; TCCR0B - управление таймером
; TIMSK0 - прерывания от таймера
; TCNT0 - значение таймера
; OCR0A - значение модуля сравнения
; TIFR0 - флаги прерываний от таймера
;-- начало программного кода
.cseg
.org 0
rjmp Init		; переход на начало программы
;-- вектора прерываний
reti			; INT0
rjmp PinChange		; Pin Change
rjmp TimerOverflow	; Timer
reti			; EEPROM
reti			; comparator
reti			; timer compare match A
reti			; timer compare match B
reti			; watchdog
reti			; ADC
;-- начало программы
Init:	ldi w,RAMEND		; устанавливаем указатель вершины
out SPL,w		; стека на старший байт RAM
sbi ACSR,7		; выключаем компаратор
ldi w,1<<LDIODE|1<<RELE	; определяем входы/выходы (1-вых, 0-вх)
out DDRB,w
com w			; подтягивающие резисторы включены
cbr w,1<<IR_IN		; (кроме IR_IN), начальное
out PORTB,w		; состояние выходов = 0
;-- включить прерывания от ИК-приёмника
ldi w,1<<IR_IN		; выбираем ногу, к которой подключен ИК
out PCMSK,w
ldi w,1<<PCIE		; разрешаем прерывание PinChange
out GIMSK,w
;-- настраиваем таймер (сколько отводится на изменение сигнала на входе)
clr w
out TCCR0A,w		; вых.OCR0A, OCR0B откл., Normal Mode
ldi w,TTC	        ; записываем начальное значение таймера
out TCNT0,w
ldi w, 1<<TOIE0		; прерывание по переполнению
out TIMSK0,w
ldi TTimer,TTW		; начальное значение счетчика
;-- включаем таймер и прерывания
ldi w,0b00000100	; включить таймер, Normal Mode, /256
out TCCR0B,w
sei
;-- начало работы
Start:
sbic PINB, BUTTON	; если кнопка нажата -
rjmp Start		; пропустить эту команду
sbr Flags,1<<0		; устанавливаем 0-й бит (начинаем отсчёт
; до переключения в рабочий режим)
rjmp Start
 
;----------------------------------------------------------------------
;--- Interrupts ---
;--- если сработал таймер - действия в зависимости от режима
TimerOverflow:
cbi PORTB, LDIODE	; выключаем светик (сигнал пропал)
brtc TR_and_TF		; если флаг T сброшен - прыгаем
Work:	sbi PORTB, RELE		; включаем реле
rjmp Work		; и уходим в глухой цикл
;--- сбрасываем таймер и если надо - доотсчитываем до рабочего режима
PinChange:
sbi PORTB, LDIODE	; включаем светик
TR_and_TF:			; (timer reset and flag test)
ldi w,TTC		; записываем начальное значение таймера
out TCNT0,w		; (то есть перезапускаем его)
sbrs Flags,0		; если 0-й флаг установлен - 
reti			; пропускаем эту команду
inc TTimer		; увеличиваем счётчик
breq Set_Work		; если переполнился - прыгаем
reti			; выход
Set_Work:			; переходим в рабочий режим
set			; устанавливаем флаг T
reti			; выход
;----------------------------------------------------------------------

[свернуть]

Чтобы всё корректно работало — в тиньке должны быть «запрограммированы» фьюзы SPIEN, SUT0 и CKSEL0 (то есть в PonyProg напротив них должны стоять галочки). Кроме того, не затрите случайно калибровочную константу в пике.

Скачать одним архивом алгоритмы, исходники и прошивки

Добавить комментарий