Наш магазин на eBay Наш магазин на AliExpress Наш канал в 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 напротив них должны стоять галочки). Кроме того, не затрите случайно калибровочную константу в пике.

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

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