4° progetto (PIC18F45K50) – ADC con trimmer

Il progetto in questione prevede un lampeggio LED scandito da tempi ricavati dalla lettura di un valore analogico di tensione, ottenuto tramite un trimmer.

Progetto completo.

Fasi realizzazione progetto (dopo la sua creazione).

  1. Configurazione del PIC
  2. Stesura del codice:
    1. Creazione del ciclo while infinito
    2. Settaggio iniziale (pin e dispositivi)
    3. Progettazione e stesura del programma
    4. Verifica del codice e programmazione del PIC
  3. Montaggio del circuito elettrico
  4. Test su breadboard

Configurazione del PIC.

Questa può essere fatta tramite il tool descritto nel primo progetto (qui) o configurando manualmente cioè ‘scrivendo a mano’ soltanto le configurazioni cambiate.

Stesura del codice.

Creazione del ciclo while infinito.

Per funzionare, il programma ha bisogno di un while infinito entro cui noi andremo a scrivere le istruzioni che verranno svolte in continuazione.

void main(void){
    while(1){
    }
}
Settaggio iniziale (pin e dispositivi).
PINComponente
RD1+ (LED)
RD2VO (TRIMMER)

Le configurazioni principali finalizzate al nostro progetto riguardano soprattutto l’ADC. L’ADC dispone di moltissimi registri che ci permettono di gestirlo in tutte le sue sfumature:

  • ADCON0, ADCON1 e ADCON2 – Registri che contengono tutte le impostazioni dell’ADC
  • ADRESH e ADRESL – Registri che contengono il risultato della conversione ADC (vedremo le loro possibili configurazioni)

Eventualmente l’ADC si potrebbe utilizzare anche in modalità interrupt (l’interrupt si genera al termine della conversione), ma in questo caso verrà svolto in modalità polling.

La prima cosa da fare è settare l’ADC e per farlo partiamo dal registro ADCON0. Con il registro in questione andiamo a scegliere il canale ADC che vogliamo convertire, attraverso il corretto settaggio dei bit (nel nostro caso il canale è l’AN22).

ADCON0 = 0b01011001;

Sempre con questo stesso registro andiamo ad abilitare il nostro convertitore ADC, ponendo a 1 il bit meno significativo.

Il registro ADCON1 serve a selezionare le due alimentazioni di riferimento (Vref+ e Vref-). Queste due tensioni di riferimento normalmente sono utilizzate a  5V e a massa però, nel caso in cui si necessiti di un range molto più ridotto di tensione, si può ricorrere all’utilizzo di due appositi pin (vedi datasheet). Il registro in questione serve anche a selezionare il trigger con il quale verrà campionato il segnale.

ADCON1 = 0b00000000;

Con l’ultimo registro andiamo invece a selezionare il tempo di campionamento e di conversione del nostro ADC.

ADCON2 = 0b10010101;

N.B. l’ADC interno al PIC riesce a lavorare soltanto con certi tempi descritti accuratamente nel datasheet (pag.289). I settaggi fatti in questa guida rispondono a queste limitazioni.

Come avevamo accennato poco sopra, l’ADC per funzionare necessita del modulo CCP2 (Capture Compare PWM 2) per questo motivo occorre disabilitarlo in questo modo:

CCP2CON = 0x00;
CCPR2L = 0x00;
CCPR2H = 0x00;

Non ci resta ora che settare i pin necessari al progetto:

// Registro per la configurazione dei pin (INPUT-1, OUTPUT-0)
TRISDbits.RD1 = 0; // Pin collegato al LED
TRISDbits.RD2 = 1; // Pin collegato al trimmer
// Registro per la congigurazione del tipo di pin (ANALOGICO-1, DIGITALE-0)
ANSELD = 0b00000100;
Progettazione e stesura del programma.

Una volta inizializzato il nostro ADC possiamo andare a modificare il nostro ciclo infinito in modo che, ad ogni sua ‘ripetizione’, legga il valore di tensione derivato dal nostro trimmer.

Per riuscire a gestire i ritardi, dato che le funzioni predefinite del compilatore non accettano variabili, dobbiamo creare una funzione noi. Innanzitutto bisogna dichiarare la funzione prima del nostro main, in questo modo:

void RitardoMS(int d);

void main(void) {
    ...
}

Poi subito dopo il main andiamo a scrivere la nostra routine:

void RitardoMS(int d){
    // Eseguo il ciclo fino a quando d = 0
    while(d > 0){
        // Aspetto 1 ms
        __delay_ms(1);
        // Diminuisco la variabile d di 1
        d--;
    }
}

Così facendo abbiamo creato la nostra funzione per ritardi personalizzati. Non ci resta che scrivere ora il ciclo infinito:

while (1) {
    // Avviamo la conversione dell'ADC
    ADCON0bits.GO = 1;
    // Aspettiamo fino a quando la conversione non è terminata
    while(ADCON0bits.GO == 1);
    // Memorizziamo il risultato dentro una variabile
    unsigned int RisultatoADC = (ADRESH << 8) + ADRESL;
    // Utilizziamo il valore appena letto per cambiare la frequenza di lampeggio
    PORTDbits.RD1 = 1;
    RitardoMS(RisultatoADC + 1000);
    PORTDbits.RD1 = 0;
    RitardoMS(RisultatoADC + 1000);
}

Come si può leggere dai commenti interni alla parte di codice per avviare una conversione da analogico a digitale, una volta fatte tutte le impostazioni, basta:

Porre ADCON0bits.GO = 1; -> Aspettare fino a quando il bit non diventa 0 while(ADCON0bits.GO == 1);-> Leggere il risultato della conversione a seconda dell’allinemaneto scelto in precedenza unsigned int RisultatoADC = (ADRESH << 8) + ADRESL;SE A DESTRA – unsigned int RisultatoADC = ADRESH + (ADRESL >> 8); SE A SINISTRA

Verifica del codice e programmazione del PIC.

Una breve ricontrollata generale a tutto il codice unita a una buona riuscita nella compilazione del progetto ci permetteranno poi di programmare il nostro microcontrollore.

Montaggio del circuito elettrico.

Fatto questo non ci resta altro che montare il circuito.

 

 

Mi raccomando prestate particolare attenzione alle varie alimentazioni perchè la mancata attenzione su ciò potrebbe portare alla rottura di diversi componenti.

Test su breadboard.

 

Download.

La cartella del progetto completo, compilato (con XC8 v.1.42) e funzionante la potete scaricare qui  PIC18F45K50_ADC.X

 

Lascia un commento