Самодельная GSM сигнализация. Пишем управляющую программу.

Содержание

Здравствуйте  дорогие друзья, вот, наконец, настают выходные дни, а это значит, что у меня есть немного свободного  времени для написания нового интересного поста.

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

В этой конструкции основой является управляющая плата с подключенным к ней сотовым телефоном.  Впрочем, вернуться к ней не сложно, нужен  лишь один клик по ссылке. Так что останавливаться здесь не буду.

Signalizatciia-pishem-programmu

Как я и обещал, настало, наконец,  время вдохнуть жизнь в бездушный «кусок текстолита» и посмотреть, что же из всего этого получится. Чем мы сейчас и займемся.

Нашей задачей является написать программу для  управляющей платки gsm сигнализации. Писать мы ее будем на ассемблере, ибо только ассемблер дает нам полное понимание работы микроконтроллера, ИМХО конечно же.

Что мы имеем

Значит так, в нашем распоряжении текстолитовая печатная плата и старенький, отслуживший свое,  сотовый телефон марки siemens. Телефон мы пока отложим в сторону, а вот над платкой будем колдовать. Наша плата имеет входы и выходы. Входные сигналы у нас подаются с кнопки и шлейфного датчика, а на выходе у нас будут соответствующие сигналы с ножек контроллера.

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

Хочу добавить только то, что должно обязательно срабатывать условие — режим охраны может быть установлен только при цельном шлейфном датчике.

В режиме «охрана» происходит постоянный мониторинг состояний шлейфного датчика, а также контролируется кнопка.

При обрыве шлейфного датчика, мирно горящий светодиод начинает весело мигать, сигнализируя о тревожном событии. На выходе появляются два сигнала: один поступает через транзисторный ключ на динамик, второй воздействует на клавишу сотового телефона. Я пока динамик подключать не буду, а вот с телефоном немного поэкспериментирую.

С составом и устройством платы, все понятно, а вот как написать программу? На этот вопрос нам поможет ответить блок-схема. С блок-схемой мы построим  логику работы нашей программы, а там и до программы не далеко. 

Логика

Логика нашей программы будет следующей:

Diagramma1

Такая получилась у меня блок-схема.  Я конечно могу что-то и упустить, так что если есть какие-то неточности то  пишите в комментариях, исправлю. Но общий смысл должен быть понятен. Здесь логика состоит в периодической проверке то шлейфа, то кнопки и в зависимости от результата выполняется то или иное действие.

При обработке кнопки программа выполняет задержку, это программная реализация антидребезга контакта при нажатии кнопки.

При  подаче питания на микроконтроллер, программой проверяется состояние шлейфного датчика. Задумка состоит в том, что сигнализацию будет невозможно поставить на охрану с разорванным шлейфом. Нажатие на кнопку просто не будет обрабатываться программой. В случае разрыва рабочая точка программы будет возвращаться в начало до тех пор пока шлейф не будет восстановлен.

Если шлейф у нас цел то программа идет на обработку кнопки. И если она не нажата, то рабочая точка также возвращается восвояси, то есть  в самое начало. При нажатии кнопки происходит один неприятный момент. Контакт кнопки не может мгновенно замкнуться или разомкнуться. Поэтому возникает контактный дребезг. Серия включений и выключений за короткий промежуток времени, буквально миллисекунды. Для нашей скоростной программы этого может оказаться достаточным чтобы распознать нажатие — отжатие кнопки.

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

Шлейф цел и кнопка нажата? Значит пора зажигать наш светик — все теперь наша охранная система находится в режиме «охрана». А рабочая точка программы идет на следующие рубежи. И теперь нам нужно опять проверить кнопку. Ведь повторное нажатие в нашей программе означает снятие с охраны. Циклы задержки также сопутствуют обработчику кнопки. Теперь нажатие кнопки гасит светодиод и рабочая точка возвращается в самое начало.

Допустим кнопку мы не трогали,а это означает что пришло время судорожно сканировать шлейфовой датчик на случай внезапного вторжения непрошеных гостей. Шлейф цел — программа возвращается к кнопочке и так далее по нашей блок-схеме. При обрыве,  на данном участке нашей логики, идет проверка на нажатие кнопки. Кнопка нажата — уходим домой, но если нажатия нет , а обрыв шлейфа зафиксирован, то производится дозвон абоненту и включается  мерцание светодиода. И это продолжается до тех пор пока хозяин не нажмет на кнопку и тем самым не отключит «тревогу».

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

Так с  логикой разобрались, теперь осталось написать управляющую программу.

Пишем программу


Как я и писал выше программа у нас представляет из себя ассемблерный код, написанный для Attiny45-20. Оформление может и так себе но что есть то есть. В тексте встречаются макросы, они конечно же будут расшифрованы.  Еще в программе применяются таймеры и прочие штуки.  На комментарии прошу не обращать внимания, все подробности будут дальше по тексту. Хочу лишь добавить что в структуру команд  и прочие особенности языка асма я не вдаюсь. Это тема слишком обширна и всего рассказать здесь не смогу.

