Elektronicky zabezpecovaci system se senzorem:Alois Regnard, Tomas Barath

Z MAM wiki

Přejít na: navigace, hledání

Alois Regnard a Tomas Barath

Obsah

[editovat] Elektronický zabezpečovací systém

[editovat] Zadání semestrální práce

Při indikaci z externího vstupu (log1 nebo log0) se vyhodnotí na mikroprocessoru ATtiny2313 narušení a po dobu vymezenou na zadání kodu z klávesnice. Sepne (při špatném kodu), nebo nesepne (správný kod) výstupní relé na další signalizaci

[editovat] Princip funkce

Celý systém se skládá ze dvou základních částí. Obvodu signalizace přerušení (obvod s optoelektronickým senzorem TCST 1103) a obvodem pro vyhodnocení (s mikroprocesorem ATTINY 2313) a následném zpracování (sepnutí relé). Systém se nachází v jednom z možných stavů. Každý stav je indikován specifickým blikáním zelené LED diody.

Odemčeno	    Ignoruje detekci narušení
Zamčeno	            Pohotovostní režim čekání na narušení
Příchodový stav	    Čas na zadání kódu v zamčeném stavu
Odchodový stav	    Čas na odchod po zadání kódu v odemčeném stavu
Poplach	            Nezadán, nebo špatný kód po narušení v zamčeném stavu – relé sepnuto
  • Po zapnutí (restartu) je systém v zamčeném stavu – bezpečnější pro případ výpadku napájení.
  • Při narušení (otevřené okno, dveře atd...) se spouští příchodový čas, během kterého uživatel může zadat přístupový kód (nastaven: 1234). Pokud se nezadá správně, nebo nebude zadán vůbec v daném časovém intervalu, tak se systém přepne do stavu poplachu a sepne relé.
  • Pokud se systém nachází v odemčeném stavu, můžeme zadat kód a tím dá systém čas na odchod, během kterého nedetekuje narušení a po uplynutí této doby se přepne do stavu pohotovosti.

Optoelektronický senzor vyhodnocuje 2 stavy činností:

  • Zakryto stav log 0 (0.038V) – sledovaný objekt zavřen (kontakt přerušen)
  • Odkryto stav log 1 (5V) – sledovaný objekt otevřen (kontakt uvolněn)

Kód má pevně danou délku a skládá se pouze z číslic. Vyhodnocení je pouze pro správnou zadanou sekvenci kódu (pro daný případ 1234). Vyhodnocení správné kombinace potvrdí červená LED dioda krátkým zablikáním a změnou stavu zelené diody. V případě špatné kombinace delším bliknutím. Kód lze zadávat po dobu časového intervalu neomezeně, avšak pokud se zadá špatné číslo, musí se doplnit na celkový počet 4 číslic a začít znova. Každý stisk klávesnice je potvrzen krátkým bliknutím červené LED diody.

[editovat] Schema zapojení vyhodnocovacího obvodu

Soubor:Obvody.JPG

[editovat] Schema zapojení optického senzoru

Soubor:Obvody1.JPG

[editovat] Zdrojový kód

;                   __________                                           
;           PA2 o--|    \/    |--o VCC
;     (LED) PD0 <--|          |--> PB7 (klavesnice sl. 3)
;     (LED) PD1 <--|          |--> PB6 (klavesnice sl. 2)
;           PA1 o--|          |--> PB5 (klavesnice sl. 1)
;           PA0 o--|          |--> PB4 (klavesnice sl. 0)
;   (cidlo) PD2 -->|          |<-- PB3 (klavesnice r. 3)
;           PD3 <--|          |<-- PB2 (klavesnice r. 2)
;           PD4 o--|          |<-- PB1 (klavesnice r. 1)
;           PD5 o--|          |<-- PB0 (klavesnice r. 0)
;           GND o--|__________|--o PD6
;                   ATTiny2313

;To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low
;byte must be read before the high byte.

.include "tn2313def.inc"

; ----------------------------------------------------------------------------
;  pouziti registru ke specialnim ucelum
; ----------------------------------------------------------------------------

