Está en la página 1de 8

PWM en Arduino

http://arduino.cc/es/Tutorial/SecretsOfArduinoPWM
La modulación por ancho de pulso (PWM) puede ser utilizada en el Arduino de diferentes maneras, Este
artículo explica tanto las técnicas simples de PWM como el como usar los registros de PWM
directamente para un mayor control sobre el ciclo de trabajo (duty cycle) y la frecuencia. Este artículo se
centra en los modelos Arduino Diecimila y Duemilanove, los cuales utilizan el ATmega168 y
ATmega328.

Si no estas familiarizado con la Modulación de Ancho de Pulso, échale un vistazo al tutorial. Brevemente,
una señal PWM es ona honda digital cuadrada, donde la frecuencia es constante, pero la fracción de
tiempo en que la señal está encendida (el ciclo de trabajo) puede variar entre el 0 y el 100%..

Ejemplos de PWM
PWM tiene diferentes usos:

 Atenuación de un LED.
 Disponer de una salida analógica; si la salida digital está filtrada,
esto proveerá de un voltaje entre el 0% y el 100%.
 Generar señales de audio.
 Proveer de un control de velocidad variable para motores.
 Generar una señal modulada, por ejemplo para utilizar un LED infrarojo para control remoto.

Modulación de Ancho de Pulso simple con analogWrite

El lenguaje de programación de Arduino hace que el PWM sea fácil de usar; simplemente llama a
analogWrite(pin, dutyCycle), donde dutyCycle es un valor entre 0 y 255, y pin es uno de los PWM pins
(3, 5, 6, 9, 10, or 11). La función analogWrite ofrece un interface simple al hardware PWM, pero no
ofrece ningún control sobre la frecuencia. ( Notese que a pesar del nombre de la función, la señal de
salida es digital, a menudo haciendo referencia a una onda cuadrada).

1
Probablemente el 99% de los lectores pueden detenerse aquí y utilizar solamente analogWrite, pero hay
otras opciones que ofrecen una mayor flexibilidad.

Bit-banging (Golpes de pulso) con PWM


Puedes "manualmente" implementar PWM en cualquier pin encendiendo y apagando repetidamente el pin
en los tiempos deseados. Ejem.

void setup()
{
pinMode(13, OUTPUT);
}

void loop()
{
digitalWrite(13, HIGH);
delayMicroseconds(100); // Aproximadamente 10% de ciclo de trabajo a 1KHz
digitalWrite(13, LOW);
delayMicroseconds(1000 - 100); // Aproximadamente 90% de ciclo de trabajo restante
apagado
}

Esta técnica tiene la ventaja de poder ser utilizada en cualquier pin de salida digital, tienes el control
completo del ciclo de trabajo y la frecuencia. La mayor desventaja es que cualquier interrupción afectará
a la cuenta de tiempo, lo cual puede causar fluctuaciones considerables a menos que desabilites las
interrupciones. La segunda desventaja es que no puedes tener la salida trabajando mientras el procesador
hace alguna otra cosa. Finalmente, es dificil determinar las constantes para un ciclo de trabajo y
frecuencia en particular a menos que cuentes cuidadosamente los ciclos, o modifiques los valores
mientras haces la medición con un osciloscopio.

Un ejemplo más elaborado de para hacer PWM en todos los pins se puede encontrar aqui.

Usando directamente los registros de PWM del ATmega


El chip ATmega168P/328P tiene tres timers para PWM, controlando 6 salidas PWM. Manipulando
directamente los registros del timer del chip, puedes obtener un mayor control que el que proporciona la
función analogWrite.

La ficha del AVR ATmega328P proporciona una descripción detallada de los timers, pero la ficha puede
ser dificil de comprender, debido a los muchos y diferentes modos de control y salida de los timers.

A continuación encontrarás unas palabras más ordenadas acerca de la relacción entre el lenguaje de
Arduino y la ficha.

Los timers del Atmega 168/328.

El ATmega328P tiene tres timers conocidos como Timer 0, Timer 1, and Timer 2. Cada uno de ellos
posee dos registros de salida comparados que controlan el ancho del pulso PWM para las dos salidas de

2
los timers: cuando el timer alcanza el valor del registro comparado la correspondiente salida es
conmutada. Las dos salidas de cada timer tienen normalmente la misma frecuencia, pero pueden tener
diferentes ciclos de trabajo (dependiendo del respectivo registro de salida comparado).