Итак выкладываю программу по кускам:

;=================================================
;==		Программа GSM сигнализации 	===
;==  Используемый контроллер Attiny45-20PU	===
;==================================================
.include  "tn45def.inc"  ; Используем Attiny 45 - 20PU
;= Start macro.inc ========================================

; Тут будут наши макросы, потом. 
	.macro naj		//макрос мониторинга нажатия кнопки
	 clt
	 in r16, pinb
	 sbrs r16, 4
	 set
	 .endm

	.macro  otj		//мониторинг отжатия кнопки
	 clt
	 in r16, pinb
	 sbrc r16, 4
	 set
	 .endm

Строки 1-4. На этом участке кода расположена общая информация о программе. Это позволит нам вспомнить о чем была программа через некоторое время. Кому ассемблер знаком не по наслышке, наверное все это и так понятно, но начинающим думаю будет важна любая информация по теме.

В строке 5 я подключаю библиотеку tn45def.inc. В этом файле расписаны все команды относящиеся к Attiny45. Располагается данный файл в дебрях папок вашего симулятора AVR Studio или какого другого.

В строках 9-21, спрятаны небольшие макросы. В моей программе они участвуют в обработке кнопки, тем самым избавляют от написания повторяющихся участков кода. В дальнейшем, по тексту программы, я могу указывать лишь сами макрокоманды (naj, otj). В тексте программы, (ссылку на которую вы увидите в конце статьи) есть еще парочка макросов, но на них внимания обращать не стоит, они применялись в другом проекте, а здесь они висят мертвым грузом. Вообще полезно накапливать библиотеку макросов и выводить их в отдельный файл, подключая из проекта в проект. Это может значительно облегчить жизнь кодера.

.list 				; Включение листинга
.def temp=R16			; Определение главного рабочего регистра
.def loop=R17			; определение регистра организации цикла

.def loop1=r18			;определение регистров
 				;организации цикла задержки 
 				;для переключения светодиода
.def loop2=r19
.def loop3=r20

.def rab=r21
.def dat=r22

.equ kdel=20
.equ kdel1=1

В этом участке кода первая строка включает листинг. Честно говоря, не знаю для чего он мне нужен, ну да ладно, я его и так не использую. В следующих строчках посредством оператора .def мы привязываем безликим регистрам типа r16, r17 осмысленные имена — повышаем читаемость кода. Регистр temp, будет у нас наиболее эксплуатируемым, заюзаем его под различные промежуточные действия.

Оператор .equ позволяет нам присвоить числовым константам символические метки. И в дальнейшем, применяя эту метку мы можем убивать зайцев в массовом порядке. Так  если мы хотим поменять значение константы во всем тексте программы, нам достаточно изменить лишь одну строчку, например .equ kdel=20.

          .DSEG ; Сегмент ОЗУ
; FLASH ===================================================

         .CSEG	    ; Кодовый сегмент
         .ORG $000     	    ; Установка текущего адреса на ноль
         RJMP   Reset	    ; (RESET)

;вектора прерывания смотрим  именно для своей модели микроконтроллера
        .ORG $001
         RETI             ; (INT0)  Внешнее прерывание 0
         .ORG $002
         RETI             ; (PCINT) Прерывание 0 по изменению состояния выхода
         .ORG $003
         RETI	           ; (TIMER1 COMPA) Совпадение А таймера/счетчика Т1
         .ORG $004
         RETI             ; (TIMER1 OVF) Переполнение таймера /счетчика Т1
         .ORG $005
         RETI	          ; (TIMER0 OVF) Переполнение таймера /счетчика Т0
         .ORG $006 
         RETI             ; (EE_RDY) EEPROM готово
         .ORG $007
         RETI             ; (ANA_COMP) аналоговый компаратор
         .ORG $008
         RETI             ; (ADC) Преобразование АЦП завершено
         .ORG $009
         RETI             ; (TIMER1 COMPВ) Совпадение В таймера/счетчика Т1
         .ORG $00A
         RETI             ; (TIMER0 COMPА) Совпадение А таймера/счетчика Т0
         .ORG $00B
         RETI    	   ; (TIMER0 COMPB) Совпадение B таймера/счетчика Т0
         .ORG $00C
         RETI    	     ; (WDT) Тайм-аут сторожевого статуса
         .ORG $00D
	 RETI    	     ; (USI START) состояние старт USI
         .ORG $00E
	 RETI    	     ; (USI OVF) переполнение USI

