Elaborato Di Lorenzo Enzo N46000021

Transcript

Elaborato Di Lorenzo Enzo N46000021
Scuola Politecnica e delle Scie
ienze di Base
Corso di Laurea in Ingegneria
a Informatica
Elaborato finale in Misure per
er l'Automazione e la Produzione Indust
striale
Progetto e impleme
entazione di un
contatore reciproco
co basato su PIC18F4620
in ambiente Proteu
us
Anno Accademico 2013/2014
Relatore:
Prof. Rosario Schiano Lo Mo
oriello
Candidato:
Enzo Di Lorenzo
matr. N46000021
Indice
Indice .................................................................................................................................................... 3
Introduzione ......................................................................................................................................... 5
Capitolo 1: Descrizione teorica dei componenti .................................................................................. 6
1.1 Il Contatore ................................................................................................................................ 6
1.2 Misuratore di frequenza o Frequenzimetro ................................................................................ 6
1.3 Misuratore di Periodo o Contatore Numerico ............................................................................ 8
1.4 Contatore Reciproco .................................................................................................................. 9
1.5 Descrizione dell'ambiente di sviluppo ..................................................................................... 10
1.5.1 Proteus 7 Professional ....................................................................................................... 10
1.5.2 MPLAB IDE ..................................................................................................................... 10
1.5.3 Microcontrollore PIC18F4620 .......................................................................................... 11
1.5.4 LCD (LM016L)................................................................................................................. 12
Capitolo 2: Realizzazione e descrizione ........................................................................................... 13
2.1 Premessa................................................................................................................................... 13
2.2 Collegamento dei componenti ................................................................................................. 13
2.3 Inizializzazione dei Componenti .............................................................................................. 14
2.3.1 Timer e Clock di sistema .................................................................................................. 14
2.3.2 Display LCD ..................................................................................................................... 17
2.4 Programma principale “Main” ................................................................................................. 19
Capitolo 3: Simulazione e Test .......................................................................................................... 23
3.1 Misurazione Bassa Frequenza .................................................................................................. 23
3.2 Misurazione Alta Frequenza .................................................................................................... 24
3.3 Misurazione al Limite .............................................................................................................. 25
Conclusioni ........................................................................................................................................ 26
Bibliografia ........................................................................................................................................ 27
3
4
Introduzione
Nel seguente lavoro di tesi è stato realizzato un progetto che in maniera automatica
implementi il comportamento di un contatore reciproco basato sul PIC18F4620.
Lo schema circuitale, ovvero l'ambiente dove viene simulato il progetto, è stato realizzato
con Proteus, un software per la simulazione dei microprocessori.
I componenti presenti nello schema, sono stati programmati in un linguaggio basato sul
linguaggio C ed il software è stato realizzato interamente nell'ambiente di sviluppo
MPLAB. Lo scopo di questo progetto, oltre a rappresentare il suddetto contatore
reciproco, è anche quello di voler dimostrare come l'informatica unita all'elettronica riesca
ad ottenere automaticamente risultati che l'uomo da solo non potrebbe mai raggiungere,
come ad esempio quello di contare quante volte si ripete un segnale ad alta frequenza in un
determinato lasso di tempo.
5
Capitolo 1: Descrizione teorica dei componenti
1.1 Il Contatore
Il Contatore, come si può evincere dal significato del nome, è uno strumento che conta il
numero di volte che un particolare processo o evento si verificha. Misurare ad esempio
due intervalli di tempo, quello campione preso come riferimento e quello sotto misura,
equivale a contare quante volte l'intervallo campione si ripete nell'intervallo da misurare o
viceversa. Un semplice esempio è quello di prendere un intervallo campione pari ad 1
secondo e supponendo che esso venga ripetuto per 60 volte, riusciamo a sapere che
l'intervallo misurato è equivalente ad 1 minuto, ovvero 60 secondi
Definito ciò, lo scopo del progetto è quello di realizzare un contatore che autonomamente
dato un segnale in ingresso con frequenza "f", riesca a stampare tale frequenza su un
display.
1.2 Misuratore di frequenza o Frequenzimetro
Il misuratore di frequenza o frequenzimetro é uno strumento di misura che permette di
determinare mediante un operazione di conteggio, quante volte un segnale si ripete,
calcola dunque la frequenza del segnale. Di seguito, in Fig.1.1 lo schema del
Frequenzimetro.
tx
x(t)
c(t)
Condizionamento
del segnale
Unità di
conteggio
Visualizzazione
Tc
Condizionamento
del segnale
Fig. 1.1
6
Come è possibile osservare in ingresso abbiamo due segnali: c(t) è il clock che viene preso
come segnale campione essendo un segnale che oscilla con una frequenza nota, mentre
x(t) è il segnale che si vuole caratterizzare.
La presenza dei due blocchi di condizionamento permette di adattare i segnali in ingresso
alla restante parte del circuito.
Il condizionamento del segnale x(t) genera un impulso ad ogni termine di ciclo del
segnale, questi impulsi saranno poi contati dall'unità di conteggio e il risultato verrà così
visualizzato come frequenza del segnale x(t).
Il condizionamento del segnale c(t)
fornisce un segnale rettangolare di durata Tc,
chiamato tempo di gate o tempo campione. Il fronte di salita e quello di discesa
determinano rispettivamente il segnale di start e di stop per il conteggio degli impulsi di
x(t). L'unità di conteggio conta il numero di impulsi che si verificano tra lo start e lo stop
forniti dal tempo di gate. Se si prende come tempo di gate un segnale rettangolare di
durata pari ad un secondo, il risultato del conteggio sarà direttamente visualizzato dal
blocco di visualizzazione come la frequenza misurata in Hz.
Infatti, definendo N come risultato ottenuto dall'unità di conteggio, risulta che
da cui la frequenza
= sarà:
fx =q
N
Tc
Il pedice "q", vicino al simbolo di uguale, sta a significare che il conteggio avverrà nel
senso della quantizzazione, ovvero non si terrà conto delle frazioni di periodo.
Definendo ∆ =
risoluzione in frequenza, si può notare che la frequenza è espressa
come un multiplo di ∆ , e se si vuole misurare un frequenza di 1Hz, bisogna settare un
tempo di gate almeno pari ad 1s. Se si vuole ottenere un buona misurazione, occorre
aumentare il tempo di gate. Se analizzando la risoluzione relativa, definita come il
rapporto
∆
, si nota che la risoluzione relativa è direttamente proporzionata ad N, dunque
per un fissato valore Tc , all'aumentare di N la risoluzione migliora.
∆
=
1 1
=
1
=
1
7
1.3 Misuratore di Periodo o Contatore Numerico
Il misuratore di periodo o contatore numerico è uno strumento di misura che permette di
determinare il periodo di un segnale ignoto mediante un’operazione di conteggio,
confrontandolo con un segnale noto a priori.
Di seguito è raffigurato in Fig.1.2 lo schema del Contatore Numerico.
Tc
c(t)
x(t)
Condizionamento
del segnale
Unità di
conteggio
Visualizzazione
Tx
Condizionamento
del segnale
Fig. 1.2
Lo schema è composto principalmente dagli stessi componenti del Frequenzimetro, con la
differenza che gli ingressi sono invertiti, quindi il segnale definisce l'intervallo di tempo e
il clock determina gli impulsi da conteggiare.
Se definiamo sempre con N il numero di impulsi contati dall'unità di conteggio, otteniamo
come risultato della misurazione il periodo del segnale in ingresso:
= Il risultato,
, é espresso come multiplo di
misurazione di periodo è proprio
e il massimo errore che si può avere nella
.
Analizzando anche in questo caso la risoluzione relativa definita come rapporto di
notiamo che, fissato
∆
,
, all'aumentare di N la risoluzione migliora.
∆
=
=
=
1
8
1.4 Contatore Reciproco
Il contatore reciproco è uno strumento di misura che dato un tempo fissato di clock
scelto un tempo determinato di gate
,e
, in modo intelligente effettua una misura di
frequenza o di periodo su un segnale in ingresso ottimizzando la risoluzione, e quindi
effettuando una misurazione più precisa.
Confrontando le due risoluzioni relative, rispettivamente di frequenza e di periodo:
∆
=
1 1
=
1
=
1
∆
=
=
=
1
possiamo notare che nella misurazione di frequenza, per ottenere una misurazione
accettabile, abbiamo bisogno di una frequenza del segnale maggiore della frequenza
campione, mentre in quella di periodo la situazione deve essere opposta, ovvero il periodo
del segnale campione deve essere maggiore. Ricordiamo che nella misurazione di periodo
il massimo errore che si può commettere è proprio pari al periodo campione.
Detto ciò, possiamo tracciare un grafico che mette in evidenza la soglia del contatore
reciproco che determina se è opportuno usare una misurazione anziché l'altra.
∆
∆
∆ Frequenza
∆ Periodo
0
1
Fig. 1.3
Come si può evincere, abbiamo due regioni di decisione definite dalla soglia di valore
unitario dato dall'intersezione delle due equazioni. Questa soglia si presenta quando la
frequenza del segnale in ingresso e quella del segnale campione sono uguali.
Quindi il contatore reciproco, quando il segnale in ingresso avrà frequenza maggiore di
quella del segnale campione, procederà con una misurazione di frequenza, in caso
9
contrario procederà con una misurazione di periodo. Spesso le misurazione più usata è
proprio quest’ultima, dato che il segnale campione più utilizzato è il segnale del clock di
sistema ed è a frequenza elevata.
1.5 Descrizione dell'ambiente di sviluppo
Il progetto è stato interamente realizzato con componenti virtuali e sviluppato con due
software, uno per la realizzazione del circuito elettrico con i componenti, Proteus 7
Professional e l'altro per lo sviluppo del codice Mplab IDE.
1.5.1 Proteus 7 Professional
Proteus 7 Professional è un software prodotto dalla
Labcenter Elettronics per la realizzazione virtuale di
circuiti elettrici con l'aggiunta di componenti elettronici,
come i microcontrollori "PIC", misuratori, convertitori,
display, generatori, keypad, led, bottoni ed altri ancora.
Fig. 1.4
Attraverso una finestra di editing è possibile scegliere, attraverso un menù, i componenti
da usare e disporli graficamente come se li stessimo posizionado su una base, per poi
interconnetterli con collegamenti eletrici virtuali.
1.5.2 MPLAB IDE
MPLAB IDE è un software che permette di realizzare la logica del
progetto, ovvero consente di sviluppare un codice che andrà poi
caricato nel microcontrollore permetendogli di eseguire delle
funzionalità specifiche.
Fig. 1.5
MPLAB utilizza come linguaggio di programmazione il C/C++ ed è stato progettato per la
configurazione di diverse tipologie di microchip. Al suo interno troviamo infatti alcune
librerie che ne aiutano la realizzazione e da una semplice interfaccia grafica che permette
10
di simulare il software già in fase di progettazione. Una volta compilato, il programma
appena realizzato può essere caricato nel PIC ed è possibile simulare il tutto poichè
Proteus Professional può essere utilizzato in maniera integrata anche all'interno di
MPLAB.
1.5.3 Microcontrollore PIC18F4620
Il PIC18F4620 è un dispositivo elettronico capace di interagire con altri dispositivi e di
gestirli
svolgendo
in
maniera
diverse
precedentemente
autonoma
funzionalità
caricate
nella
propria area di memoria.
Di PIC ne esistono diverse versioni
che si distinguono per una parte del
nome, ad esempio le versioni che
usano i CMOS all'interno del nome
Fig. 1.5
hanno una C, le versioni invece che usano le ROM hanno CR mentre le versioni che usano
una memoria FLASH presentano una F come il PIC18F4620. Dunque, questi dispositivi
possiedono una propria memoria, sono capaci di effettuare dei calcoli, e se non fosse per le
prestazioni limitate, potrebbero essere paragonati a delle CPU. Uno dei principali vantaggi
di questi dispositivi è il basso costo e la facilità di programmazione.
Il PIC è composto oltre dalla memoria anche da altre fondamentali componenti, tra cui
ricordiamo il Clock interno, generato da un oscillatore utile ad esempio a sincronizzare
una determinata operazione utilizzando la frequenza del sistema, oppure un clock esterno
se si vuole una temporizzazione diversa.
Inoltre i Microcontrollori sono dotati di alcune porte, ognuna delle quali è dotata di diversi
pin configurabili in ingresso o in uscita.
11
1.5.4 LCD (LM016L)
Il display LM016L è uno degli LCD alfanumerici più
usati
ed
è
possibile
interfacciarlo
con
svariati
microcontrollori ad 8 e a 4 bit. Il dispositivo è composto
da 14 Pin e supporta oltre 80 caratteri su due livelli. I
Fig. 1.6
primi 3 pin servono per l'accensione del display, mentre il secondo blocco di altri 3 pin
serve al controller del display per interpretare in modo giusto il dato che poi gli sarà
invitao attraverso l’ultimo blocco di pin. In base al comando ricevuto, il display capirà se è
un codice di configurazione o è un dato da far visualizzare.
12
Capitolo 2: Realizzazione e descrizione
2.1 Premessa
Partendo dal presupposto che questo elaborato ha come scopo la progettazione di un
Contatore Reciproco, dopo una panoramica generale sul comportamento di questo
strumento, vorrei adesso far presente che il progetto realizzato è una variante del classico
Contatore. La diversità sta proprio nella misurazione che avviene tramite la coordinazione
dei due timer, il Timer0 e il Timer1, oltre che nel comportamento sia come frequenzimetro
che come Contatore Numerico. Di seguito verrà illustrata la realizzazione del progetto e
alla fine verrà proposta una breve simulazione per verificarne il corretto funzionamento.
2.2 Collegamento dei componenti
Come prima cosa sono stati posizionati i componenti tracciando un opportuno circuito per
farli interagire. Sono stati posizionati due generatori per l'alimentazione del
microcontrollore e del display. Per quanto riguarda il PIC. al pin RC0, impostato come
ingresso, è stato collegato un clock che sarà poi usato come tester per controllare se il
contatore reciproco effettua una misura accurata, mentre ai pin RC1, RC2, RC3 sono stati
collegati tre ingressi dell’LCD che serviranno ad inizializzare il dispositivo prima di ogni
operazione. Questi ingressi sono rispettivamente:
RS (Comando), RW ( Lettura o
Scrittura) e RC3 (Abilitazione), mentre ad ogni singolo bit della porta D sono stati
collegati i rispettivi 7 pin del display, dedicati alla ricezione di un codice di comando o di
un carattere da visualizzare .
A questo punto per ricordare meglio quesi collegamenti possiamo etichettare le uscite con
una nomenclatura più facile da ricorare.
Di seguito è riportato il codice di queste definizioni :
define DATA
PORTD
#define RS
PORTCbits.RC1
13
#define RW
PORTCbits.RC2
#define E
PORTCbits.RC3
#define SCELTACMD
PORTCbits.RC1 = 0
#define SCELTADATO
PORTCbits.RC1 = 1
#define SCRIVI
PORTCbits.RC2 = 0
#define LEGGI
PORTCbits.RC2 = 1
#define ABILITARW
PORTCbits.RC3 = 1;
Nop();
PORTCbits.RC3 = 0;
2.3 Inizializzazione dei Componenti
2.3.1 Timer e Clock di sistema
Il Timer è un contatore con scadenza programmabile che permette di temporizzare
operazioni predefinite facendo riferimento ad un segnale deterministico locale (clock di
sistema) o esterno. In questo progetto è stato scelto un segnale con frequenza 4 MHz,
ovvero un clock al quarzo con FOSC/4, pari ad un milione di oscilazioni al secondo.
Ai fini del progetto sono stati configurati due timer: Timer0 e Timer1, il primo è usato
come temporizzatore per la configurazione degli altri componenti, ed il secondo è
prettamente usato per la realizzazione del contatore reciproco.
L’inizializazione dei Timer è definita in due semplici funzioni che settano opportunamente
il registro del Timer rispettando le esigenze richieste.
void configTmr0(void){
// Abilitazione/Disabilitazione
T0CON = 0;
// 8/16 bit
T0CONbits.T08BIT = 0;
// Prescaler
T0CONbits.PSA = 1;
}
14
void configTmr1(void){
// Abilitazione/Disabilitazione
T1CON = 1;
// Lettura/Scrittura 8/16 bit
T1CONbits.RD16=0;
// Clock Interno/Esterno
T1CONbits.T1SYNC=0;
// Prescaler
T1CONbits.T1CKPS1=0;
T1CONbits.T1CKPS0=0;
// Ingresso del clock esterno "RC0"
T1CONbits.TMR1CS=1;
}
Ritengo opportuno soffermarmi sul concetto di prescaler, ma prima bisogna capire come
funziona il Timer. Ad ogni ciclo di clock il registro del Timer viene incrementato di
un’unità, fino a che non si riempie e all’incremento successivo va in overflow. Dunque se
prendiamo come esempio un Timer a 8 bit dopo 255 cicli di clock il Timer va in overflow
e se stiamo usando un clock a 4MHz riempiremo il registro in meno di mezzo
millisecondo1.
Per avere un intervallo di tempo maggiore usando sempre il registro ad 8 bit bisogna usare
il Prescaler, il quale altro non è che un divisore di frequenza, che ottiene tempi di
esecuzione più alti ma senza modificare la velocità del sistema. Ad esempio se vogliamo
usare un prescaler 1:16 il registro verra incrementato con una frequenza pari a
(FOSC/4)/16 e quindi, riferendoci allo stesso esempio di prima, questa volta andremo in
overflow dopo circa 4 secondi, un tempo nettamente superiore a quello precedente. In
questo progetto tuttavia il prescaler non viene impiegato, avendo poichè a disposizione un
registro a 16 bit, possiamo conteggiare fino a 65535 cicli di clock. Il clock usato ha una
frequenza di 4MHz e quindi facendo la proporzione si ottiene l’incremento del registro di
un’unità ogni microsecondo2. Detto ciò il timer andrà in overflow al massimo dopo 65535
µs, circa 65 ms. Se volessimo utilizzare un tempo maggiore avremmo bisogno del
prescaler. In questo progetto avendo bisogno di un tempo minore il prescaler non è
1
2
Questa unità di misura verrà successivamente definita con la sigla “ms”.
Questa unità di misura verrà successivamente definita con la sigla “us”.
15
necessario, ma è invece necessario un tempo specifico, per determinare il quale si va a
precaricare il registro in modo da arrestarsi nel tempo desiderato. Questo è proprio quello
che viene fatto nelle prossimo codice.
void waitusTmr0(int us){
// Precarico il registro
unsigned int appoggio = 0xFFFF - us;
TMR0H = appoggio/256;
TMR0L = appoggio - (appoggio/256)*256;
// Avvio il Timer
T0CONbits.TMR0ON = 1;
// Aspetta fino a che non va in overflow e resetta il tutto
while ( !INTCONbits.TMR0IF);
INTCONbits.TMR0IF = 0;
T0CONbits.TMR0ON = 1;
}
void waitmsTmr0(int ms){
// Precarico il registro
unsigned int appoggio = 0xFFFF - ms*1000;
TMR0H = appoggio/256;
TMR0L = appoggio - (appoggio/256)*256;
// Avvio il Timer
T0CONbits.TMR0ON = 1;
// Aspetta fino a che non va in overflow e resetta il tutto
while ( !INTCONbits.TMR0IF);
INTCONbits.TMR0IF = 0;
T0CONbits.TMR0ON = 1;
}
Nelle precedenti due funzioni si può notare che il precaricamento altro non è che il
caricare il registro al massimo valore, al quale viene sottratto numero di µs che si vogliono
attendere. È facile notare che le due funzioni svolgono la medesima operazione, con la
differenza che nella prima viene passata come parametro una quantità in µs, mentre nella
seconda è passata in ms e perciò tale parametro è moltiplicato per un fattore pari a 1000.
Le due operazioni che seguono servono a trasferire il valore calcolato nella parte alta e
bassa del registro con un piccolo stratagemma matematico ed una volta fatto ciò si avvia il
16
timer. Si attende fintantochè il registro non si riempie e alzi di conseguenza il bit che
indica l’overflow, dopodichè si resetta il tutto e si esce dalla funzione.
2.3.2 Display LCD
Il display LM016L, già introdotto nel capitolo precedente, per avviarsi oltre
all’alimentazione ha bisogno per avviarsi di una procedura di inizializzazione che serve a
settare dei determinati valori. Questa procedura ha bisogno di tempi di attesa prestabiliti e
ci serviremo del Timer0 come temporizzatore. La procedura è un susseguirsi di istruzioni
di comando, salvataggio della modifica e attesa di un breve lasso di tempo. Di seguito è
riportato il codice utilizzato nell’inizializzazione del display e alla fine seguiranno alcune
funzioni utilizzate per scrivere dei caratteri su di esso.
void inizializzaLCD(void){
int i = 0;
waitmsTmr0(20);
SCELTACMD;
SCRIVI;
// Attivazione LCD
DATA = 0x30;
ABILITARW;
waitmsTmr0(5);
DATA = 0x30;
ABILITARW;
waitusTmr0(100);
DATA = 0x30;
ABILITARW;
waitusTmr0(100);
// Fine attivazione LCD
// Impostazione #bit comunicazione, #linee, font
DATA = 0b00111000;
ABILITARW;
waitusTmr0(100);
// Spegnimento display, cursore e blink
DATA = 0b00001000;
ABILITARW;
17
waitusTmr0(100);
// Clear display
DATA = 0b00000001;
ABILITARW;
waitusTmr0(100);
// Entry mode set Direzione cursore e shift display
DATA = 0b00000110;
ABILITARW;
waitmsTmr0(2);
// Accensione display, cursore e blink
DATA = 0b00001111;
ABILITARW;
waitusTmr0(100);
}
void scriviStringa(char* myString){
short int i = 0;
SCELTADATO;
SCRIVI;
// Cicla la stringa
while(myString[i]!=0){
scriviCarat(myString[i]);
i++;
}
}
void scriviCarat(char myChar){
SCELTADATO;
SCRIVI;
DATA = myChar;
ABILITARW;
waitusTmr0(100);
}
void selezRiga(short int riga, short int colonna){
SCELTACMD;
SCRIVI;
18
if(riga)
DATA = 0xC0 + colonna;
else
DATA = 0x80 + colonna;
ABILITARW;
waitusTmr0(100);
}
Come si può notare, per scivere sul display bisogna scrivere un carattere alla volta e se si
vuole scrivere una parola o più parole bisogna ciclare l’intero insieme di caratteri.
L’ultima procedura non serve per scrivere ma per seleziona su quale riga del display
vogliamo scrivere i nostri caratteri, infatti il display che stiamo utilizzando è un display a
due livelli.
2.4 Programma principale “Main”
Il Main è la parte principale del progetto, la parte dove viene implementata tutta la logica
che fa funzionare il contatore reciproco. È suddiviso in tre parti: una prima parte di
inizializzazione dei componenti e delle variabili usate nel progetto, una seconda per lo
sviluppo dei vari algoritmi di calcolo e di logica del contatore ed infine una terza per la
stampa del risultato sul display.
La logica utilizzata in questo progetto non segue di pari passo il concetto di contatore
come abbiamo visto nel primo capitolo dove venivano contati gli impulsi del segnale da
misurare tra il fronte di salita e quello di discesa del tempo di gate. La logica utilizzata è
molto simile la quale sfrutta una sincronizzazione fra i due timer. Si utilizza il Timer0
come campione e il Timer1, incrementato con clock esterno, come contatore.
Detto ciò implemenare il frequenzimetro è un’operazione facile infatti, bastera lanciare il
Timer1 e aspettare un tempo fissato con il Timer0. Finita l’attesa, il Timer1 viene loccato
e si va a leggere nel registro di quante unità è stato incrementato, e in base al tempo di
attesa sarà semplice ricavare la frequenza. Ad esempio: se il tempo di attesa è pari a 50ms,
il numero che otteniamo da registro dovrà essere moltiplicato di un fattore 20 e otterremo
la frequenza del segnale direttamente in Hz. Ma supponiamo che passati i 50ms il registro
del Timer1 non è ancora stato incrementato, cosa succede? Questo accade quando il
19
segnale in ingresso ha un periodo maggiore del tempo di attesa, perciò in questo caso il
contatore reciproco dovrà effettuare una misurazione di periodo e quindi dovrà contare
quante volte si ripete un fissato tempo campione, fino a che il registro del Timer1 non si
incrementa di una singola unità, e basterà moltiplicare il numero di conteggio per il tempo
ottenendo il periodo del segnale in ingresso. Una volta ottenuto il periodo, facendo il
reciproco otteniamo la frequenza. Tutta questa logica è implementata in un ciclo infinito
all’interno del Main, e ad ogni giro calcola la frequenza che vine poi stampata sul display.
Il Main completo è riportato nel codice seguente:
#include <p18f4620.h>
#include "myTimer.h"
#include "myLCD.h"
// Dichiarazione delle Variabili
char benvenuto[12] = {"Hello world"};
char codice[10] = {"00000"};
char Hz[4]= {"Hz"};
float freq=0;
int result;
int count =-1;
void main(void){
// Il primo bit configurato come ingresso
// ed i restanti come uscite
TRISC = 0b0000001;
TRISD = 0;
PORTC = 0;
PORTD = 0;
configTmr0();
configTmr1();
inizializzaLCD();
scriviStringa(benvenuto);
selezRiga(1,0);
while(1){
if(count<0){
// Frequenzimetro
freq = 0;
20
TMR1H=0x00;
TMR1L=0x00;
T1CONbits.TMR1ON=1;
waitmsTmr0(50);
T1CONbits.TMR1ON=0;
freq=TMR1L;
freq+=TMR1H*256;
if(freq>2){
result=freq*20;
int2str(result,codice);
selezRiga(2,0);
scriviStringa(codice);
scriviStringa(Hz);
}else{
count=count+1;
}
}else{
// Contatore Numerico
freq = 0;
count = 0;
TMR1H=0x00;
TMR1L=0x00;
T1CONbits.TMR1ON=1;
while(TMR1L<3){
waitmsTmr0(1);
count=count+1;
}
T1CONbits.TMR1ON=0;
freq=3000/(count);
result=freq;
int2str(result,codice);
selezRiga(2,0);
scriviStringa(codice);
scriviStringa(Hz);
count = -1;
}
}
}
21
Come si può notare, nelle prime righe di codice riportate all’interno del Main, troviamo la
parola “Include” seguita dal nome del file con estensione “.h”. La loro funzione è quella
di includere delle librerie che vengono usate nel progetto. Le librerie non sono altro che
file contenenti funzioni generiche che possono essere utilizzate in varie occasioni, in modo
tale che qual’ora dovessero servire non è necessario riscrivere la funzione, ma basta
semplicemente includere la libreria che la contiene. La prima della lista serve ad inserire le
funzioni base del PIC, infatti il nome del file è proprio “PIC18F4620.h”, ed è una libreria
di sistema che viene aggiunta direttamente con l’editor di sviluppo, mentre le altre sono
state progettate direttamente per la realizzazione di questo progetto. Si tratta delle funzioni
principali dei timer e dell’Lcd con l’aggiunta di altre funzioni che svolgono un insieme di
istruzioni una o più volte, come ad esempio “scriviStringa” che richiama più volte la
scrittura di un carattere sul display. L’utilità delle librerie, oltre ad evitare la ripetitivita del
codice, serve anche ad utilizzare alcune funzioni già testate da altri e ad avere una
maggiore leggibilità del codice nel caso in cui ci sia bisogno di effettuare una modifica.
Questo perché a volte determinate procedure, come ad esempio l’inizializzazione del
display, sono lunghe ed elaboriose, ma venendo eseguite sempre le stesse istruzioni, è
sufficiente includere la ibreria del display e chiamare la funzione con una singola riga e
sarà poi compito del compilatore richiamare il codice nell’ordine giusto per essere
eseguito.
22
Capitolo 3: Simulazione e Test
In questo capitolo, simuleremo graficamente il Runtime del Contatore Reciproco,
riportando graficamente le vari fasi dell’operazione di misura.
Lo schema virtuale, completo è riportato in figura 3.1 ed è composto dal PIC 18F4620,
dall’LCD e dal Generatore di Clock che andremo poi ad impostare per simulare il segnale
in ingresso.
Fig. 3.1
Una volta posizionati i componenti bisogna trasferire il programma all’interno del
microprocessore e settare il segnale di ingresso ad una frequenza di test. Successivamente
si accende il simulatore che iniziera ad eseguire il codice precedentemente caricato.
3.1 Misurazione Bassa Frequenza
Nella prima simulazione, viene impostata una frequenza pari a 4Hz nella zona evidenziata
in rosso, figura 3.2, e dato che è una frequenza molto bassa il contatore effettuerà una
misurazione di periodo. Il risultato atteso è proprio quello di leggere dal display una
frequenza di 4Hz, figura 3.3. Il primo test ha avuto esito positivo e quindi il contatore a
basse frequenze si comporta come un contatore di periodo, ottenendo una misura accurata
della fequenza del segnale in ingresso.
23
Fig. 3.2
Fig. 3.3
Nella figura 3.3 si può notare una cosa in paticolare. I pin in ingresso al display sono
colorati di rosso o di blu, indicando rispettivamente una tensione alta o bassa che in
digitale significa avere o non avere l’ingresso, e quindi a runtime è possibile visualizzare
lo stato di ogni singolo ingresso.
3.2 Misurazione Alta Frequenza
Nella seconda misurazione, invece, viene impostata una frequenza pari a 600 Hz, una
frequenza di test cento volte superiore alla precedente e quindi, considerando che stiamo
parlando di un alta frequenza il contatore reciproco si comporterà come un frequenzimetro
effettuando una misurazione diretta di frequenza.
Fig. 3.4
Fig. 3.5
Ed anche in questo caso il test ha avuto un esito positivo.
24
3.3 Misurazione al Limite
A questo punto vengono effettuate le utlime due misurazioni impostando due segnali con
frequenza limite per vedere come si comporta il contatore in questi casi. La prima
frequenza è quella di 1 Hz e il contatore riesce a leggerla senza nessun problema. La
seconda invece è stata impostata a 32.000 Hz perché impostando una frequenza maggiore
il risultato non è corretto, a causa della variabile di tipo intero usata per memorizzare il
risultato. Questo accade perche il tipo INT riesce a contenere come valore massimo
32.767, ovvero 215.
Fig. 3.6
Fig. 3.7
Fig. 3.8
Fig. 3.9
25
Conclusioni
Concludendo, dopo aver effettuato altri test su varie misurazioni non riportati
graficamente nella simulazione, si può affermare che questa variante del Contatore
Reciproco riesce a misurare la frequenza con una buona attendibilità, ma presenta anche
alcuni punti critici. Innanzi tutto, punto critico è il valore di soglia, cioè dove avviene il
passaggio dalla misurazione di frequenza a quella di periodo. Usando un seganle con
frequenza appartenete a questo range, può capitare di avere un’oscilazione del risultato
con una variazione di qualche unità. Un altro problema è che riusciamo a rappresentare al
massimo 30khz, e quindi un segnale con frequenza superiore a questo valore non può
essere visualizzato, proprio perchè non si riesce a memorizzare una frequenza superiore.
Il compito principale in questo progetto era la realizzazione dello strumento senza
soffermarsi sulla scalabilità o sulla percentuale di attendibilità del risultato, ritengo quindi
opportuno fermarmi con queste caratteristiche e lasciare la risoluzione di queste
problematiche allo sviluppo della versione successiva.
Uno sviluppo futuro, potrebbe essere quello di caricare questo codice in un vero
PIC18F4620 e collegare il tutto ad un vero display, in modo da vedere praticamente gli
strumenti e il loro modo di interagire.
Concludo citando questa bellissima frase di Theodore von Kármán
“Lo scienziato descrive ciò che esiste; l'ingegnere crea ciò che non era mai stato.”
26
Bibliografia
MICROCHIP@, http://www.microchip.com.
[1]
MPLAB® IDE User’s Guide.
[2]
PIC18F2525/2620/4525/4620 Data Sheet
http://hitachi.com
[3]
HITACHI HD44780U Dot Matrix Liquid Crystal Display
Controller/Driver Data Sheet
[4]
MPLAB® C18 Compiler User’s .
[5]
C18 Step by step.
27