Cada uno de los timers tiene un Predivisor (prescaler) que genera el tempodizador dividiendo el reloj del
sistema por un factor como 1, 8, 64, 256 o 1024. El Arduino tiene un reloj de sistema a 16MHz y la
frecuencia del temporizador será el reloj de sistema dividido por el factor del Predivisor. Notese que el
Timer 2 posee un conjunto diferente de valores para el predivisor con respecto a los otros timers.

Los timers son complicados por sus diferentes modos. Los principales modos son "Fast PWM" y "Phase-
correct PWM", los cuales se describen más adelante. Un timer puede trabajar de 0 a 255, o de 0 a un valor
fijo. (El Timer 1 de 16-bits tiene modos adicionales que soportan valores de timer hasta los 16 bits).
Cualquier salida puede además ser invertida.

Los timers tambiém pueden generar interrupciopnes en desbordamiento (overflow) y/o coincidiendo con
alguno de los registros de salida comparados, pero esto está más allá de lo que cubre este artículo.

Registros de Timers

Muchos registros son utilizados para controlar cada timer. el Controlador de Registros del
Timer/Contador TCCRnA y TCCRnB mantiene el control de los bits principales del timer. (Notese que
TCCRnA y TCRnB no corresponden a las salidas A y B). Estos registros mantienen varios grupos de bits:

 Waveform Generation Mode bits (WGM): Estos controlan el timer de modo general.
(Estos bits se dividen entre TCCRnA y TCCRnB.)
 Clock Select bits (CS): Controla el reloj predivisor
 Compare Match Output A Mode bits (COMnA): Habilita/deshabilita/invierte la salida A
 Compare Match Output B Mode bits (COMnB): Habilita/deshabilita/invierte la salida B

Los Registros de Salida Comparada OCRnA y OCRnB ajustan los niveles en los que las salidas A y B
serán afectadas. Cuando el valor del timer coincida con el valor del registro, la correspondiente salida será
modificada como se especifique por el modo.

Los bits son ligeramente diferentes para cada timer, así que consulta la ficha para más detalles. Timer 1 es
un timer de 16-bits y tiene modos adicionales. El Timer 2 posee diferentres valores de predivisor.

PWM rápido (Fast PWM)

En el modo de PWM simple, el timer cuenta repetidamente desde 0 a 255. La salida se enciende cuando
el timer está en 0, y se apaga cuando el timer coincide con el registro de salida comparado. A mayor valor
en el registro de salida comparado, el ciclo de trabajo será mayor. Este modo es conocido como modo
rápido de PWM.

El siguiente diagrama muestra las salidas para dos valores particulares de OCRnA y OCRnB. Notese que
ambas salidas tienen la misma frecuencia, coincidiendo con la frecuencia de un ciclo completo del timer.

3
Modo PWM rápido (Fast PWM Mode)

El siguiente fragmento de código configura el PWM rápido en los pines 3 y 11 (Timer 2). Para resumir el
registro de configuración, poniendo los bits del Modo de generación de Ondas (WGM - waveform
generation mode) a 011 selecciona PWM rápido. Poniendo los bits COM2A y COM2B a 10 asigna PWM
no-invertido (non-inverted PWM) para las salidas A y B. Poniendo el CS a 100 ajusta el predivisor a
dividir el reloj por 64. (Como los bits son diferentes para los diferentes timers, consulta la ficha para ver
los valores correctos). Los registros comparados de salida son arbritariamente ajustados a 180 y 50 para
controlar el ciclo de trabajo del PWM de las salidas A y B. (Por supuesto puedes modificar directamente
los registros en vez de utilizar pinMode, pero necesitas configurar los pins a OUTPUT).

pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(CS22);
OCR2A = 180;
OCR2B = 50;

En el Arduino Duemilanove, estos valores produce:

 Frecuencia salida A: 16 MHz / 64 / 256 = 976.5625Hz


 Duty cycle salida A: (180+1) / 256 = 70.7%
 Frecuencia salida B: 16 MHz / 64 / 256 = 976.5625Hz
 Duty cycle salida B: (50+1) / 256 = 19.9%

La frecuencia de salida son los de 16MHz de la frecuencia del reloj de sistema, dividido por el valor del
predivisor (64), dividido por los 256 ciclos que necesita el timer para dar la vuelta completa. Notese que
el PWM rápido (fast PWM) mantiene la salida levantada un ciclo más que el valor del registro
comparado.