На этом участке кода все просто.  Рабочая точка стартует с .ORG $000 и сразу улетает по метке reset, пропуская таблицу векторов прерывания. Ведь у нас еще не вся периферия прошла инициализацию. А вектора прерываний нам в этой программе не понадобятся.

Идем дальше…

 ; Инициализация памяти, стека, регистров========================================
reset:	  	        LDI R16,Low(RAMEND)		; Инициализация стека
		  	OUT SPL,R16			; Обязательно!!!

		  	LDI R16,High(RAMEND)
		  	OUT SPH,R16

RAM_Flush:	LDI	ZL,Low(SRAM_START)	; Адрес начала ОЗУ в индекс
			LDI	ZH,High(SRAM_START)
			CLR	R16					; Очищаем R16
Flush:		ST 	Z+,R16				; Сохраняем 0 в ячейку памяти
			CPI	ZH,High(RAMEND+1)	; Достигли конца оперативки?
			BRNE	Flush			; Нет? Крутимся дальше!

			CPI	ZL,Low(RAMEND+1)	; А младший байт достиг конца?
			BRNE	Flush

			CLR	ZL					; Очищаем индекс
			CLR	ZH

			CLR	R0
			CLR	R1
			CLR	R2
			CLR	R3
			CLR	R4
			CLR	R5
			CLR	R6
			CLR	R7
			CLR	R8
			CLR	R9
			CLR	R10
			CLR	R11
			CLR	R12
			CLR	R13
			CLR	R14
			CLR	R15
			CLR	R16
			CLR	R17
			CLR	R18
			CLR	R19
			CLR	R20
			CLR	R21
			CLR	R22
			CLR	R23
			CLR	R24
			CLR	R25
			CLR	R26
			CLR	R27
			CLR	R28
			CLR	R29

Строки 1-6. Далее выполняем одну важную вещь — инициализируем стэк. Стэк это своеобразная оперативная память, устроеннная в контроллере особым образом. Операции со стэком в АВРках используются частенько.

После этого следует глобальная очистка памяти. Ведь  никто не гарантирует, что в момент включения, контроллер будет иметь в ячейках своей памяти нули.  В ячейках памяти контроллера могут остаться какие-либо значения, поэтому лучше подстраховаться. Очищаем всю оперативную память, включая регистры общего назначения. Теперь можно спать спокойно, точнее будем двигаться дальше.

;Инициализация компаратора====================================
		ldi	temp, 0x80	; заносим 0x10000000 в регистр temp
		out ACSR, temp		; выключаем компаратор

;Инициализация портов ВВ=====================================
start:	        LDi temp, 0b11101110	 ;записываем число в регистр temp (0b11101111 - порт пб0 на вывод)
		out DDRB,  temp		 ;ставим вывод PB4 на ввод, все остальные на вывод	

		LDi temp, 0b00011001	 ;записываем число в регистр temp
		out PORTB,  temp	 ;PB0 -> порт на ввод включен подтягивающий резистор (если на вывод т вывод лог 1)
					 ;PB1 -> порт на вывод лог 0
					 ;PB2 -> порт на вывод лог 0
					 ;PB3 -> порт на вывод лог 1
					 ;PB4 -> порт на ввод, включен подтягивающий резистор
;Инициализация таймера Т1=======================================
		ldi temp, 0xf;C;b;1
		out	TCCR1, temp

Инициализируем периферию. В первую очередь отключаем компаратор (строки 2-3), здесь он нам ни к чему. Затем инициализируем порты ввода/вывода.  Порты завязанные на обработку кнопки и шлейфного датчика, настраиваем на ввод, остальные послужат нам для вывода информации, будь то светодиод, или вывод на динамик. В строках 16,17 мы инициализируем аппаратный таймер. На таймере будем реализовывать задержки.

С команды rcall opros рабочая точка программы ныряет в подпрограмму обработки шлейфа. В полном соответствии с нашей блок-схемой.

opros:
		push dat
		clt				;сбрасываем флаг Т
		sbic pinb, 0			;проверка нулевого бита, если бит сброшен (0)то выходим из подпрограммы
						;вариант проверки установленного бита -> sbrs temp, 0		
						;Если бит установлен => шлейф разорван то поднимаем флаг Т
		set						
		pop dat
		ret

Если событие есть то поднимаем флаг, если нет то нет. Подпрограмму опроса шлейфа мы разместим в конце нашей программы. Там будут и другие подпрограммы.

Сейчас я вам покажу основной цикл программы. Думаю что основная суть понятна из комментариев и нашей блок-схемы, приведенной выше.

;Начало основного цикла=======================================
nachalo:

		rcall opros			;переход в подпрограмму опроса шлейфа
		BRTs  nachalo			;если обрыв то в начало	

		naj				;мониторинг кнопки на нажатие
		brtc nachalo			;если не нажато то в начало иначе