.undef  XL                  ; nechceme warning u redefinice r26
.def    r_event     = r20   ; aktualni event
.def    r_status    = r21   ; aktualni stav EZS
.def    r_timeout   = r22   ; pocitadlo timeoutu stavu
.def    r_delayo    = r23   ; delay
.def    r_delayi    = r24   ; delay
.def    r_code      = r25   ; stav zadavani kodu (ff - zadavani nezacalo, 00 - chyba, 01 - zatim ok)
.def    r_blink     = r26   ; aktualni blikaci "program"
;  r29, r28 (Y) - ukazatel na aktualni znak pristupoveho kodu ve flash

; ----------------------------------------------------------------------------
;  vektory preruseni
; ----------------------------------------------------------------------------

.cseg
.org 0x0000
    rjmp        start
.org 0x0004
    rjmp        timer1_top
.org 0x000b
    rjmp        pcint_change

; ----------------------------------------------------------------------------
;  definice konstant a maker
; ----------------------------------------------------------------------------

;.equ   Timer1Top       = 975       ; TOP hodnota casovace Timer1 -> tik cca 1x za sekundu
.equ    Timer1Top       = 244       ; TOP hodnota casovace Timer1 -> tik cca 4x za sekundu
.equ    blink_delay     = 60;11        ; casova konstanta pro zpozdeni kratkeho bliknuti

; mozne udalosti
.equ    evt_code_good   = 0x01      ; zadan spravny kod
.equ    evt_code_bad    = 0x02      ; zadan spatny kod
.equ    evt_timeout     = 0x03      ; vyprsel timeout daneho stavu
.equ    evt_detect      = 0x04      ; detekovano naruseni

; kody stavu, musi korespondovat s tabulkou "ezs_status"
.equ    st_unlocked     = 0x00      ; stav odemceno
.equ    st_locked       = 0x01      ; stav zamceno
.equ    st_enter        = 0x02      ; stav prichodovy cas
.equ    st_leave        = 0x03      ; stav odchodovy cas
.equ    st_alarm        = 0x04      ; stav poplach

.equ    st_default      = 0x01      ; vychozi stav po resetu

; pojmenovani ruznych PINu
.equ    pin_keyboard    = 0
.equ    pin_status      = 1
.equ    pin_detect      = 2
.equ    pin_relay       = 6

; ----------------------------------------------------------------------------
;  definice pevnych dat
; ----------------------------------------------------------------------------

.cseg

; tabulka stavu EZS (timeout, blikacka)
ezs_status:     .db     0x00, 0b11110000        ; odemceno
                .db     0x00, 0b10000000        ; zamceno
                .db     0x40, 0b10101010        ; prichod
                .db     0x40, 0b10101010        ; odchod
                .db     0x01, 0b11111110        ; poplach

; tabulka zmen stavu:   vychozi stav       + udalost         -> cilovy stav  
ezs_transition: .db     st_unlocked | (evt_code_good << 4),     st_leave
                .db     st_locked   | (evt_code_good << 4),     st_unlocked
                .db     st_locked   | (evt_detect    << 4),     st_enter
                .db     st_enter    | (evt_code_good << 4),     st_unlocked
                .db     st_enter    | (evt_timeout   << 4),     st_alarm
                .db     st_leave    | (evt_code_good << 4),     st_unlocked
                .db     st_leave    | (evt_timeout   << 4),     st_locked
                .db     st_alarm    | (evt_code_good << 4),     st_unlocked
                .db     0x00,                                   0x00

; tabulka prevodu z 'radek, sloupec' na 'klavesa' (tabulka je konstantni, proto je ve flashi (CSEG))
kbrd_table:     .db     0x81, 0x82, 0x83, 'A'
                .db     0x84, 0x85, 0x86, 'B' 
                .db     0x87, 0x88, 0x89, 'C'
                .db     '*',  0x80, '#',  'D'