PWM de Corrección de fase (Phase-Correct PWM)

El segundo modo es llamaddo PWM de Corrección de fase (Phase-Correct PWM). En este modo, el timer
cuenta de 0 a 255 y cuenta hacia abajo de nuevo hasta 0. La salida se apaga cuando el timer alcanza el
valor del registro comparado cuando cuenta hacia arriba y se enciende cuando se alcanza mientras cuenta
hacia abajo. El resultado es una salida más simétrica. La frecuenccia de salida será aproximadamente la
mitad de el valor xxquexx para el modo PWM rápido, por que el timer corre en ambos sentidos arriba y
abajo.

Ejemplo PWM de Corrección de fase

El siguiente fragmento de código configura el PWM de corrección de fase en los pines 3 y 11 (Timer 2).
Los bits del modo de generación de ondas WGW estan configurados a 001 para el PWM de corrección de
fase. Los otros bits son iguales que para el modo de PWM rápido.

pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);

4
TCCR2B = _BV(CS22);
OCR2A = 180;
OCR2B = 50;

En el Arduino Duemilanove, estos valores producen:

 Frecuencia salida A: 16 MHz / 64 / 255 / 2 = 490.196Hz


 Duty cycle salida A: 180 / 255 = 70.6%
 Frecuencia salida B: 16 MHz / 64 / 255 / 2 = 490.196Hz
 Duty cycle salida B: 50 / 255 = 19.6%

El PWM de corrección de fase divide la frecuencia por dos, comparado con el modo PWM rápido (fast
PWM), porque el timer va hacia arriba y hacia a abajo. Sorprendentemente, la frecuencia es dividida por
255 en vez de por 256, y los cálculos del el ciclo de trabajo no añaden uno como para el PWM rápido.
Ver la explicación más adelante en "Off-by-one".

Variando el límite superior del timer: PWM rápido

Ambos modos, PWM rápido y PWM de corrección de fase, tienen un modo adicional que otorga el
control sobre la frecuencia de salida. En este modo, el timer cuenta desde 0 hasta OCRA (El valor del
registro de salida comparado A), en vez de de 0 a 255. Esto da mucho más control sobre la frecuencia de
salida y los modos previos. (Para un mayor control de la frecuencia, utiliza el Timer 1 de 16-bits).

Notese que en este modo solo la salida B puede ser utilizada para PWM; OCRA no puede ser utilizada
como máximo valor y valor de comparación de PWM. Sin embargo, hay un modo de Casos-Especiales
"Conmutar OCnA en coincidencia comparada" esto conmutará la salida A al final del ciclo de trabajo,
generando un 50% fijo de ciclo de trabajo y la mitad de la frecuencia en este caso. Los ejemplos utilizarán
este modo.

En el siguiente diagrama, el timer se resetea cuando coincide con OCRnA, produciendo una frecuencia de
salida más rápida para OCnB que en diagramas anteriores. Notese como OCnA conmuta cada vez que el
timer se resetea.

Modo PWM rápido (Fast PWM) con límite OCRA

El siguiente fragmento de código configura el PWM rápido en los pines 3 y 11 (Timer 2). Utilizando
OCR2A como el valor superior del timer. Los bits del modo de generación de onda WGW se cambian a
111 para el PWM rápido con el OCRA controlando el límite superior. El límite superior del OCR2A es
puesto arbritariamente a 180, y el registro de comparación OCR2B es ajustado arbritariamente a 50. El
modo OCR2A está configuado para "Conmutar en coincidencia comparada" cambiando los bits del
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;

5
En el Arduino Duemilanove, estos valores producen:

 Frecuencia salida A: 16 MHz / 64 / (180+1) / 2 = 690.6Hz


 Duty cycle salida A: 50%
 Frecuencia salida B: 16 MHz / 64 / (180+1) = 1381.2Hz
 Duty cycle salida B: (50+1) / (180+1) = 28.2%

Note que en este ejemplo, el timer va de 0 a 180, que tarda 181 ciclos de reloj, entonces la frecuencia de
salida es dividida por 181. La salida A tiene la mitad de la frecuencia que la salida B por que la
conmutación en modo de Comparación de Coincidencia (Compare Match mode) conmuta la salida A por
cada ciclo completo del timer.

