Brainbooster
Che cos'è il PWM
Tutorials -
Lunedì 05 Luglio 2010 22:44
Scritto da Brainbooster

Ovvero prendiamo confidenza con il PWM di Arduino Duemilanove

La modulazione di larghezza di impulso (Pulse Width Modulation) pu√≤ essere usata da Arduino in diversi modi. In questo tutorial cercher√≤ di spiegare l'uso di PWM "semplici" , cos√¨ come come utilizzare il PWM  ed i registri che lo regolano per un maggiore controllo sul ciclo di lavoro e di frequenza.

Un segnale PWM √® un'onda quadra (meglio rettangolare) che varia da 0V a VCC (tensione di uscita massima che per arduino √® 5V) , dove la frequenza √® costante , e cambia la frazione di tempo in cui il segnale √® attivo  a VCC ( detto ciclo di lavoro utile o dutycycle) pu√≤ essere variata tra 0 e 100 %.

Your browser may not support display of this image.

Il PWM ha diversi utilizzi :

  • Variare la luminosit√† di un led LED (tramite un filtro rc), fornendo una tensione analogica tra lo 0% e il 100%.
  • Generare di frequenze udibili e quindi audio
  • Controllare la velocit√† dei motori
  • Controllare servomotori da modellismo
  • Puo essere usato come generatore di segnale modulante
  • Ed altro ancora

Semplice PWM con l'uso del comando analogWrite

Il linguaggio di programmazione Arduino, rende il PWM facile da usare , è sufficiente chiamare analogWrite(Pin , dutyCycle ), Dove dutyCycle è un valore da 0 a 255, e Pin è uno dei pin PWM (3, 5 , 6, 9 , 10, o 11). Il comando analogWrite fornisce una semplice interfaccia per il PWM hardware, ma non fornisce alcun controllo sulla frequenza.

Ma andiamo un p√≤ pi√Ļ in profondit√†... ci sono altre opzioni che forniscono pi√Ļ flessibilit√† :)

Il PWM manuale su tutti i pin

√ą possibile  creare "manualmente" un PWM su ogni pin semplicemente "spegnendo" e "accendendo" un pin in uscita. ad esempio:

void setup ()

{

pinMode (13, OUTPUT) ;

}

void loop ()

{

digitalWrite (13 , HIGH) ;   / / Lascio il pin "acceso" (per 100ms)

delayMicroseconds (100); / / Circa il 10 %  di duty cycle (sarebbe 1KHz)

digitalWrite (13, LOW);     / / Spengo il pin ed aspetto il prossimo ciclo

delayMicroseconds (900) ;/ / Attesa prima del prossimo ciclo (per 900ms)

}

 

Facendo così, si ha il vantaggio di poter utilizzare qualsiasi pin di uscita digitale . Inoltre, avete il pieno controllo del duty cycle e della frequenza. Uno dei principali svantaggi è che ogni interrupt inciderà negativamente sui tempi , a meno che non si disattivino gli interrupt. Un altro svantaggio è che non si può lasciare girare il processo mentre il processore fa qualcos'altro. Infine , è difficile determinare le costanti appropriate per un ciclo di funzionamento particolare e la frequenza richiesta, a meno che non si calcoli attentamente dai cicli di clock.

Uso del PWM parlando con i registri dell'atmega di Arduino

Il chip ATmega168P/328P ha tre timer PWM , che controllano le 6 uscite PWM. Manipolando il timer del chip direttamente tramite i registri , è possibile ottenere un maggiore controllo rispetto al analogWrite per "piegarlo" alle nostre necessità.

Il datasheet dell'ATmega328P  fornisce una descrizione dettagliata dei timer PWM, ma ati pu√≤ essere difficile da capire, a causa delle molteplici modalit√† di uso dei timer.

Proviamo a capirci qualcosa. (datasheet alla mano ;) )