; pristupovy kod (zakonceny nulou a zarovnany na sudy pocet bajtu)
code:           .db     0x81, 0x82, 0x83, 0x84, 0x00, 0x00

; ----------------------------------------------------------------------------
;  vstupni bod programu
; ----------------------------------------------------------------------------

start:

    ; nastav stack-pointer na konec RAM
    ldi     r16, low(RAMEND)
    out     SPL, r16                ; nastav stack-pointer na konec RAM
 
    ; nastaveni Timer1 casovace
    ldi     r16, 0b01000000
    out     TIMSK, r16              ; povol preruseni pri dosazeni TOP
    ldi     r16, 0b00001101
    out     TCCR1B, r16             ; preddelicka casu 1024
    ldi     r16, 0b00000000
    out     TCCR1A, r16             ; CTC mod, TOP je OCR1A

    out     TCNT1L, r16         
    out     TCNT1H, r16             ; vynuluj counter

    ldi     r16, high(Timer1Top)
    out     OCR1AH, r16             ; nastav TOP hodnotu
    ldi     r16, low(Timer1Top)
    out     OCR1AL, r16

    ; nastav preruseni pri zmene log. urovne na klavesnici
    ldi     r16, 0b00001111
    out     PCMSK, r16
    ldi     r16, 0b00100000
    out     GIMSK, r16

    ; nastav I/O porty
    ldi     r16, 0b11110000
    out     DDRB, r16
    ldi     r16, 0b00001111
    out     PORTB, r16          
    ldi     r16, 0b01000011
    out     DDRD, r16           
    ldi     r16, 0b00000100
    out     PORTD, r16

    ; nastav vychozi hodnoty specialnich registru
    ldi     r_code, 0xff
    ldi     r_status, st_default
    rcall   ezs_status_init

    ; povol preruseni a jed
    sei

main_loop:
    
    rjmp    main_loop

; ----------------------------------------------------------------------------
; obsluha dovrseni citace (pravidelne "tiky")
; ----------------------------------------------------------------------------

timer1_top:

    ; zkontroluj, zda bezi timeout
    tst     r_timeout               ; je r_timeout nulovy?
    breq    detect_test             ; je, timeout tedy nebezi, bez rovnou testovat naruseni
    dec     r_timeout               ; timeout bezi, sniz citac
    brne    detect_test             ; pokud timeout jeste nevyprsel do nuly, neres ho
    ldi     r_event, evt_timeout    ; timeout vyprsel, nastav udalost ...
    rcall   ezs_event               ; ... a zpracuj ji

detect_test:

    ; pokud je detekovano naruseni, opakuj udalost naruseni
    sbis    PIND, pin_detect        ; pokud je detekovano naruseni, vynech nasledujici instrukci
    rjmp    blink_test              ; naruseni detekovano neni, preskoc rovnou na blikani
    ldi     r_event, evt_detect     ; naruseni -> nastav udalost "evt_detect" ...
    rcall   ezs_event               ; ... a zpracuj ji

blink_test:

    ; blikej podle blikaciho programu
    lsl     r_blink                 ; rotuj blikaci program a nejvyssi bit vysun do C
    brcc    blink_off               ; pokud nejvyssi bit byl 0, skoc na vypnuti LED

    ; zapni indikaci stavu
    sbi     PORTD, pin_status       ; rozsvit LED
    ori     r_blink, 0x01           ; dopln nejvyssi vysunuty bit zpatky na zacatek, at muzem blikat naveky
    reti

blink_off:
    
    ; vypni indikaci stavu
    cbi     PORTD, pin_status
    reti

; ----------------------------------------------------------------------------
; obsluha EZS udalosti
; ----------------------------------------------------------------------------

ezs_event:

    ; vytvor kod z akt. stavu a udalosti pro vyhledavani v tabulce prechodu
    lsl     r_event
    lsl     r_event
    lsl     r_event
    lsl     r_event
    or      r_event, r_status
    ldi     ZH, high(2*ezs_transition)
    ldi     ZL, low(2*ezs_transition)