Variando el límite superior: PWM corrección de fase (phase-correct PWM)

De manera similar, el timer puede ser configurado en modo de corrección de fase para resetear cuando
alcance el OCRnA.

PWM corrección de fase con límite OCRA

El siguiente fragmento de código configura PWM corrección de fase en los pines 3 y 11 (Timer 2),
utilizando el OCR2A como el valor superior del timmer. Los bits del modo de generación de onda WGW
son ajustados a 101 para el PWM de corrección de fase con el OCRA controlando el límite superior. El
límite superior del OCR2A es arbitrariamente ajustado a 180, y el registro comparado OCR2B se ajusta
arbritariamente a 50. El modo OCR2A está configuado para "Conmutar en coincidencia comparada"
cambiando los bits del 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;

En el Arduino Duemilanove, estos valores producen:

 Frecuencia salida A: 16 MHz / 64 / 180 / 2 / 2 = 347.2Hz


 Duty cycle salida A: 50%
 Frecuencia salida B: 16 MHz / 64 / 180 / 2 = 694.4Hz
 Duty cycle salida B: 50 / 180 = 27.8%

Observese que en este ejemplo, el timer va de 0 a 180 y vuelve hacia el 0, lo que requiere 360 ciclos de
reloj. Entonces, todo es dividido por 180 o 360, al contrario que en el caso del PWM rápido, en el que
todo se divide por 181; ver más adelante para más detalles.

Desplazado-en-uno (Off-by-one)

Puedes haber observado que el PWM rápido (fast PWM) y el PWM de corrección de fase (phase-correct
PWM) parecen desfasados en 1 uno con respecto al otro, dividiendo por 256 contra 255 y añadien do 1 en
6
varios lugares. La documentación es un poco oscura en esto, por lo que intentaré explicarlo con algo más
de detalle.

Imagina que el timer está configurado en modo PWM rapido y está ajustado para contar hasta un valor de
OCRnA de 3. El timer tendrá los valores 012301230123... observa que hay cuatro ciclos de reloj en cada
ciclo de timer. Entonces la frecuencia será dividida por 4, no por 3. El ciclo de trabajo será un múltiplo de
25%, desde que la salida esté levantada para 0, 1, 2, 3 o 4 de los cuatro. De la misma manera, ssi el timer
cuenta hasta 255, existirán 256 ciclos de reloj en cada ciclo de timer, y el ciclo de trabajo será un múltiplo
de 1/256. Para resumir PWM rápido divide por N+1 donde N en el máximo valor del timer (sea OCRnA o
255).

Ahora considera el modo PWM de corrección de fase contando hasta un valor de OCRnA de 3. Los
valores del timer seran 012321012321... aquí hay 6 ciclos de reloj en cada ciclo de timer (012321).
Entonces la frecuencia será dividida por 6. El ciclo de trabajo será un múltiplo de 33%, desde que la
salida puede estar levantada para 0, 2, 4 o 6 de los ciclos. De la misma manera, si el timer cuenta hasta
255 y vuelve hacia abajo, habrá 510 ciclos de reloj en cada ciclo de timer, y el ciclo de trabajo será un
múltiplo de 1/255. Para resumir el PWM de corrección de fase divide por 2N, donde N es el valor
máximo del timer.

La segunda diferencia importante en la temporización es que el PWM rapido mantiene la salida en alto
para un ciclo más que el valor del registro de salida comparado. El motivo de esto es que para el PWM
rápido contando hasta 255, el ciclo de trabajo puede ser de 0 a 256, pero el valor del registro de salida
comparado solo puede ser de 0 a 255. ¿que pasa con el valor perdido? El PWM mantiene la salida en alto
para N+1 ciclos cuando el registro de salida comparado es N por lo que el valor del registro de salida
comparado de 255 es el 100% del ciclo de trabajo, pero el valor del registro de salida comparado de 0 no
es el 0% del ciclo de trabajo sino un 1/256 del ciclo de trabajo. Esto es diferente del PWM de corrección
de fase, donde el valor de un registro de 255 es 100% del ciclo de trabajo y un valor de 0 es un 0% del
ciclo de trabajo.

Timers y Arduino

