Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

21
voti

LO HAI MAI REALIZZATO CON UN PIC? - Una semplice tecnica di PWM software

Indice

Abstract

Spesso molti utenti di questo sito richiedono di poter disporre di molti canali PWM, ciascuno configurabile a piacere in termini di duty-cycle. Ora, diversi microcontrollori (compresi i PICMicro, ovviamente) dispongono di molteplici canali PWM ma per rimanere nella famiglia a 8-bit al più si arriva a 6 canali, tipicamente impiegati per applicazioni di elettronica di potenza, come inveter, chopper oppure SMPS. Volendo aumentare il numero di canali PWM è necessario mettersi di impegno e cercare di implementare una tecnica per sviluppare PWM soltanto con righe di codice: via software, insomma.

Cos'è il PWM

Non mi voglio dilungare troppo su cosa sia il PWM, tecnica di modulazione di ampiezza di un'onda quadra, impiegata per diversi scopi. In questo articolo ho già trattato l'argomento in relazione al PWM generato dai moduli hardware contenuti all'interno di un PICMicro. Rimando quindi alla lettura di quell'articolo per approfondire le tematiche relative.

Ora l'intento è quello di realizzare 8 canali PWM indipendenti, ciascuno con il proprio valore di duty-cycle impostabile da 0% al 100%; l'unica "pecca" di questo sistema è che, sfruttando interrupt e timer come risorse comuni a tutti i canali PWM, il risultato è quello di avere tutti i canali in fase tra di loro e tutti con la medesima frequenza. In effetti esiste la possibilità di impostare, entro certi limiti, frequenze differenti di Fpwm, ma con il microcontrollore scelto per questo progetto/tutorial l'impresa diventa ardua, in quanto si arriva ben presto ad esaurire le risorse disponibili sul PIC.


Come realizzare un firmware-PWM

Una possibile tecnica è quella di utilizzare timer ed interrupt; l'uso dei timer in polling è infatti molto limitante ed è sconsigliato quando si vogliono avere "molti" PWM firmware. L'esempio proposto, scritto e compilato con SDCC (benché sia facilmente portabile su altri compilatori), si basa su di un PIC16F819, secondo lo schema di figura.


La tecnica non è complicata ed è descritta passo-passo nel seguito:

  • La prima cosa da fare è configurare un timer, con una base dei tempi a scelta che determinerà la periodicità con la quale verrà eseguita la funzione PWM. Per semplicità, TMR0 sarà il timer scelto per svolgere questa funzione.
  • Un secondo timer va configurato e mandato in esecuzione; questo secondo timer, ad esempio TMR2, non viene impostato per generare un interrupt su overflow, ma soltanto per funzionare come "contatore libero" e sarà quello che determinerà la frequenza (Fpwm) dell'onda quadra che viene modulata.
  • Ogni qualvolta si scatena un interrupt su overflow di TMR0, viene eseguita la funzione PWM(), la quale, per ciascun canale, confronta il valore del duty-cycle che si vuole ottenere con il valore di TMR2, e pone l'uscita PWM a valore alto o basso di conseguenza, secondo la regola:

Se duty < TMR2 -> OutPWM = 0

Se duty >= TMR2 -> OutPWM = 1

Una regola importante da seguire è quella per la quale i due timer devono avere necessariamente tempi di aggiornamento differenti, onde evitare che, essendo sincroni, il PWM sostanzialmente non sia possibile eseguirlo.

In fase di inizializzazione, ecco le impostazioni sui timer:


    // TMR0 setup
    OPTION_REG = 0x80;

    // TMR2 setup
    T2CON = 0x07;
    TMR2ON = 1;

    // TMR0 and General interrupt enable
    TMR0IE = 1;
    PEIE = 1;
    GIE = 1;


Per la gestione di TMR0 si sfrutta l'interrupt:

// Interrupt Service Routine
void Intr(void) __interrupt 0
{

// Timer 0 overflow
    if (TMR0IF) // Interrupt each 255us
    {
        PWM();         // Call PWM() function
        TMR0IF = 0;  // Clear TMR0 interrupt bit
    }
}


La funzione PWM risulta pertanto realizzata in questo modo:

// Software PWM made with the comparison between a duty value and Timer2 value

void PWM (void)
{
    if (uchStartPWM & 1 == 1)
    {
        if (uchDuty[0] >= TMR2)
        {
            RB0 = 1;
        } else {
            RB0 = 0;
        }
    }

    if (uchStartPWM & 2 == 0x02)
    {
        if (uchDuty[1] >= TMR2)
        {
            RB1 = 1;
        } else {
            RB1 = 0;
        }
    }

    if (uchStartPWM & 4 == 0x04)
    {
        if (uchDuty[2] >= TMR2)
        {
            RB2 = 1;
        } else {
            RB2 = 0;
        }
    }

    if (uchStartPWM & 0x08 == 8)
    {
        if (uchDuty[3] >= TMR2)
        {
            RB3 = 1;
        } else {
            RB3 = 0;
        }
    }

    if (uchStartPWM & 0x10== 0x10)
    {
        if (uchDuty[4] >= TMR2)
        {
            RB4 = 1;
        } else {
            RB4 = 0;
        }
    }

    if (uchStartPWM & 0x20 == 0x20)
    {
        if (uchDuty[5] >= TMR2)
        {
            RB5 = 1;
        } else {
            RB5 = 0;
        }
    }

    if (uchStartPWM & 0x40 == 0x40)
    {
        if (uchDuty[6] >= TMR2)
        {
            RB6 = 1;
        } else {
            RB6 = 0;
        }
    }

    if (uchStartPWM & 0x80 == 0x80)
    {
        if (uchDuty[7] >= TMR2)
        {
            RB7 = 1;
        } else {
            RB7 = 0;
        }
    }

}

Con queste semplici considerazioni, nelle figure che seguono è mostrato il risultato un PWM con duty-cycle al 10%, al 50% e al 90%, con Fpwm a valore di circa 500Hz.

Duty-cycle al 10%

Duty-cycle al 10%

Duty-cycle al 50%

Duty-cycle al 50%

Duty-cycle al 90%

Duty-cycle al 90%

Duty-cycle al 10% e al 90% a confronto

Duty-cycle al 10% e al 90% a confronto

Cycle slip

Se l'implementazione del PWM è tale da richiedere repentine variazioni di duty-cycle, variazioni determinate da calcoli e/o condizioni del programma, si può notare un leggero sfarfallio nella frequenza Fpwm. Il fenomeno va ricercato nel fatto che il microcontrollore deve eseguire un certo numero di istruzioni legate alla gestione degli interrupt ed al ciclo logico del programma. Il ciclo logico potrebbe essere a durata variabile, in funzione degli eventi che intercorrono, allungando o accorciando l'esecuzione di talune routine con conseguente effetto di cycle slip.


The LED CHASER

Mettendo insieme un po' di queste considerazioni, ho voluto cimentarmi nella realizzazione di un circuito a LED in grado di generare effetti luminosi: The Led Chaser. Benché di questo tipo di progetti ne è piena la rete, ho voluto mostrare come sia possibile, con poche risorse disponibili, realizzare qualche effetto luminoso. I componenti utilizzati sono veramente poco più che una manciata: il PIC16F819, 8 LED e 8 resistori, un regolatore di tensione 78L05, un condensatore da 100nF

I componenti utilizzati

I componenti utilizzati


Una volta montato il tutto, la resa luminosa è di un certo effetto. All'inizio del filmato si nota come l'accensione e lo spegnimento dei LED avvenga con una leggera sfumatura grazie all'intervento del PWM firmware implementato nel codice.


Star Light

Star Light

Qualche raccomandazione

I valori impostati nei timer sono stati determinati e testati avendo cura di verificare con la strumentazione che tutto funzionasse a dovere. La scelta di un microcontrollore diverso e/o i valori dei timer che determinano le basi dei tempi, porta inevitabilmente a rimettere tutto in discussione, non tanto dal punto di vista teorico quanto da quello pratico. Insomma, la tecnica va affinata sul campo.

Download