ezs_event_search:
    
    lpm     r16, Z+                 ; nacti kod stavu a udalosti v tabulce
    tst     r16                     ; je nulovy?
    breq    ezs_event_end           ; ano, konec tabulky
    lpm     r17, Z+                 ; nacti potencialni cilovy stav
    cp      r16, r_event            ; porovnej kod z tabulky s hledanym kodem
    brne    ezs_event_search        ; pri nerovnosti hledej dal
    mov     r_status, r17           ; prislusny prechod nalezen - menime stav

ezs_status_init:

    ; inicializace noveho stavu (blikacka, timeout...)
    ldi     ZH, high(2*ezs_status)  ; adresa zacatku ...
    ldi     ZL, low(2*ezs_status)   ; ... tabulky s informacemi o stavech
    mov     r16, r_status           ; priprav si index aktualniho stavu
    lsl     r16                     ; vynasob ho dvema (kazdy zaznam v tabulce ma dva bajty)
    add     ZL, r16                 ; a pricti ho k Z, abychom...
    clr     r16                     ; ... se dostali ...
    adc     ZH, r16                 ; ... na prislusny zaznam
    lpm     r_timeout, Z+           ; nacti novou hodnotu casoveho citace stavu
    lpm     r_blink, Z+             ; nacti novy blikaci "program"

    ; sepni nebo vypni rele podle typu stavu (0-ty bit timeoutu)
    sbrs    r_timeout, 0
    rjmp    ezs_event_relay_off
    
    sbi     PORTD, pin_relay
    rjmp    ezs_event_end

ezs_event_relay_off:
    
    cbi     PORTD, pin_relay

ezs_event_end:

    ret

; ----------------------------------------------------------------------------
; obsluha klavesnice
; ----------------------------------------------------------------------------

pcint_change:

    ; priprava pro cteni stisknutych klaves
    ldi     ZH, high(2*kbrd_table)  ; uloz do Z adresu zacatku tabulky klaves (ve flash)
    ldi     ZL, low(2*kbrd_table)   ; pozdeji se budes do tabulky pomoci Z neprimo odkazovat
    clr     r19                     ; kod stisknute klavesy
    ldi     r16, 0x10               ; maska pro OUT

kbrd_scan_column:

    ; precti radek klavesnice pro dany sloupec do bitu 0-3 registru r17
    com     r16                     ; zvoleny pin tlac na log. 0, ostatni nech vstupni
    out     PORTB, r16              ; nastav vybrany sloupec
    com     r16                     ; vrat puvodni hodnotu r16, zaroven "sync latch" pred in
    in      r17, PINB               ; nacti hodnotu na radcich sloupce
    ldi     r18, 4                  ; zkoumejme prectene 4 bity
    
