giovedì 26 dicembre 2013

Studio PIC 18F (18F4431) #4 :: "PWM led"


Vai al precedente POST della serie

Generare un segnale PWM con i pic 18F è estremamente semplice soprattutto se questi dispongono del supporto hardware come nel caso del 4431.
Dando per scontato che si sappia già cosa sia un segnale PWM (eventualmente approfondire in rete l'argomento) vediamo come utilizzarlo per far lampeggiare un led in modo "sfumato" cioè con una progressione da spento fino alla massima luminosità e viceversa.

Iniziamo col dire che il 4431 dispone di 4 generatori PWM indipendenti tra loro in termini di duty cycle ma tutti dipendenti da uno stesso TIMER che ne determina la frequenza/periodo: questo TIMER è dedicato al modulo PWM e si chiama PTMR (non va confuso con gli altri timer del pic).
Associati ad ogni canale PWM abbiamo una coppia di pin di uscita: PWM0 e PWM1 (33-34) per il canale PWM0, PWM2 e PWM3 (35-36) per il canale PWM1, PWM4 e PWM5 (38/28-37) per il canale PWM2, PWM6 e PWM7 (29-30) per il canale PWM3.
NB: dato che i pin di uscita sono condivisi con le porte B e D sarà necessario riservare tali pin al modulo PWM tramite il registro PWMCON0.

In questo esempio utilizziamo un solo canale PWM: il canale 0 e solo il pin di uscita PWM0 (33).
I registri coinvolti sono: PTCON0, PTCON1, PWMCON0, PWMCON1, PTMRL, PTMRH, PTPERL, PTPERH, PDC0L, PDC0H.
I passi per generare il segnale PWM sono:
  1. inizializzare i registri di controllo del timer PTMR: PTCON0 e PTCON1
  2. inizializzare i registri di controllo del modulo PWM: PWMCON0 e PWMCON1
  3. impostare il numero di conteggi del timer PTMR settando i registri PTMRL e PTMRH (12 bit)
  4. impostare il duty cycle del segnale PWM settando i registri PDC0L e PDC0H (14 bit)
  5. avviare il timer PTMR settando a 1 il bit PTEN del registro PTCON1

Determinare la frequenza del segnale

La generazione del segnale PWM è molto semplice: il timer PTMR conta da 0 fino al valore impostato in PTPERL+H incrementando i registri PTMRL+H ad ogni impulso di clock pari a FOSC/4.
Si può ulteriormente scalare il clock attivando il prescaler agendo su PTCKPS<3:2> del registro PTCON0.

Se ad esempio utilizzo un quarzo da 8 MHZ avrò le seguenti possibili combinazioni:

OSC 8 MHZ
PTCKPSprescalerPTMR clockFrequenzaIntervallo incremento PTMR
001:1FOSC/42.000.000 HZ0,5 uSec
011:4FOSC/16500.000 HZ2 uSec
101:16FOSC/64125.000 HZ8 uSec
111:64FOSC/25631.250 HZ32 uSec

Quando il timer PTMR inizia il conteggio da 0 il pin di uscita è posto a livello alto e rimane cosi fino a quando il conteggio non raggiunge il valore impostato in PDCx: a questo punto il pin passa a livello basso.
Il conteggio prosegue fino a quando il valore di PTMRL+H non raggiunge il valore impostato in PTPERL+H: a questo punto PTMRL+H si azzerano, il pin di uscita torna alto e il ciclo ricomincia.
Questo è il funzionamento in modalità free-running: le altre due modalità possibili (single-shot e continuous-up/down) non sono trattate qui.

La frequenza del segnale PWM è quindi determinata da: (FOSC / 4) / ((PTPER+1) * prescaler).
Ad esempio: se il quarzo è da 8Mhz, il prescaler vale 1:4 e PTPER lo imposto a 0xFF avrò: (8.000.000 / 4) / (256 * 4) = 2.000.000 / 1.024 = 1.953,125 Hz.

Registri PDCxL e PDCH

Fino a qui sembra tutto molto semplice ma bisogna fare attenzione ad una particolare insidia che non emerge subito chiaramente dal datasheet: il valore del duty cycle (che determina il passaggio del segnale PWM a livello basso) va inserito nei registri PDCxL+H shiftato di 2 bit verso sinistra in quanto i primi due bit (1:0) di PDCxL determinano il Q-Clock cioè in quale fase di clock deve avvenire il confronto tra PTMRL+H e PDCxL+H.
PTMR e PTPER permettono di impostare al massimo un valore a 12 bit mentre PDCx a 14 bit cioè 12 bit di confronto del duty + 2 bit di impostazione su quando effettuare il confronto (vedi datasheet cap 18.6).

PDCx si presenta quindi in questo modo:
PDCxHPDCxL
XX XX 11 10 09 08 07 06 05 04 03 02 01 00 Q-1 Q-0

Dalla teoria alla pratica

Per far lampeggiare il led dobbiamo variare il duty cycle dallo 0% al 100% e dal 100% allo 0%.
Per fare questo possiamo utilizzare un timer oppure sfruttare un particolare interrupt generato dal modulo PWM ad ogni reset del timer PTMR: questa seconda possibilità è quella che ho scelto in questo caso.
Per semplificare le cose ho scelto di utilizzare solo i registri L e quindi limitare la risoluzione PWM a 8 bit.
Per avere un lampeggio lento ho ridotto il clock impostando il prescaler a 1:16 avendo quindi una frequenza di incremento pari a  FOSC/64.
La frequenza PWM sarà pari a: 2.000.000 / (256 * 16) = 488 Hz circa.
La durata del lampeggio è invece: (256*2) / 488 = 512 / 488 =  1,049 secondi circa.     

Il progetto MPLAB-X relativo a questo articolo è scaricabile qui.

Lo schema elettrico è il seguente:

Il risultato è questo:



Stay tuned!
ap

Vai al successivo POST della serie

NB: l'autore non risponde di eventuali danni causati da omissioni, inesattezze o errori eventualmente presenti nell'articolo pubblicato.
Prego, segnalare suggerimenti e migliorie commentando questo post o inviando una email a padnest@gmail.com.

Nessun commento :

Posta un commento