Orologio - Sveglia
Link Articolo Originale: http://www.grix.it/viewer.php?page=10824
Volendo dotare la mia camera con un orologio che possa essere visibile anche durante la notte senza dover premere nessun pulsante per illuminare il display LCD, ho deciso di realizzarlo utilizzando dei display a 7 segmenti.
Il cuore del progetto risiede nel microcontrollore Microchip 16F88, di uso comune e quindi facile reperibilità.
Il software che ho sviluppato comprende 4 stati di regolazione, 1 di visualizzazione dell'orologio e 1 di funzionamento dell'orologio e della sveglia.
Visualizzazione dell'ora
void Cifre_Display()
{
result=0;
switch (mux)
{
case 1:
result=ore/10; //decine ore
cod_disp1=0;
cod_disp2=0;
mux=2;
break;
case 2:
result=ore%10; //unità ore
cod_disp1=0;
cod_disp2=1;
mux=3;
break;
case 3:
result=minuti/10; //decina minuti
cod_disp1=1;
cod_disp2=0;
mux=4;
break;
case 4:
result=minuti%10; //unità minuti
cod_disp1=1;
cod_disp2=1;
mux=1;
break;
}
dispReg = dispnum[result];
}
Avviata la procedura di visualizzazione, ogni 5 ms viene spento il display attualmente acceso e si procede all'accensione del seguente.
clicca per ingrandire |
Quindi, a secondo del valore della variavile mux, il programma accede a diverse istruzioni grazie allo switch e provvede a determinare il numero che deve essere visualizzato sul determinato display e lo attiva secondo la codifica descritta.
Per determinare il numero da visualizzare effettuo una semplice divisione:
- per la decina dei minuti divido la variavile minuti per 10.
- per l'unità dei minuti calcolo il resto della divisione intera.
Per i due display delle ore il discorso è analogo.
Si capisce quindi che la visualizzazione attravero i display delle ore e dei minuti sfrutta un sistema di multiplexing (per ulteriori informazioni sul multiplexing dei display vedere un altro esempio qui:elektor.altervista.org/contatore_multiplexato.html)
clicca per ingrandire |
Ovviamente, avendo utilizzato solo due segnali per l'accensione del singolo display, è necessario utilizzare anche un decodificatore. In questo modo le 4 combinazioni possibili dei bit di RA0 e RA1 possono identificare il singolo display.
Tabella codifica
cod_disp1 0 0 1 1
cod_disp2 0 1 0 1
00 --> digit1 --> oreH
01 --> digit2 --> oreL
10 --> digit3 --> minH
11 --> digit4 --> minL
Infine determinato il numero, si procede alla decodifica in modo da poter ottenere un valore numerico binario da porre in uscita al PORTB del microcontrollore.
dispReg = dispnum[result];
Quindi, per le definizioni precedentemente implementate nel codice sorgente:
#define dispReg PORTB //porta di collegamento dei display
#define A 128 //RB7 Decimale
#define B 64 //RB6
#define C 32
#define D 16
#define E 8
#define F 4
#define G 2
// Segmenti da accendere in base al numero (Nn) da comporre
#define m0 A+B+C+D+E+F
#define m1 B+C
#define m2 A+B+G+E+D
#define m3 A+B+G+C+D
#define m4 F+G+B+C
#define m5 A+F+G+C+D
#define m6 A+F+G+E+C+D
#define m7 A+B+C
#define m8 A+B+F+G+C+D+E
#define m9 A+B+F+G+C+D
const unsigned char dispnum[]={m0,m1,m2,m3,m4,m5,m6,m7,m8,m9};
Se result è uguale a 2 per esempio devono accendersi i segmenti A-B-G-E-D. Ad ogni segmento è associato un numero, ovvero quello per cui il corrispettivo binario posto in uscita al portB permette di accendere quello e quel solo segmento. Pertanto in questo caso, se si sommano le "codifiche" dei vari segmenti che devono essere accesi, viene visualizzato il numero in esame.
Stato 1 e 2
In questi due stati avviene la regolazione dei minuti e delle ore. Quindi, alla pressione del pulsante pt_menu avviene l'accesso allo stato 1 ed eventuali pressioni del pulsante pt_set comportano un incremento dei minuti.
Analogamente, ad una successiva pressione del pulsante pt_menu, si accede allo stato successivo e il punsate di set assume la funzione di regolazione delle ore.
Nelle due procedure qui descritte la visualizzazione è analoga a quanto detto precedentemente, l'unica differenza è che vengono completamente esclusi 2 dei 4 display.
void stato_1()
{
//Attivo la visualizzazione dei minuti per la regolazione
result=0;
if (mux<3) mux=3; //Se l'accesso alla procedura è avvenuto con la selezione del display <3 (1 o 2)
//è necessario porlo a 3 o 4 affinchè la visualizzazione possa riguardare solo
//i due display relativi ai minuti.
switch (mux)
{
case 3:
result=minuti/10; //decina minuti
cod_disp1=1;
cod_disp2=0;
mux=4;
break;
case 4:
result=minuti%10; //unità minuti
cod_disp1=1;
cod_disp2=1;
mux=3;
break;
}
dispReg = dispnum[result];
anti_minuti(); //Letura pulsante per regolazione
}
Lettura del pulsante. --> la struttura è tale per cui l'incremento dei minuti è continuo.
void anti_minuti()
{
if (!minuti_filtered)
if (pt_set)
if (contatore1 == 11)
{
minuti_filtered=1;
minuti++;
contatore1=0;
}
else contatore1++;
else if (contatore1 == 0);
else contatore1--;
else
if (pt_set)
if (contatore1 == 11) minuti_filtered=0;
else contatore1++;
else if (contatore1 == 0);
else contatore1--;
}
Stato 3 e 4
Le due funzioni sono simili a quelle dello stato 1 e 2, infatti permettono la regolazione delle ore e dei minuti della sveglia. In questo caso l'accesso ai due stati è consentito solo se la sveglia è attiva, ovvero è stato premuto il pulsante pt_sveglia e quindi l'uscita di segnalazione dell'attivazione (stato_sveglia) è alta.
Funzione Orologio e Sveglia.
Ogni 5ms viene eseguito quanto contenuto nella funzione di interrupt (sfruttato il timer1 a 16bit per avere maggiore precisione), ovvero viene resettato il flag relativo e incrementata la variabile conta.
Quando raggiungo 60 secondi incremento i minuti, raggiunti 60 minuti incremento le ore e infine raggiunto le ore 24 le resetto a 0.
if (conta==200)
{
secondi++;
conta=0;
punto^=1; //inverto lo stato del punto, resta acceso/spento per 1 sec
}
if (secondi==60)
{
secondi=0;
minuti++;
}
if (minuti==60)
{
minuti=0;
ore++;
}
if (ore==24)
{
ore=0;
}
La sveglia, una attivata tramite il pulsante relativo, compara semplicemente le ore e i minuti e, nel caso questi siano entrami uguali, l'uscita stato_sveglia che fino a questo momento era sempre rimasta attiva alta, inizia ad oscillare.
void sveglia()
{unsigned char a;
if ( ore_sveglia==ore & minuti_sveglia==minuti )
{
a=conta%50;
if (a==0) //se conta/50 = 0
{
stato_sveglia^=1;
}
}
}
Immagini realizzazione
clicca per ingrandire |
Video funzionamento
Video con buzzer di allarme e animazione all'avvio.
Qualsiasi frequenza venga utilizzata, probabilmente per la scarsa qualità del buzzer, il suono emesso è decisamente deludente.
Ho quindi intrapreso lo studio di integrati che permetto una breve riproduzione audio e giustificando quindi l'acquisto di un nuovo altoparlante di piccole dimensioni.
Download
- orologio.hex --> senza buzzer e animazione all'avvio
- Sveglia 4.3 --> con buzzer e animazione all'avvio
Elektor+