PWM, modulación por ancho de pulsos, es una poderosa técnica para controlar circuitos analógicos con sus salidas digitales. Con esta técnica puedes controlar fácilmente el brillo de los LEDS, o la velocidad de un motor.
En este tutorial aprenderás qué es la modulación por ancho de pulsos PWM, cómo puedes obtener la salida PWM de los pines digitales de la placa Arduino, y aprenderás a controlar el brillo de un LED manualmente usando un potenciómetro.
¿Qué es la modulación por ancho de pulsos PWM?
La modulación de ancho de pulsos PWM (PWM – Pulse Width Modulation) es un método usado para generar una señal analógica utilizando una fuente digital.
Una señal PWM consta de dos componentes principales que definen su comportamiento: un ciclo de trabajo y una frecuencia.
El ciclo de trabajo describe la cantidad de tiempo que la señal está en un estado alto (encendido) como un porcentaje del tiempo total que lleva completar un ciclo.
La frecuencia determina qué tan rápido la modulación por ancho de pulsos completa un ciclo (es decir, 1000 Hz sería 1000 ciclos por segundo) y, por lo tanto, qué tan rápido cambia entre los estados alto y bajo.
Al encender y apagar una señal digital a una velocidad lo suficientemente rápida, y con un cierto ciclo de trabajo, la salida parecerá comportarse como una señal de voltaje analógica constante al proporcionar energía a los dispositivos.
¿En dónde se usa la modulación por ancho de pulsos PWM?
Las señales de modulación por ancho de pulsos PWM se utilizan para una amplia variedad de aplicaciones de control.
Su uso principal es para controlar motores de CC, pero también se puede usar para controlar fuentes de iluminacion, válvulas, bombas, sistemas hidráulicos y otras partes mecánicas.
La frecuencia con la que se debe configurar la señal PWM dependerá de la aplicación y del tiempo de respuesta del sistema que se está alimentando.
A continuación, se presentan algunas aplicaciones y algunas frecuencias mínimas típicas de usadas en la modulación por ancho de pulsos:
- Elementos o sistemas de calefacción con tiempos de respuesta lentos: 10-100 Hz o más.
- Motores eléctricos de CC: 5-10 kHz o más.
- Fuentes de alimentación o amplificadores de audio: 20-200 kHz o superior.
- Control de iluminación de CC: 1-5 kHz o más.
¿Cómo se usa la modulación por ancho de pulsos PWM?
En la actualidad todos los microcontroladores modernos admiten salidas de modulación por ancho de pulsos, entre ellos, los usados por las placas Arduino.
En el caso de la placa Arduino UNO, los pines disponibles para el uso del PWM son los denominados digital output D3, D5, D6, D9, D10 y D11.
El control de la modulación de ancho de pulsos puede hacerse usando la función analogWrite o mediante el uso directo de los registros temporizadores del PWM.
Como se indicó anteriormente, uno de las aplicaciones más frecuentes en el uso de PWM es en el control de velocidad de motores. Para ello, a la salida del PWM se usan filtros de paso bajo (generalmente tipo RC) se usan para convertir la salida PWM a voltaje de CC.
El término ciclo de trabajo se refiere a la relación entre la cantidad de tiempo de encendido y el período del tren de pulsos. Está especificado en porcentaje. Por lo tanto, 10% se refiere a 10/100 y 90% se refiere a 90/100 en formato decimal.
La ecuación siguiente menciona la relación entre el voltaje de salida promedio y el ciclo de trabajo.
Salida de voltaje de CC = Voltaje en Estado Alto x Ciclo de trabajo
¿Cómo puedo controlar la modulación de ancho de pulsos PWM?
Mediante el uso de la función analogWrite, la placa Arduino puede hacer la modulación por ancho de pulsos (PWM). Es una manera cómoda y simple de controlarlo, pero no ofrece control sobre la frecuencia de trabajo.
La función analogWrite(pin, valor) se usa para emitir una señal PWM. El número de pin utilizado para la salida PWM es alguno de los pines mencionados antes, D3, D5, D6, D9, D10 y D11, validos en la mayoría de las placas Arduino.
Un número proporcional al ciclo de trabajo de la señal se enumera como valor. Cuando valor es igual a 0, la señal siempre está apagada. Cuando valor es igual a 255, la señal siempre está activada.
La frecuencia de la señal PWM en la mayoría de los pines esta prefijada, y es de aproximadamente 490 Hz. En la placa Arduino UNO y placas similares, los pines D5 y D6 tienen una frecuencia de aproximadamente 980 Hz. Los pines D3 y D11 en la placa Arduino Leonardo también funcionan a 980 Hz.
¿Cómo puedo controlar la modulación de ancho de pulsos PWM usando el temporizador?
A nivel hardware, la modulación por ancho de pulsos está controlada por los temporizadores incorporados en el microcontrolador de la placa Arduino.
El microcontrolador ATmega328P tiene tres temporizadores, conocidos como Timer 0, Timer 1 y Timer 2.
Cada temporizador tiene dos registros de comparación, y dos salidas que controlan el ancho PWM.
Cuando el conteo del temporizador alcanza el valor de registro de comparación (valor umbral o threshold), la salida correspondiente cambia de valor lógico, esto es, se alterna.
Las dos salidas para cada temporizador normalmente tendrán la misma frecuencia, pero pueden tener diferentes ciclos de trabajo (dependiendo del registro de comparación de salida respectivo).
El control de PWM por manipulación directa de los registros del timer es un tema avanzado de programación, ya que requiere conocer aspectos relativos a la frecuencia de reloj del microcontrolador, detección de eventos y servicio de interrupciones.
Esto por si solo es amplio material para otra publicación, por lo tanto, este tema se dejará para un tutorial posterior.
Ejemplo de uso en modulación por ancho de pulsos PWM
Veamos un ejemplo de aplicación práctica, que será modular el nivel de brillo de un LED. Para ello, usaremos lo siguiente:
- Placa Arduino UNO
- Resistencia de 4.7k Ohm
- Potenciómetro 10k Ohm
- LED
- Tabla de pruebas
- Cables de conexión
Usáremos control PWM mediante la función analogWrite. El LED tendrá su ánodo conectado mediante una resistencia de 4.7kOhm al pin D9 y su cátodo a GND.
El programa realiza las siguientes actividades:
- Inicializa el puerto serie y el pin PWM.
- Lee el valor del potenciómetro usando el ADC.
- Ajusta la lectura del ADC a valores que maneja el PWM.
- Escribe el valor ajustado del ADC en el PWM mediante analogWrite.
- Envía el valor ajustado del ADC al puerto serie.
La actividad central del programa es leer al vuelo el nivel de voltaje en el cursor del potenciómetro, mediante el convertidor ADC en el pin A0. Esta lectura estará en el rango de 0 a 1023.
Dado que el PWM solo acepta valores entre 0 y 255 es necesario cambiar la escala de la lectura del ADC. Para ello, se usa la siguiente función:
map(valor, desde_valor_bajo, desde_valor_alto, hasta_valor_bajo, hasta_valor_alto)
Esta función tiene cinco parámetros, el primero es la variable en la que se almacena el valor analógico. Los otros son 0, 1023, 0 y 255 respectivamente. Estos últimos 4 valores corresponden con los rangos de origen y destino que se desean adaptar o mapear.
De esta forma, la función permite que el valor de una entrada analógica que varía de 0 a 1023 se pueda ajustar a una salida que vaya de 0 a 255, lo cual es el rango ideal para controlar una señal PWM.
El efecto de cambio de brillo del LED viene dado por no por el voltaje aplicado, que será constante, 5V, sino por el tiempo que ese voltaje es aplicado al LED.
El LED estará siendo alimentado por pulsos, y de acuerdo al ancho de estos pulsos variará el brillo. Si el ciclo de trabajo es bajo, el brillo será bajo y tenue (Dim). Si el ciclo de trabajo es alto, el brillo será intenso (Bright).
Ejemplo de modulación por ancho de pulsos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/* * Ejemplo de modulación por ancho de pulsos * * https://www.proyectoarduino.com * */ const int led_pwm = 2 ; // Usamos salida PWM en pin D2 int adc_nuevo = 0 ; // Usamos entrada ADC en pin A0 int adc_viejo = 0 ; // Guardamos la última lectura del ADC void setup() { // Inicializamos el puerto serie Serial.begin(9600); // Configuramos pwm como salida pinMode(led_pwm, OUTPUT) ; } void loop() { // Leemos el valor del ADC en el pin A0 adc_nuevo = analogRead(0) ; // Ajustamos el valor leido en A0 para adaptarlo al rengo // del PWM. Se adapta la escala de 0-1023 a 0-255 adc_nuevo = map(adc_nuevo, 0, 1023, 0, 255); if (adc_nuevo != adc_viejo) { // Actualiza la lectura del ADC adc_viejo = adc_nuevo; // Envia el valor actual al puerto serie Serial.println(adc_nuevo); // Envia el valor adaptado al PWM analogWrite(led_pwm, adc_nuevo); } } |