kbrd_scan_rows:

    ; otestuj postupne bity 0-3 registru r17, precteneho jako radek klavesnice
    lsr     r17                     ; vysunme si nejnizsi bit do C flagu
    brcs    kbrd_continue           ; C = 1, klavesa tedy neni stisknuta, pokracuj

    ; prislusna klavesa je stisknuta    
    tst     r19                     ; byla uz nalezena stisknuta klavesa drive?
    brne    kbrd_stop               ; ano, jsou tedy stisknuty minimalne 2, spatny konec :-(
    lpm     r19, Z                  ; ne, nacti kod stisknute klavesy z tabulky

kbrd_continue:

    ; prejdi na dalsi klavesu v rade
    adiw    ZL, 1                   ; presun se na dalsi pozici v tabulce kodu klaves
    dec     r18                     ; sniz citac neotestovanych bitu
    brne    kbrd_scan_rows          ; pokud jsou jeste bity k testovani, jed znovu

    ; radek byl docten, posun se na dalsi sloupec
    lsl     r16                     ; posun masku na dalsi sloupec    
    brne    kbrd_scan_column        ; pokud mam jeste sloupce k testovani, jed znovu

    ; prozkoumany vsechny klavesy - otestuj, byla-li nejaka stisknuta
    tst     r19
    breq    kbrd_stop               ; zadna stisknuta nebyla - skonci

    sbi     PORTD, pin_keyboard
    rcall   delay
    cbi     PORTD, pin_keyboard

    sbrs    r19, 7                  ; je-li nastaven nejvyssi bit kodu klavesy, jedna se o cislici
    rjmp    kbrd_stop               ; neslo o cislici, nic zajimaveho

    ; byla stisknuta cislice, zadavame tedy pristupovy kod
    cpi     r_code, 0xff            ; zadavani kodu jeste nezacalo?
    brne    kbrd_code_next          ; uz zacalo, zpracuj dalsi cislici
    ldi     r_code, 0x01            ; zadani je zatim spravne
    ldi     YH, high(2*code)        ; uloz do Y adresu nasledujiciho ...
    ldi     YL, low(2*code)         ; ... znaku pristupoveho kodu

kbrd_code_next:

    movw    ZL, YL                  ; ukazatel na kod presun do Z (kvuli instrukci lpm)
    lpm     r16, Z+                 ; nacti ocekavany znak kodu (a posun Z na dalsi)
    movw    YL, ZL                  ; vrat Z do Y
    cp      r16, r19                ; porovnej ocekavany znak s kodem zrovna stisknute klavesy
    breq    kbrd_code_ok            ; pokud jde o spravny znak, pokracuj ...
    clr     r_code                  ; ... v opacnem pripade nastav, ze kod je spatny

kbrd_code_ok:

    lpm     r16, Z                  ; koukni na pristi ocekavany znak kodu
    tst     r16                     ; otestuj ho na nulu
    brne    kbrd_stop               ; pokud nejde o konec kodu, skonci
    tst     r_code                  ; jsme na konci kodu, otestuj spravnost zadaneho kodu
    brne    kbrd_code_entered       ; kod byl zadan spravne, zpracuj udalost

    ; kod byl zadan nespravne
    ldi     r_code, 0xff            ; resetuj sledovac zadavaneho kodu
    ldi     r_event, evt_code_bad   ; nastav udalost "evt_code_bad" ...
    rcall   ezs_event               ; ... a zpracuj ji

    ; loserovske bliknuti
    rcall   delay
    sbi     PORTD, 0
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    rcall   delay
    cbi     PORTD, 0

kbrd_stop:

    ; konec obsluhy klavesnice
    ldi     r16, 0x0f
    out     PORTB, r16              ; vrat klavesnicovy port do puvodniho stavu
    nop                             ; nech ustalit vstup
    nop                             ; (aneb dalsi sync-latch)
    ldi     r16, 0x20               ; ignoruj zmeny, ktere probehly na portu B behem obsluhy preruseni...
    out     EIFR, r16               ; ... zapisem log. 1 do bitu PCIF tento priznak vynuluj
    reti

kbrd_code_entered:

    ; kod byl zadan spravne, vyvolej udalost
    ldi     r_code, 0xff
    ldi     r_event, evt_code_good  ; nastav udalost "evt_code_good" ...
    rcall   ezs_event               ; ... a zpracuj ji

    ; vitezny blikot
    rcall   delay
    sbi     PORTD, 0
    rcall   delay
    cbi     PORTD, 0
    rcall   delay
    sbi     PORTD, 0
    rcall   delay
    cbi     PORTD, 0
    rcall   delay
    sbi     PORTD, 0
    rcall   delay
    cbi     PORTD, 0

    rjmp    kbrd_stop

; ----------------------------------------------------------------------------
;  pomocne rutinky
; ----------------------------------------------------------------------------

; kratke aktivni cekani (urcene hlavne pro kratke bliknuti LED)
; mimo preruseni volat *pouze* mezi cli a sei
delay:
    ldi     r_delayo, blink_delay

delay_loop_outer:
    clr     r_delayi

delay_loop_inner:
    dec     r_delayi
    brne    delay_loop_inner
    dec     r_delayo
    brne    delay_loop_outer
    ret

[editovat] Obrázek zapojení

Soubor:Obvody3.jpg

Osobní nástroje