Il ATmega328P ha tre timer conosciuti come Timer 0, Timer 1 e Timer 2 . Ogni timer ha due output con dei registri a comparazione che controllano la larghezza PWM per il timer di due uscite : quando il timer raggiunge il valore di comparazione impostato nel registro , l'uscita corrispondente è attivata . Le due uscite per ogni timer normalmente hanno la stessa frequenza , ma possono avere cicli di lavoro differenti (a seconda dei rispettivi valori dei registri a comparazione).

Ciascuno dei timer ha un prescaler che genera il suo clock dividendo il clock di sistema per un fattore di Prescale come 1, 8, 64 , 256 o 1024. Arduino duemilanove ha un clock di sistema di 16MHz e la frequenza di clock del timer sarà la frequenza di clock di sistema diviso per il fattore Prescale . Attenzione il Timer 2 ha un diverso insieme di valori Prescale rispetto agli altri timer .

I timers sono complicati da diverse modalit√† di uso e controllo. Le modalit√† PWM principali sono " PWM Fast "e" PWM a correzzione di fase ". Il timer pu√≤ essere pilotato con valori 0-255 (8 bit) , o da un valore fisso, se serve. (Il  Timer 1  √® dotato di modalit√† supplementari per supportare valori fino a 16 bit. ) Ogni uscita pu√≤ anche essere invertita.

Il timer può anche generare interrupt con overflow , ma questo và oltre le mie possibilità esplicative (per adesso).

Timers e Registri

Per controllare ogni timer vengono utilizzati vari registri. I Timer / Counter dei Registri di controllo  TCCRnA e TCCRnB contengono il bit di controllo principale per i timers.Questi registri possono contenere diversi gruppi di bit :

  • bit di Generazione di forme d'onda ( WGM ): questa e la modalit√† di controllo globale del timer. (Questi bit sono divisi tra TCCRnA e TCCRnB .)
  • bit Clock Select ( CS ): questo serve a controllare il prescaler sul clock
  • bit di comparazione uscita A ( COMnA ): questo serve ad attivare / disattivare / l'output invertito per  l'uscita A
  • bit di comparazione uscita B ( COMnB ): questo serve ad attivare / disattivare / l'output invertito l'uscita B

Le uscite di comparazione dei Registri OCRnA e OCRnB servono ad impostare i livelli a cui le uscite A e B saranno "azionate". Quando il valore del timer corrisponde al valore di registro , l'uscita corrispondente viene modificata come specificato dalla modalità.

I bit sono leggermente diversi per ogni timer , (vedi datasheet per i dettagli).Come dicevamo prima, il Timer 1 è un timer a 16 bit e dispone di modalità aggiuntive e Timer 2 ha valori diversi di prescaler .

Fast PWM

Nel "semplice" PWM , il timer conta ripetutamente 0-255 . L'uscita si accende quando il timer √® a 0, e si spegne quando il timer corrisponde a quanto impostato nell'apposito registro. Pi√Ļ alto √® il valore nel registro di uscita , maggiore √® il dutycycle. Questa modalit√† √® nota come Fast PWM Mode.

L'esempio seguente illustra come usare le uscite per due valori particolari di OCRnA e OCRnB . Da notare che entrambe le uscite hanno la stessa frequenza, ed usano la frequenza di un ciclo completo di clock .

Fast PWM Mode

L'esempio di codice seguente imposta il PWM sui pin 3 e 11, (Timer 2). Per riassumere le impostazioni di registro , Il bit di generazzione di forma d'onda WGM lo impostiamo a 011 (selezione fast PWM mode). Impostiamo i bit COM2A e COM2B a 10 (PWM non invertito per le uscite A e B). l'impostazione del bit CS la mettiamo a 100 (quindi dividiamo il clock di sistema per 64). (Poiché i bit sono diversi per i diversi timer , consultare il datasheet .)

Le uscite dei registri di comparazione sono impostate arbitrariamente a 180 e 50 per il controllo del dutycycle del PWM per le uscite A e B. (Naturalmente, si può anche modificare i registri direttamente invece di utilizzare pinMode, ma è necessario impostare il pin di uscita. )

 