c:		rcall wait			; задержка		

		otj				;мониторинг кнопки на отжатие
		brtc c				; если не отжато то задержка и снова проверка	

		cbi portb, 3			;если отжато то сбрасываем бит PB3(зажигаем светодиод)
		nop
kn:		naj				; мониторим кнопку на нажатие
		brtc c1 			; если не нажата то переходим к проверкам шлейфа

c2:		rcall wait			; иначе задержка

		otj				; мониторинг кнопки на отжатие	
		brtc c2				; если не отжато то задержка и снова проверка
		rjmp start			; если отжато то в начало

c1:
		rcall opros			;переход в подпрограмму опроса шлейфа
		BRTc  kn			;если не оборван то повторяем мониторинг кнопки сначала

		naj				;мониторим кнопку на нажатие
		brtc c3 			;если не нажата то переход в с3

c4:		rcall wait			; иначе задержка

		otj				; мониторинг кнопки на отжатие	
		brtc c4				; если не отжато то задержка и снова проверка
		rjmp start			; если отжато то в начало

c3:

В строке 4 — вызываем подпрограмму опроса шлейфа, где ставится нужный флаг. Затем в строке 5 анализируется состояние флага.
Далее идет обработка кнопки, но это мы тоже проходили,здесь обработчик спрятан в макрос. Нужные телодвижения, будь то временная задержка или опрос датчика выполняются прыжком в подпрограммы командой rcall.

Ладно, на этом я пожалуй закончу описательную часть кода программы. Основные моменты я показал, так что если есть вопросы или замечания, то прошу писать в комментариях. А здесь я оставлю ссылочку на текст программы,  скачать ее можно [urlspan]тут.[/urlspan]

Ах да для зашивки программы в контроллер вам понадобится программатор. Могу посоветовать программатор громова, почитайте о нем, самый простой и практичный программатор.

Также по просьбе читателей размещаю [urlspan]материалы проекта[/urlspan], нарисованные в программе Eagle CAD. В архиве лежит рисунок платы и схема.  Рисунок  платы немного довел  до ума, но пока не изготавливал.

А сейчас я хочу вам показать работу gsm сигнализации в действии, так что смотрим видео…

По-моему получилось не плохо для первого раза, раньше мне видео снимать не приходилось.

Хочу добавить, что данная программа, так же как и проект gsm сигнализации будет постепенно дорабатываться,  модернизироваться. Чтобы не пропустить выход новых статей предлагаю подписаться по [urlspan]rss[/urlspan] или по[urlspan] email[/urlspan].

Ну что же дорогие друзья, на этом у меня все. Желаю вам успехов во всем и прекрасного настроения, а всех дам с праздником 8 марта. До встречи.

С уважением, Владимир Васильев.

P.S. Друзья, обязательно подписывайтесь на обновления! Подписавшись вы будете получать новые материалы себе прямо на почту! И кстати каждый подписавшийся получит полезный подарок!

 

 

Лучший способ сказать СПАСИБО автору это отправить донат!


 

Читайте также:

комментариев 7

  1. Прикольно сделал почитал, очень интересно!! Видео оригинально!!!

  2. Гриша:

    Здравствуйте.Я новичок в этих делах.Перерыл разные сайты и из многих именно Ваше устройство мне показалось самым простым в исполнении под мои нужды.Интересуют вопросы:как и чем залить программные файлы в контроллер?все ли файлы из архива будут участвовать в прошивке контроллера?подойдет ли написанная Вами программа под другие контроллеры?если да-то еще под какие (чтоб если что в магазине аналог имеющийся можно было купить)?можно ли взамен разрыва шлейфа установить чувствительный микрофон?Заранее благодарю за ответы.

    • Это устройство я сварганил из того что было под рукой. Рад что статья заинтересовала. Чтобы залить программу в контроллер, тебе понадобится программатор. Поройся в интернете, есть простые схемы программаторов. Я эту тему только планирую осветить. Для прошивки достаточно файла с расширением .hex.
      К сожалению эта прога подойдет только для Аттини 45, впрочем как и все ассемблерные программы затачиваются, как правило, под конкретный камень.
      По части микрофона -врятли, так как микрофон аналоговая вещь. Здесь нужен датчик работающий по принципу замкнуто/разомкнуто.

  3. Конструкция, ПО, реальное воплощение в жизнь — на отлично с плюсом!!!!!
    Одно «НО», нет номиналов резисторов на сх. А для начинающих — это тёмный
    лес.
    Всего доброго, успехов. АНДРЕЙ.

    • Спасибо за комментарий. Изначально при написании этой статьи не стояла задача выложить конструкцию готового устройства доступного для повторения.
      Задача была заинтересовать человека, чтобы читатель загорелся и у него появилось желание разобраться в конструкции самостоятельно.
      А одноразовое повторение конструкции …это нет.

  4. PabloEskaban:

    Не плохо. подпишусь

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *