Progetto accensione 8 luci Rnd
Eseguito per la Chiesa di Romanoro nel Dicembre 1999
Il progetto prevede l uso di un microcontrollore PIC16C84 con 8 uscite per accensione luci e 3 uscite ausiliarie. Si prevedono anche 2 ingressi.
Descrizione del circuito:
In fase di riposo il pic controlla continuamente un ingresso e se lo trova basso spegne tutte le luci che sono collegate alla porta b, quando l ingresso cambia di stato (va alto), alza o (abbassa dipende come e meglio) il bit di una uscita ausiliaria (si puo collegare lo spegnimento del mulino)e dopo un po di ritardo (fisso), accende a caso le varie luci delle casette (otto uscite), tenendo un breve ritardo tra una accensione e l altra (circa 1 secondo). Oppure, invece di controllare sempre l ingresso, si può far partire il tutto nel momento che viene alimentato.
Comunque sia il metodo per la partenza, quando ha acceso tutte le luci, dopo un periodo di tempo comincia a spegnere a random le luci e aspetta tra uno spegnimento e l altro un tempo superiore rispetto a quello avvenuto prima tra una accensione e l altra.
Ovviamente tutto questo ciclo (accensione, spegnimento di tutte le luci) deve avvenire in un tempo inferiore al tempo NOTTE fissato nella centralina alba tramonto.Questo perché avvenendo l inizializzazione del ciclo quando va in NOTTE la centralina alba tramonto, prima che quest ultima faccia ALBA o comunque quando é ancora NOTTE devono essere spente tutte le case.
Per la generazione del numero random si usa una routine che necessita di due registri (RAND_HI e RAND_LO) nei quali sono caricati 2 numeri (a 8 bit). Il registro con il Byte RAND_HI ha un valore random all accensione del pic, in altre parole non gli viene assegnato nessun valore, mentre il registro RAND_LO prende il valore dalla EEPROM del pic. Il valore che prende lo legge come già detto da un registro della EEPROM pic. Questo registro e quello puntato dal valore messo in un altro registro Eeprom che potrebbe essere l ultimo (63 D); al primo uso il valore contenuto in questo registro vale 0 quindi il numero passato a RAND_LO sarà quello contenuto nel registro 00 della Eeprom pic; la seconda volta che il programma ripartirà caricherà in RAND_LO il valore che ha trovato nel addr Eeprom pic 01 (era stato incrementato) ecc
Il numero massimo di registri è volutamente 32 (si effettua un AND con 32 con il numero letto nel adr 63D) in modo che possano rimanere liberi altri 32 registri della Eeprom pic per eventuali future modifiche.
Con questi numeri casuali contenuti nei registri della Eeprom pic, la routine genererà per 8 volte altri numeri casuali (con l aiuto di RAND_HI) che opportunamente filtrati ed elaborati contribuiranno ad accendere le luci nelle casette in modo casuale.
I vari ritardi (in secondi) sono dichiarati all inizio del listato asm:
RIT_INI : ritardo iniziale dopo che la centralina AGTN ha dato alimentazione al pic
RIT_TRA_ACC: ritardo tra una accensione di una casetta e l altra
RIT_ACC_ALL : ritardo prima di iniziare a spegnere dopo che si sono accese tutte le casette
RIT_TRA_SPE : ritardo tra uno spegnimento e l altro
Schema
Flow-chart
;**************************************************************************
;
;
Fontana Dino
;
;
listato asm luci presepe
;
;
Versione 1.2 del 01-12-99
;
;**************************************************************************
LIST p=16c84
#include
p16c84.inc;
__CONFIG 11h
constant BASE_VAR=0CH
LOOP3 equ BASE_VAR+0 ;
for timing
LOOP2 equ BASE_VAR+1
LOOP1 equ BASE_VAR+2
LOOP4 equ BASE_VAR+3
RAND_HI equ BASE_VAR+4 ;
16-bit random number
RAND_LO equ BASE_VAR+5
TEMPB equ BASE_VAR+6
TEMPLETTO equ BASE_VAR+7
TEMPDATA equ BASE_VAR+8
;-------------------------------------------------------------------------------
;
assegnazione ritardi (x 1 sec.)
RIT_INI equ .1
; ritardo all' accensione
RIT_TRA_ACC equ .1 ;
ritardo tra due accensioni
RIT_ACC_ALL equ .5 ;
ritardo dopo che tutto e' acceso prima di cominciare a spegnere
RIT_TRA_SPE equ .2 ;
ritardo tra due spegnimenti
MAIN:
clrf PORTB
; clrf
RAND_HI
; clrf
RAND_LO
bsf STATUS,RP0
clrf TRISB
; all bits on PORTB are outputs
movlw b'11111000'
movwf TRISA
bcf STATUS, RP0
clrf PORTA
;------------------------------------------------------------------------------------------------------
;
; Lettura
della EEPROM pic all' adr 63 dove e' contenuto l' adr prossimo da leggere
; si fa un
and con il numero 31
;
;--------------------------------------------------------------------------------------------
movlw .63
movwf EEADR
; leggi dalla eeprom quale regitro della stessa devo leggere
call readeeprom
movf EEDATA,W
; in EEDATA ho il valore letto
movwf TEMPDATA
; metto in TEMPDATA
movlw b'00011111'
andwf TEMPDATA,F
; faccio and con il numero 31 in modo da avere sempre un numero compreso tra 0 e 31
movf TEMPDATA,W
movwf EEADR
; metto questo numero compreso tra 0 e 31 in EEADR
call readeeprom
; leggo questo registro della EEPROM
movf EEDATA,W
movwf RAND_LO
; e metto il dato letto in RAND_LO
incf TEMPDATA,W
; aumento di uno il registro letto prima
movwf EEDATA
movlw .63
; lo scrivo nell' adr 63 cosi' la prossima volta andro' a prendere i dati da un Adr
eeprom pic successivo
movwf EEADR
call writeeprom
movlw RIT_INI
; ritardo iniziale
movwf LOOP4
call DELAY
main_1
call RANDOM
; generate 16-bit random number
movf RAND_LO,W
andlw b'00001111'
btfsc STATUS,Z
; se il risultato e' zero rirandomizza
goto main_1
call table
movwf TEMPLETTO
movf PORTB,W
andwf TEMPLETTO,W
btfss STATUS,Z
; salta se non c'e' già
goto main_1
movf PORTB,W
iorwf TEMPLETTO,W
movwf PORTB
movf PORTB,W
xorlw b'11111111' ; ho
acceso tutto
btfss STATUS,Z ;
se z e' 1 vuol dire che ho acceso tutto
goto rita
goto cspegni
rita
movlw RIT_TRA_ACC
; ritardo tra una accensione e l' altra
movwf LOOP4
call DELAY
goto main_1
; repeat indefinitely
;
-------------------------------- Inizio spegnimenti ------------------------
cspegni
movlw RIT_ACC_ALL
; ritardo dopo che sono accesi tutti prima di cominciare a spegnere
movwf LOOP4
call DELAY
main_2
call RANDOM
; generate 16-bit random number
movf RAND_LO,W
andlw b'00001111'
btfsc STATUS,Z
; se il risultato e' zero rirandomizza
goto main_2
call table
movwf TEMPLETTO
; movf
PORTB,W
comf PORTB,W
andwf TEMPLETTO,W
btfss STATUS,Z
; salta se non c'e' già
goto main_2
; movf
PORTB,W
comf PORTB,W
iorwf TEMPLETTO,F
comf TEMPLETTO,W
movwf PORTB
; movf
PORTB,W
xorlw b'00000000'
; ho acceso tutto
btfss STATUS,Z
; se z e' 1 vuol dire che ho acceso tutto
goto rita_1
goto hofinito
rita_1
movlw RIT_TRA_SPE
; ritardo tra una accensione e l' altra
movwf LOOP4
call DELAY
goto main_2
; repeat indefinitely
;
*****************************************************************************************
; Inizio Sub
;
*****************************************************************************************
RANDOM:
movf RAND_HI, W
; if current random is 0000, make it 00FFH
iorwf RAND_LO, W
btfsc STATUS, Z
comf RAND_LO, F
btfss RAND_HI, 6 ; hi.7 = hi.7 xor hi.6
movlw 00H
btfsc RAND_HI, 6
movlw 80H
xorwf RAND_HI, F
btfss RAND_HI, 4 ; hi.7 = hi.7 xor hi.4
movlw 00H
btfsc RAND_HI, 4
movlw 80H
xorwf RAND_HI, F
btfss RAND_LO, 3 ; hi.7 = hi.7 xor lo.3
movlw 00H
btfsc RAND_LO, 3
movlw 80H
xorwf RAND_HI, F
rlf RAND_HI, W ;
carry = hi.7
rlf RAND_LO, F ;
double left shift
rlf RAND_HI, F
return
;'''''''''''''''''''
DELAY:
; delays LOOP4 * 1 Sec
movlw .100
movwf LOOP3
DELAY_3
movlw .10 ; 10 msecs
movwf LOOP2
DELAY_1:
movlw .110
movwf LOOP1
DELAY_2:
clrwdt
nop
nop
nop
nop
nop
decfsz LOOP1, F
goto DELAY_2
decfsz LOOP2, F
goto DELAY_1
decfsz LOOP3, F
goto DELAY_3
decfsz LOOP4,F
goto DELAY
return
;'''''''''''''''''''''''''''
;---------------
Scrive un byte in eeprom
; dati in
imput :
;
; EEADR = indirizzo di locazione (0-63)(banco 0)
; EEDATA = Valore da memorizzare (banco 0)
;-----
writeeprom
bsf STATUS,RP0
bcf INTCON,GIE
bsf EECON1,2
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1,1
aspfine
clrwdt
; attendi fine scrittura
btfss EECON1,4
goto aspfine
bcf EECON1,4
bcf EECON1,2
bcf STATUS,RP0
retlw 0
;
;
----------------- legge un byte in eeprom ---------
;
; Dati in
input:
;
; EEADR =
indirizzo locazione da leggere ( 0 - 63 ) (banco 0)
;
-----------------------------------------
;
; Dati in
output
;
; EEDATA =
valore letto (banco 0)
;
---------------------------
readeeprom
bsf STATUS,RP0
bsf EECON1,0
bcf STATUS,RP0
retlw 0
;'''''''''''''''''''''''''
table
addwf PCL,F
retlw .1
retlw .2
retlw .4
retlw .8
retlw .16
retlw .32
retlw .64
retlw .128
retlw .1
retlw .2
retlw .4
retlw .8
retlw .16
retlw .32
retlw .64
retlw .128
retlw .255
hofinito
clrwdt
goto hofinito
end