Su Arduino Duemilanove , abbiamo questi valori :

* Frequenza dell'uscita A: 16 MHz / 64 / 256 = 976.5625Hz

* Uscita A dutycycle: (180 +1) / 256 = 70,7%

* Frequenza dell'uscita B: 16 MHz / 64 / 256 = 976.5625Hz

* Uscita B dutycycle: (50 +1) / 256 = 19,9%

La frequenza di 16MHz (frequenza del clock di sistema), diviso per il valore prescaler (64) , diviso per i 256 cicli necessari per un ciclo del timer.

PWM a correzione di fase

La seconda modalit√† di PWM  √® chiamata phase-correct PWM. In questa modalit√† , il timer conta da 0 a 255 e poi di nuovo gi√Ļ a 0. L'uscita si spegne, appena il timer raggiunge il valore del registro di comparazione di uscita durante la salita , e si gira nuovamente appena il timer raggiunge il valore del registro di comparazione di uscita durante la discesa . Il risultato √® un uscita pi√Ļ simmetrica . La frequenza di uscita sar√† pari a circa la met√† del valore per la modalit√† fast PWM, perch√© avverr√† allo scadere del tempo , sia in su che in gi√Ļ (un p√≤ dome le memorie DDR dei pc).

L'esempio seguente imposta il PWM a correzione di fase sui pin 3 e 11, (Timer 2). I bit di forma d'onda WGM sono impostati su a 001 (fase -correct PWM).

Gli altri bit sono uguali allèesempio del fast PWM .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A1 ) | _BV ( COM2B1 ) | _BV ( WGM21 ) | _BV ( WGM20 );

TCCR2B = _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Su Arduino Duemilanove , abbiamo questi valori:

  • Frequenza uscita A : 16 MHz / 64 / 255 / 2 = 490.196Hz
  • Dutycycle uscita A: 180/255 = 70,6%
  • Frequenza uscita B : 16 MHz / 64 / 255 / 2 = 490.196Hz
  • Dutycycle uscita B : 50 / 255 = 19,6%

Come vedete dai valori, il PWM phase correct , divide la frequenza in due rispetto al fast PWM, perché il timer scatta sia a monte che a valle . Sorpresa delle sorprese, la frequenza è divisa per 255 invece di 256, e ai calcoli del Ciclo non aggiunge uno come per il fastPWM.

Oltre il limite : fast PWM

Entrambi le modalit√† di PWM dispongono di un modo aggiuntivo che permette di controllare la frequenza di uscita . In questa modalit√† , il timer conta da 0 a OCRA, invece  che da 0 a 255. Questo d√† un controllo sulla frequenza di uscita pi√Ļ preciso rispetto alle modalit√† precedenti. (Per un controllo di frequenza ancora pi√Ļ preciso, usa il timer 1 a 16 bit ).

Si noti però,che in questa modalità, solo uscita B può essere utilizzata per il PWM ; OCRA non può essere utilizzato in due modi contemporaneamente. Tuttavia, vi è una modalità speciale per caso "Toggle Ocna on Match "che cambia lo stato di uscita A alla fine di ogni ciclo , generando un duty cycle fisso del 50% e la frequenza di un mezzo in questo caso.

Nel diagramma seguente, il timer viene azzerato quando cicla OCRnA , producendo una frequenza di uscita pi√Ļ veloce per OCnB che negli esempi precedenti. Nota come Ocna cambia una volta per ogni reset del timer.

Fast PWM con cimatura di OCRA.

Il codice seguente imposta PWM fast sui pin 3 e 11, (Timer 2), utilizzando OCR2A come valore di limite superiore del timer. Il bit di forma d'onda e generazione WGM sono impostati su 111 per PWM fast ma ora OCRA  ha il controllo sul limite superiore. Il limite superiore di OCR2A lo fissiamo arbitrariamente a 180 , e  OCR2B lo fissiamo arbitrariamente a 50. OCR2A adesso e in modalit√† " Attiva quando corrisponde", imposiamo il bit COM2A a 01 .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A0 ) | _BV ( COM2B1 ) | _BV ( WGM21 ) | _BV ( WGM20 );