Metto a disposizione i file di progetto, come di consueto. Il firmware di esempio è tale da:

  • impostare il PIC16F819 affinché possa lavorare con l'oscillatore interno a 8MHz;
  • impostare il duty-cycle su diversi valori (dal 10% circa all'80% circa) su ciascuno degli 8 LED
  • avviare il PWM software.

Il file, come detto, è scritto e compilato per SDCC; lo si può scaricare a questo link.

Licenza

Questo articolo ed il software rilasciato rientrano nell'ambito della licenza CREATIVE COMMONS BY-NC-ND 3.0, secondo quanto indicato nelle note legali qui riportate.

Licenza Creative Commons

Licenza Creative Commons

Sintesi delle note legali (italiano)

Note legali (italiano)

Legal code (international)

Commons deed (international)

Biblografia

Pillole di Microcontrollori PIC

Pillole di Microcontrollori PIC

16

Commenti e note

Inserisci un commento

di ,

stefanob70, SDCC è integrabile in MPLABX, quindi puoi compilare il sorgente all'interno dell'IDE di Microchip. Chiaramente userai SDCC anziché altri compilatori, in questo caso.

Rispondi

di ,

Si certo non intendevo compilare il compilatore,ma riportare i file sorgenti sull'ambiente di sviluppo MPLAB-IDE. Ci provero' e vedremo che salta fuori.

Rispondi

di ,

SDCC è un compilatore, non puoi "compilarlo" con MPLAB IDE. Quello che intendi tu è probabilmente utilizzare MPLAB come ambiente di sviluppo e SDCC come compilatore. In linea di massima si dovrebbe poter fare, configurando MPLAB in modo che chiami il compilatore e gli passi i parametri in modo corretto, ma ti consigli di fare delle prove per esserne sicuro!

Rispondi

di ,

Ciao Paolino complimenti per l'articolo. Volevo chiederti se e' possibile caricare il sorgente SDCC e compilarlo con MPLAB-IDE che utilizza anchesso il compilatore dell'Hi-tech. Grazie.

Rispondi

di ,

Il PWM descritto qui è tutto software. I PIC a 8 bit arrivano anche a svariati canali PWM (basta vedere quelli che ha il PIC di PIERIN PIC18). Chiaro: fare un PWM software su molti canali significa in qualche modo sacrificare l'attività del microcontrollore. Si rende necessaria una analisi.

Rispondi

di ,

ciao, ho una piccola perplessità: tu parli di PIC a 8 bit, e questi hanno al massimo un paio di PWM standard e 5 o 6 timer. in genere ogni PWM utilizza un timer come base, quindi comunque non credo che si riescano ad ottenere molti canali. se bisogna fare qualcosa di complesso col PIC c'è il rischio che sia nell' ISR per molto tempo...

Rispondi

di ,

Ciao sono nuovo del forum e da poco ho iniziato la programmazione dei pic attualmante sto usando un pic 16f628a con compilatore hi-teck c ho letto il tuo articolo ed è l'unico che ho trovato chiaro per me che sono un neofita volevo chiederti se era possibile postare un programma semplice per pwm software di un solo led scritto in c perche sto trovando difficolta nel trascrivere il tuo e non so cosa sbaglio se il settaggio dei tmr o altro cmq complimenti ancora per l'articolo

Rispondi

di ,

Grazie, Carlo. Devo dire che ho anche imparato dai tanti validi maestri che ho incontrato strada facendo, sul mio cammino professionale.

Rispondi

di ,

"Studia prima la scienzia, e poi seguita la pratica nata da essa scienzia."
Paolo, Leonardo quando scrisse questo aforisma mi sa che si riferiva proprio a te; alla tua capacità non solo di descrivere ma anche di realizzare. Capacità tipica di chi lavora con passione e amore per le cosa fatte bene.
Grazie di volere condividere tutto questo anche con noi. -carlo.

Rispondi

di ,

Grazie, TardoFreak. In effetti l'idea è nata proprio a seguito di continue "richieste" di questo tipo.

Rispondi

di ,

Ottimo articolo da linkare a quantio chiedono info su come pilotare più LED con un solo PIC. Bravo Paolino! :)

Rispondi

di ,

Beh, grazie per i complimenti. Sono contento che l'effetto luci sia stato di gradimento. Per ragioni varie ho utilizzato un PIC16F con poche risorse che mi ha impedito di fare qualche gioco di luci in più. Ma sono contento che l'effetto desiderato sia stato ottenuto. Grazie mir, GuidoB, Robert8 e admin. Ah, admin: l'ossimoro è mooooooolto carino :-) Grazie. Ciao. Paolo.

Rispondi

di ,

Ai classici ossimori come ghiaccio bollente, silenzio assordante, amara dolcezza, realtà virtuale, docta Ignorantia, insostenibile leggerezza, convergenze parallele noi possiamo aggiungerne uno nuovo: grande Paolino!

Rispondi

di ,

Fantastico! Complimenti.

Rispondi

di ,

Complimenti Paolino per il progetto e l'accuratezza e completezza nell'esposizione. Anche l'effetto visivo è molto carino!

Rispondi

di ,

Come sempre complimenti Paolino per la realizzazione, bello anche il filmato ed i relativi effetti luce..... ;)

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.