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