TCCR2B = _BV ( WGM22 ) | _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Sul Arduino Duemilanove , abbiamo questi valori :

  • Frequenza di uscita A: 16 MHz / 64 / (180 +1) / 2 = 690.6Hz
  • Dutycycle uscita A : 50%
  • Frequenza di uscita B : 16 MHz / 64 / (180 +1) = 1381.2Hz
  • Dutycycle uscita B: (50 +1) / (180 +1) = 28,2%

Si noti che in questo esempio, il timer va da 0 a 180, che però prende 181 cicli di clock , per cui la frequenza di uscita è divisa per 181. L'uscita A ha la metà della frequenza dell'uscita B perché la modalità di confronto cambia l'uscita A una volta per ogni ciclo completo del timer .

Oltre ogni limite : ma per il phase-correct PWM

Allo stesso modo , il timer può essere configurato per il phase -correct PWM e ciclare quando raggiunge OCRnA .

L'esempio seguente imposta PWM phase correct sui pin 3 e 11, (con il Timer 2), utilizzando OCR2A come valore superiore per il timer. I bit del WGM sono impostati su a 101 per PWM phase correct con il controllo del limite superiore. Il limite superiore  OCR2A √® fissato arbitrariamente a 180 , e la OCR2B (registro di confronto) √® fissato arbitrariamente a 50. OCR2A modalit√† √® impostato su " Attiva su corrispondenza al confronto", impostando i bit COM2A a 01 .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A0 ) | _BV ( COM2B1 ) | _BV ( WGM20 );

TCCR2B = _BV ( WGM22 ) | _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Sul Arduino Duemilanove , abbiamo questi valori :

  • Frequenza dell'uscita A: 16 MHz / 64 / 180 / 2 / 2 = 347.2Hz
  • Dutycycle uscita A : 50%
  • Frequenza dell'uscita B: 16 MHz / 64 / 180 / 2 = 694.4Hz
  • Dutycycle uscita B: 50 / 180 = 27,8%

Si noti che in questo esempio, il timer va da 0 a 180 e di nuovo a 0 , il che prende 360 cicli di clock. Così, tutto è diviso per 180 o 360, a differenza del caso PWM fast, che invece ha diviso tutto con per 181 ( vedi sotto per i dettagli).

L'errore "Off- by-one".

Avrete notato che PWM fast e PWM phase correct sembrano essere off- by-one l'uno  rispetto all'altro , dividendo per 256 invece che per 255 e aggiungendo uno in vari luoghi.

Supponiamo che il timer sia impostato in modalit√† PWM fast √® impostata a contare fino a un valore di OCRnA di 3. Il timer assumer√† i valori 012301230123 ... Si noti che ci sono 4 cicli di clock per ogni ciclo del timer. Cos√¨, la frequenza sar√† divisa per 4 e non 3. Il dutycycle sar√† un multiplo di 25%, dato che il segnale sara "alto" a  0, 1, 2 , 3 o 4 . Allo stesso modo, se il timer conta fino a 255 , ci saranno 256 cicli di clock in ogni ciclo del timer , e il dutycycle sar√† multiplo di 1 / 256 . Quindi, PWM fast divide per N +1 , dove N √® il valore del timer massimo (sia OCRnA o 255).

Ora consideriamo la modalit√† PWM phase correct con il timer conta fino ad un valore di OCRnA 3. I valori di timer sar√† 012321012321 ... Ci sono 6 cicli di clock per ogni ciclo del timer ( 012.321 ). Cos√¨ la frequenza sar√† diviso per 6. Il ciclo di lavoro sar√† un multiplo di 33%, dato che il segnale sar√† "alto"  per 0, 2 , 4 o 6 dei 6 cicli . Allo stesso modo, se il timer conta fino a 255 e ritorno verso il basso , ci saranno 510 cicli di clock in ogni ciclo del timer , e il dutycycle sar√† un multiplo di 1 / 255 . Quindi, PWM phase correct divide per 2N , dove N √® il valore del timer massimo.