Arduino soporta PWM en varios de sus pins de salida. No es obvio de manera inmediata que timer
controla cada salida, pero la siguiente tabla puede aclarar la situación. Esta ofrece a cada salida del timer
a un pin de salida en el Arduino (las serigrafiados en la placa), el pin en el chip Atmega, y el nombre y bit
del puerto de salida. Por ejemplo la salida del Timer 0 OC0A está conectada al Arduino en el pin 6;
utiliza el pin del chip 12 que es también conocido como PD6.

Timer Salida Arduino output Chip pin Pin name


OC0A 6 12 PD6
OC0B 5 11 PD5
OC1A 9 15 PB1
OC1B 10 16 PB2
OC2A 11 17 PB3
OC2B 3 5 PD3
El Arduino realiza alguna inicialización de los timers. El Arduino inicializa el predivisor en los tres timers
para dividir el reloj por 64. El Timer 0 es inicializado en modo PWM rápido (fast PWM), mientras que el

7
Timer 1 y el Timer 2 son inicializados en el modo PWM de corrección de fase (Phase Correct PWM).
Mira el archivo de código de Arduino wiring.c para más detalles.

El Arduino utiliza el timer 0 internamente para las funciones millis() y delay(), estate atento ya que
cambiar la frecuencia de este timer causará que estas funciones sean erroneas. Utilizar las salidas de
PWM es seguro si no cambias la frecuencia, pienso.

La función analogWrite(pin, duty_cycle) asigna el pin apropiado al PWM y configura el registro


comparado de salida apropiado al ciclo de trabajo (duty cycle) (con el caso especial del ciclo de trabajo 0
en el Timer 0). La función digitalWrite() apaga la salida de PWM si es llamada en un pin del timer. El
código relevante esta en wiring_analog.c y wiring_digital.c.

Si tu utilizas analogWrite(5, 0) obtendrás un ciclo de trabajo de 0%, aunque el timer del pin 5 (Timer 0)
utiliza PWM rápido. Como puede ser esto, cuando el valor 0 en el PWM rápido produce un ciclo de
trabajo de 1/256 como se explicó más arriba? La respuesta es que analogWrite "Hace trampas"; este tiene
un código para-casos-especiales para apagar explícitamente el pin cuando es llamado en el Timer 0 con
un ciclo de trabajo de 0. Como consecuencia, el ciclo de trabajo de 1/256 no está disponible cuando se
utiliza analogWrite en el Timer 0, y habrá un salto en el ciclo de trabajo actual entre los valores 0 y 1.

Otros modelos de Arduino utilizan un procesador AVR diferente con timers similares. El Arduino Mega
utiliza el ATmega1280 (Ficha), el cual tiene cuatro timers de 16-bit con 3 salidas cada uno y dos timers
de 8-bits con dos salidas cada uno. Solo 14 de las salidas PWM están soportadas por la librería de Wiring
de Arduino, no obstante algunos de los modelos antiguos de Arduino utilizan el ATmega8 (Ficha), el cual
tiene 3 timers pero solo tres salidas PWM: Timer 0 no tiene PWM, Timer 1 es de 16 bits y tiene dos
salidas PWM, y el Timer 2 es de 8 bits y tiene una salida PWM.

Problemática

Puede ser un poco intrincado poner a funcionar las salidas PWM. Algunos trucos:

 Necesitas tanto el pin de salida habilitado como habilitar el modo de PWM en el pin
para pode dar una salida.
Ejem. Necesitas hacer un pinMode() y configurar los bits del COM
 Los diferentes timers utilizan el control de bits y predivisor por separado;
Revisa la documentación para el timer apropiado.
 Algunas de las conbinaciones de bits que esperas que funcionen están reservadas,
lo cual significa que si intentas utilizarlos, no funcinarán.
Por ejemplo, conmutar el modo no funcionará con un PWM rápido a 255, o con salida B.
 Asegurate que los bits están configurados según piensas. Las operaciones con Bit pueden ser
intrincadas,
así que échale un ojo a los valores de registro con el formato binario (BIN) y asegurate que son los
que esperas.
 Asegurate de que estás utilizando los pines de salida correctos. Mira la tabla anterior.
 Probablemente querrás poner un condensador de desacople para evitar picos en tu salida.

Un osciloscopio es muy útil para depurar PWM si tienes acceso a uno. Si no tienes uno te recomiendo
utilizar tu tarjeta de sonido con un programa como xoscope.
8

También podría gustarte