|
|
|
![]() |
Lezione 7
Impariamo ad usare il PWM dei PIC
|
|
|
|
|
In questa pagina impareremo ad utilizzare il modulo CCP presente in molti PIC in modalità PWM.
Ci potremo pilotare i ponti H per i motori e fare altre cose come ad esempio, creare una sorta di uscita analogica in tensione, utile, ad esempio, per regolare la velocità di un motorino da ventola
|
|
Il PWM
In questa pagina prendiamo in esame i soliti due arcinoti PIC: il 16F876 e il fratello maggiore 16F877.
Entrambi sono dotati di due moduli CCP che noi andremo ad esplorare nella loro modalità PWM.
CCP sta a significare Capture, Compare, Pwm, Come per dire che questi moduli possono essere utilizzati per catturare segnali, comparare segnali e generare segnali.Ho già accennato che in questa pagina tratteremo solo la parte PWM che ritengo la modalità più importante per un robottaro. (anche le altre modalità non sono da meno).
In questa pagina cerchiamo di far funzionare il pwm il piu semplicemente possibile, in modo che i principianti possano già cominciare ad usarlo con il minimo sforzo. (per altro è davvero minimo)
Poi si potrà andare ad approfondire con i datasheet e, magari le cose saranno un pochino più semplici.
PWM è l'abbreviazione di Pulse Width Modulation ed è un segnale ad onda quadra, avente un periodo fisso (frequenza) e un duty cycle che può essere variato a piacere tra 0% e 100%.(il duty cycle è la percentuale del livello alto rispetto al periodo dell'onda quadra).
Specifico subito che il segnale PWM non è assolutamente adatto a pilotare dei servi da modellismo, in quanto ha un range di duty cycle troppo ampio e una frequenza troppo alta.
Questa volta il datasheet del PIC non ci basta più per capire come si attiva il PWM per i nostri scopi.
Dovremo consultare anche il reference manual dei PIC e la application note AN594, potete scaricarveli da internet e consultarli per i vostri approfondimenti.
All'interno del PIC 16F876/877 ci sono ben due moduli CCP, ciò vuol dire che possiamo generare ben due segnali PWM. L'unico limite che abbiamo è che questi due moduli usano la stessa risorsa del PIC per generare la frequenza di base (il TIMER 2).
Ne consegue che la frequenza dei due segnali PWM generati sarà identica e noi potremo variarne soltanto il duty cycle in maniera indipendente.
D'altra parte dobbiamo rallegrarci per il fatto che i due moduli CCP, una volta attivati, funzionano da soli senza impegnare altre risorse o parti di programma.
Quindi il PIC, mentre genera i due segnali PWM, può occuparsi di altre cose. Questo è importante.
In questa pagina ho deciso di descrivere solo a grandi linee il funzionamento del PWM, altrimenti diventerebbe illeggibile per i troppi numeri dei parametri che spesso si incrociano tra loro.
D'altra parte certe cose si capiscono prima con un esempio pratico che con tanti discorsi.
Dall'esempio che avrete a disposizione, potrete partire con i vostri esperimenti per approfondire l'argomento sui datasheet che ho già citato.
Cominciamo…
Per utilizzare il PWM dovremo attivare il Timer 2 del pic e settarne il prescaler, poi potremo settare i due moduli CCP in modalità PWM e definire la frequenza del PWM tramite il registro PR2.Il duty cycle sarà regolato dal registro CCPR1L e CCPR2L.Ovviamente faremo prima un bell'esempio con un modulo CCP soltanto per semplificare al massimo, poi basterà duplicare i comandi dati per un modulo per attivare anche l'altro.
Preparare la demoboard
La demoboard da usare potrà essere sia la 16F876 che la 877, è indifferente.Per poter fare una prova minima, ci basterà collegare un potenziometro alla porta A1 del PIC e un LED, con una resistenza in serie, alla porta RC2 del PIC e che corrisponde all'uscita del modulo CCP1. Il CCP2 ha come uscita la porta RC1 e per ora tralasciamola.Metto subito il programma minimo con le parti del PWM scritte in rosso. La parte dell'A/D nel programma, sapete bene qual è.
/*
* programma per generare il PWM e regolare
* il Duty Cycle con un potenziometro
*/
#include <pic.h>
#include <stdio.h>
#include "delay.c"
main()
{
unsigned short valore;
TRISB=0; //PORTB tutte uscite
TRISC=0; //PORTC tutte uscite
INTCON=0; //pulisce interrupt
CCP1CON=0; //pulisce modulo CCP1 (PORTC2)
T2CON=4; //Timer2 acceso con prescaler a 1
CCP1CON=12; //Modulo CCP1 settato in modalita' PWM
PR2=0xfe; //Step massimo del duty cycle (e frequenza)
ADCON0 = 0b11000001; //attiva porte analogiche
ADCON1= 0b10000000;
for(;;) {
ADGO = 1; //Fa partire la conversione
while(ADGO)
continue; //Attende che la conversione sia completa
valore = ADRESL+(ADRESH<<8); // risultato a 10 bit
CCPR1L=valore/4; //duty cycle CCP1
}
}
Questo programma legge il potenziometro e ricava il valore che servirà a regolare il duty cycle del PWM. Regolando il potenziometro, potrete vedere il led collegato alla porta RC2 variare la sua luminosità da zero al massimo con tutti i 256 valori intermedi possibili.
Compilatelo pure che vi farà comodo…..
Ovviamente tralasciamo anche il fatto che il PWM è una risorsa a 10 bit e qui la useremo a 8 bit.Vediamo insieme i comandi che abbiamo dato per il pwm.
TRISC=0; Le uscite dei moduli CCP sono i due pin RC1 e RC2 della porta C del PIC. Per usare il PWM bisogna settare come uscite almeno questi due pin e io l'ho fatto per tutta la PORTC per semplicità. Tra l'altro dovete ricordarvi che l'uscita del modulo CCP1 è la porta RC2 mentre l'uscita del modulo CCP2 è la porta RC1.
INTCON=0; serve per cancellare lo stato degli interrupt per evitare che ci siano valori casuali che interferiscano con le operazioni successive.
CCP1CON=0; serve a pulire il registro CCP da eventuali settaggi precedenti o casuali.
T2CON=4; accende la risorsa Tiner2 del PIC e ne setta il prescaler a 1.Il Prescsaler puo essere selezionato a 1, a 4 e a 16 mentre il postscaler non è usato nel PWM.Il valore 4, dato a T2CON corrisponde a 0b00000100 in binario e sul datasheet potrete trovare la tabella del registro Timer 2 e vedere la corrispondenza dei singoli bit che ho dato.
CCP1CON=12; Questo comando setta il modulo CCP 1 alla modalità PWM. Anch'esso l'ho messo in formato decimale ma è anche l'unico valore da dare per settare il PWM. Sul datasheet vedrete che gli altri valori settano altre modalità del modulo come il capture e il compare.
PR2=0xFE; Questo è il comando che setta la frequenza del PWM e il numero dei passi del duty cycle.La frequenza dipende anche dal prescaler del timer 2 e dal quarzo utilizzato in quel momento.Mettendo 0xFE, che è l'esadecimale di 254 sapremo che l'intero campo del duty cycle sarà diviso i 255 passi.Se avessimo messo 127 decimale, che è la metà di 254, avremo avuto un duty cycle al 100% già al al passo 127 ma con una frequenza raddoppiata. (periodo dimezzato).Dal valore che daremo a PR2 si determina anche il valore massimo da poter dare al comando seguente.
CCPR1L= valore/4; questo è il comando che varia il duty cycle del PWM. (parliamo del modulo CCP1) Il valore da passare a questo parametro potrà andare da 0 al valore impostato sul PR2.Il valore 0 fornirà un duty cycle dello 0% mentre il vaore massimo (dato da PR2) darà il 100% del duty cycle. Per essere più chiari, facciamo l'ipostesi che a PR2 avessimo dato 130. Il campo di variazione del duty cycle sarebbe stato tra 0% e il 100% con i valori di CCPR1L che vanno da 0 a 130 in 130 passi. Valori oltre il 130, fino a 255 daranno sempre il 100% del duty cycle.Nel nostro caso abbiamo un valore dato dalla porta A/D che va da 0 a 1023 e non possiamo andare oltre i 255 per rimanere nell'ambito degli 8 bit (altrimenti il compilatore si arrabbia), quindi il valore passato va diviso per 4.Il
PWM con risoluzione a 10 bit è possibile implementarlo ma, non è interessante per gli usi robotici.
Ora che dovrei aver chiarito l'uso del PWM, potete vedervi i datasheet per gli opportuni approfondimenti sulla frequenza data dalle interazioni tra la frequenza del quarzo, i parametri dati al prescaler e al PR2. Qui andiamo avanti in un altro modo e cerchiamo di aggiungere al programma il secondo modulo PWM. Ci basta duplicare i comandi già dati e aggiungere un altro potenziometro alla PORTA1 del PIC (aggiungiamo anche un altro LED alla porta RC1, così vediamo variare la luminosità pure di quello).
/*
* programma per generare il PWM e regolare
* il Duty Cycle con un potenziometro
*/
#include <pic.h>
#include <stdio.h>
#include "delay.c"
main()
{
unsigned short valore,valore1; // aggiunta una variabile
TRISB=0; //PORTB tutte uscite
TRISC=0; //PORTC tutte uscite
INTCON=0; //pulisce interrupt
CCP1CON=0; //pulisce modulo CCP1 (PORTC2)
CCP2CON=0; //pulisce modulo CCP2 (PORTC1)
T2CON=4; //Timer2 acceso con prescaler a 1
CCP1CON=12; //Modulo CCP1 settato in modalita' PWM
CCP2CON=12; //modulo CCP2 settato in modalita' PWM
PR2=0xfe; //Step massimo del duty cycle (e frequenza)
ADCON0 = 0b11000001; //attiva porte analogiche
ADCON1= 0b10000000;
for(;;) {
CHS0=0; // seleziona la porta da leggere (RA0)
DelayUs(10); //ritardo per il cambio porta analogica
ADGO = 1; //Fa partire la conversione
while(ADGO)
continue; //Attende che la conversione sia completa
valore = ADRESL+(ADRESH<<8); // risultato a 10 bit
CCPR1L=valore/4; //duty cycle CCP1
CHS0=1; //seleziona la porta da leggere (RA1)
DelayUs(10);
ADGO = 1;
while(ADGO)
Continue;
valore1 = ADRESL+(ADRESH<<8);
CCPR2L=valore1/4; //duty cycle CCP2
}
}
Adesso che avete i due pwm attivi, potete divertirvi con i vostri esperimenti e se avete anche l'oscilloscopio il divertimento è assicurato.
Un esempio di uso del pwm è collegare delle sonde termometriche alle porte anaogiche e pilotare delle ventole con il pwm.
In questo modo è possibile variare la velocità delle ventole al variare della temperatura.
Un altro esempio è il famigerato PID, che permette il controllo di motori molto accurato e condizionato da variabili esterne.
Insomma.... stavolta non avete scuse a non usare il PWM.
L'unico appunto che posso dare è che il PWM è un segnale da non confondere con il segnale di clock di certi circuiti e con il segnale PPM di altri circuiti.
Sono tre segnali identici all'oscilloscopio ma sono concettualmente molto lontani tra loro, sia per la tecnica di generazione che di utilizzo, quindi fate attenzione in futuro.
Buon lavoro.
|