La seconda differenza importante √® che il PWM fast tiene l'output ad alto per un ciclo pi√Ļ lungo del valore del registro di comparazione. La motivazione di ci√≤ √® che PWM fast  conta fino a 255 , il dutycycle pu√≤ essere 0-256 cicli, ma il registro pu√≤ contenere solo un valore da 0 a 255. Cosa succede al valore mancante ? La modalit√† PWM fast mantiene l' alta l'uscita per cicli di N +1 quando il registro di comparazione √® impostato su N cos√¨ un registro con valore di 255 √® 100 % del dutycycle, ma un registro con valore 0 √® non dutycycle  0 %, ma 1 / 256 del dutycycle. Questo a differenza del PWM phase correct, in cui un valore di registro di 255 √® 100 % del dutycycle e un valore di 0 √® un dutycycle dello 0%.

Timer e Arduino

Il Arduino supporta PWM su alcuni dei pin di uscita. Può non essere immediatamente evidente che c'è in timer che ne controlla l'utilizzo , ma la tabella seguente chiarirà la situazione. Essa fornisce, per ogni uscita del temporizzatore, il pin di uscita sul Arduino (cioè l'etichetta serigrafata sulla scheda) , il pin sul chip ATmega , e il nome e poco di porta di uscita . Per esempio Timer 0 OC0A uscita è collegata all'uscita Arduino pin 6 , utilizza chip pin 12 che è anche conosciuto come PD6 .

Timer di uscita Uscita su Arduino Pin sul chip Nome pin

OC0A                          6                          12                 PD6

OC0B                          5                          11                 PD5

OC1A                          9                          15                 PB1

OC1B                         10                          16                 PB2

OC2A                         11                          17                 PB3

OC2B                           3                            5                 PD3

Arduino inizializza il prescaler su tutti e tre i timer per dividere il clock per 64. Timer 0 è inizializzato in PWM fast, mentre i Timer 1 e Timer 2 vengono impostati come PWM phase correct .

Il Arduino utilizza il Timer 0 interno per i comandi Millis () e delay () , quindi sappiate che modificando la frequenza di questo timer quei comandi danno segni di pazzia. Usare le uscite PWM, invece,  √® sicuro se non si cambiamo le frequenze.

Con il comando analogWrite (pin , duty_cycle ) si imposta il pin appropriato PWM e  l'output appropriato nel registro di comparazione (Con il caso particolare di dutycycle del Timer 0 su 0). Il comndo digitalWrite () disattiva l'uscita PWM se viene chiamato su un pin timer.

Se si utilizza analogWrite (5, 0) si ottiene un dutycycle dello 0% , anche se il pin 5 del timer ( Timer 0) utilizza PWM fast. Come è possibile , quando un valore di PWM fast di 0 produce un ciclo di 1 / 256 , come spiegato sopra? La risposta è che analogWrite " bara" , ha un codice per i "casi speciali" per spegnere il pin quando si usa il Timer 0 con un dutycycle pari a 0. Come conseguenza , il ciclo che doveva essere 1 / 256 non è disponibile quando si utilizza analogWrite su Timer0 , e vi è un salto nel ciclo di lavoro reale tra i valori di 0 e 1.

Spero che questo piccolo tutorial messo insieme studianodo varii documenti reperibili sulla rete ed il datasheet dell'atmega 328, sia utile a tutti voi così come è stato utile per mè.

trovate il documento originale su cui è basato questo tutorial all'indirizzo: http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html

Ciao

Brainbooster

 

Gioblu Robotics ¬© 2010 - 2012 · Sitemap · privacy

gioscarab@gmail.com

Gioblu BOTServer è online dal 10 Aprile 2010 - 319.232 Visite - 1.027.175 Pagine visualizzate - 182.309 Visitatori unici - 536 utenti attivi