PWM: emulando pines analógicos con tu placa Arduino

PWM señales

Con los pines digitales y analógicos, que puedes usar en tu placa Arduino, puedes recibir o enviar señales eléctricas para controlar u obtener datos de tus proyectos electrónicos. Además, existen otras señales muy interesantes en este tipo de placas, y esas son las PWM, que pueden emular a una señal analógica sin ser realmente analógica. Es decir, son pines digitales que pueden actuar de forma similar (que no igual) a una señal analógica.

Este tipo de señales son muy prácticas para cuando no solo se quiere usar señales HIGH y LOW digitales, es decir, 1 o 0, ON y OFF, sino que se quiere ir más allá y describir señales algo más complejas. Por ejemplo, se puede modular así la velocidad de un motor DC, o la intensidad lumínica de una luz, para un solenoide, etc.

Sistema analógico vs digital

Señal analógica vs digital

Los circuitos electrónicos se pueden dividir en dos grandes familias o categorías: digitales y analógicos. Cuando se habla de una electrónica digital se están usando magnitudes con valores discretos, es decir, un sistema binario representado por señales eléctricas de un voltaje bajo o alto para interpretar el estado de esos bits que se manejan. En cambio, cuando se trata de un circuito analógico se están empleando magnitudes con valores continuos.

Dentro de los sistemas digitales se pueden encontrar a su vez los de tipo combinacional y los de tipo secuencial. Es decir, los primeros son aquellos en el que la salida del sistema sólo depende del estado de las entradas. En cambio, en los secuenciales se incluyen elementos de memorias, y la salida dependerá del estado actual de las entradas y del estado anterior almacenado.

En el caso de los analógicos no hay estos dos grandes grupos o variantes, ya que aquí son señales continuas que siempre dependerán de la señal actual del sistema. Por ejemplo, en un altavoz, la señal que se le suministra dependerá del sonido que se quiera reproducir. Igual con un micrófono, que generará una señal analógica en función del sonido que esté recibiendo. Seguramente también lo hayas visto con otros muchos sensores que hemos descrito en este blog y que actúan con señales analógicas (y por tanto, había que crear una fórmula para que luego se pudieran calcular o acondicionar los valores en los sketchs de Arduino IDE)…

Estas características de uno y otro hace que unos tengan sus ventajas e inconvenientes, como suele ser habitual en casi todo. Por ejemplo, los digitales suelen ser más baratos, más rápidos, son más fáciles de desarrollar, se puede almacenar la información más fácilmente, tienen mayor exactitud, se pueden programar, no son tan vulnerables a los efectos del ruido, etc. Pero también es cierto que con los analógicos se puede operar con señales más complejas.

Por ejemplo, un sensor de efecto Hall de tipo digital solo puede captar la presencia o no presencia de un campo magnético cercano. En cambio, un sensor de efecto Hall analógico puede hacer eso y también determinar la densidad de dicho campo magnético gracias a una señal analógica que genera a su salida. Sabiendo interpretar bien esa señal de mayor o menor voltaje, se puede saber esa magnitud fácilmente. Otros ejemplos los tienes en multitud de magnitudes de la naturaleza que puedes medir de forma cuantitativamente con un sistema analógico, como la temperatura, el tiempo, la presión, la distancia, el sonido, etc.

Señal analógica vs digital

Dicho esto, una señal analógica será un voltaje o corriente eléctrica que varía con respecto del tiempo y de forma continua. Si se representa en una gráfica, la señal analógica sería una onda senoidal de una sola frecuencia.

En cuanto a la señal digital, es un voltaje que varía de forma escalonada con respecto al tiempo. Es decir, si se representa en una gráfica, será una señal escalonada que no varía de forma continua, sino que cambia por pasos o en incrementos discretos.

Debes saber que hay circuitos para pasar de una señal analógica a otra digital o viceversa. Estos conversores se conocen como DAC (Digital-to-Analog Converter) y ADC (Analog-to-Digital Converter). Y son muy frecuentes en multitud de dispositivos que usamos en la actualidad, como la TV, los ordenadores, etc. Con ellos se puede convertir las señales digitales que usan estos equipos a nivel electrónico para trabajar con otros periféricos o partes que funcionan en analógico.

Por ejemplo, un altavoz o micrófono con señales analógicas que funciona con una tarjeta de sonido, o las tarjetas gráficas digitales que tenían el famoso chip RAMDAC para los puertos de monitores analógicos… En Arduino también se usan este tipo de conversores para múltiples proyectos, como veremos…

¿Qué es PWM?

duty cycle grafica

Aunque PWM (Pulse-Width Modulation), o modulación por ancho de pulsos, tiene una base digital, la forma de su señal se asemeja a una señal analógica algo “cuadrada”. Permite mediante pulsos digitales ir variando la señal para emular un sistema analógico como ya he comentado anteriormente. De hecho, si te fijas en el nombre, ya te da pistas de lo que hace, mediante el ancho de los pulsos digitales.

Esto es beneficioso para Arduino ya que hay muchos automatismos o componentes electrónicos que puedes agregar a tus proyectos y que no son capaces de proporcionar una auténtica señal analógica, sino que se valen de este PWM para operar. Tampoco pueden usar una señal analógica discretizada, es decir, que vaya a saltos de tensión para asemejarse a una digital. Lo que sí pueden es usar una salida digital -Vcc o Vcc de tipo digital para generar esta señal tan peculiar…

Por tanto, PWM es una especie de “truco” con el que Arduino y otros sistemas pueden interoperar con este tipo de señales que no llegan a ser del todo analógicas ni tampoco digitales convencionales. Para que sea posible, mantienen una salida digital activa durante un tiempo específico o apagada, según interese en cada momento. Esto se aleja de lo que sería una señal de clock o reloj digital o de un código binario al uso, cuyos pulsos tienen un ancho igual.

En tus proyectos con Arduino puedes comprobar este tipo de señales PWM en las que se mantiene una frecuencia constante de disparos de pulsos en el tiempo, pero se varía la anchura de estos pulsos. De hecho, se denomina Duty Cycle al tiempo que se mantiene encendida en alto una señal con respecto al total del ciclo. Por tanto, Duty Cycle se proporciona en %.

Recuerda que en un PWM no se trabaja como en una señal analógica, entre varios valores de tensión y se va fluctuando entre ellos. En el caso de PWM es una señal cuadrada al estilo digital y cuyo valor máximo es Vcc. Por ejemplo, si se trabaja con una alimentación 3V, se pueden dar pulsos de 3V o de 0V, pero no de 1V u otro valor intermedio como ocurriría en una analógica real. Lo que variaría en ese caso es el ancho del pulso, que lo podemos mantener un 30% en ese valor Vcc alto, o un 60% para darle más potencia, etc.

Pero cuidado, ya que si un dispositivo soporta un Vcc límite y se supera con PWM se puede dañar. Así que habría siempre que respetar los valores de los datasheets que aportan los fabricantes. Además, en algunos dispositivos como los motores DC, relés, electroimanes, etc., una retirada del voltaje tras un Duty Cycle puede suponer que las cargas inductivas puedan generar daños. Por eso se deben implementar las protecciones oportunas.

PWM en Arduino

Arduino bus I2C

Ahora que ya sabes cómo funciona, vamos a ver el caso concreto de PWM dentro del mundo Arduino…

PWM: pinout en Arduino

En las placas Arduino puedes encontrar varios pines que implementan PWM por hardware. Los puedes identificar en la propia PCB porque tienen un símbolo ~ (virgulilla) junto con la numeración del pin. Se podría también hacer por software en el código de Arduino, pero eso sobrecargaría de trabajo al microcontrolador, algo absurdo cuando lo puede hacer de forma nativa y por hardware…

  • Arduino UNO, Mini y Nano: tiene 6 salidas PWM de 8 bits en los pines 3, 5, 6, 9, 10 y 11, que tendrán esa ~ justo delante del número.
  • Arduino Mega: en esta placa más potente de Arduino tienes 15 salidas PWM de 8 bits. Están en los pines del 2 al 13 y del 44 al 46.
  • Arduino Due: en este caso se cuenta con 13 salidas PWM también de 8 bits. Están en los pines 2 al 13, mas otras dos salidas analógicas discretizadas por DAC con resolución de 12 bits.

Cuando se habla de una resolución de 8 bits o 12 bits, etc., en este tipo de salidas PWM, se está refiriendo al margen de maniobra que tienes. Con 8 bits se tiene 256 niveles entre los que puedes variar, y los 12 bits suben a 4096 niveles.

Control con Timers

Para el control de PWM por hardware, Arduino empleará los Timer para ello. Cada Timer presente puede servir a 2 o 3 salidas PWM. Un registro de comparación por cada salida complementa este sistema para que cuando el tiempo alcance el valor del registro se cambie el estado o valor de la salida para detner esos Duty Cycles. Aunque haya dos salidas controladas por el mismo Timer, ambas pueden tener distintos Duty Cycles, aunque comparten la misma frecuencia.

En el caso de los Timers asociados a cada pin PWM variará en función del tipo de placa Arduino que tengas:

  • Arduino UNO, Mini y Nano:
    • Timer0 – 5 y 6
    • Timer1 – 9 y 10
    • Timer2 – 3 y 11
  • Arduino Mega:
    • Timer0 – 4 y 13
    • Timer1 – 11 y 12
    • Timer2 – 9 y 10
    • Timer3 – 2, 3 y 5
    • Timer4 – 6, 7 y 8
    • Timer5 – 44, 45 y 46

El registro preescalado dividirá por un número entero el tiempo y el Timer hace el resto para el control de cada una de las salidas PWM asociadas. Si se modifica el valor del registro se puede alterar la frecuencia. Las frecuencias también serán diferentes según el Timer y la placa:

  • Arduino UNO, Mini y Nano:
    • Timer0: permite preescalados de 1, 8, 64, 256 y 1024. La frecuencia es de 62.5 Khz.
    • Timer1: con preescalados de 1, 8, 64, 256 y 1024. Con frecuencia de 31.25 Khz.
    • Timer2: igual a Timer1, solo que añade un preescalado también de 32 y 128 además de los anteriores.
  • Arduino Mega:
    • Timer0, 1, 2: iguales a los anteriores.
    • Timer3, 4, y 5: con frecuencia de 31.25 Khz y preescalados de 1, 8, 64, 256 y 1024.

Incompatibilidades y conflictos

El Timer asociado a las salidas no es solo para esa función, también es usado por otras. Por tanto, si están siendo  usados por otra función deberás elegir entre uno u otro, no se pueden estar usando ambos a la vez. Por ejemplo, estas son algunas de las incompatibilidades que te puedes encontrar en tus proyectos:

  • Biblioteca servo: cuando usas servomotores, se hace uso intensivo de Timers, por lo que podría generar comflictos. Concretamente usa el Timer1 para UNO, Nano y Mini, es decir, que no puedes usar los pines 9 y 10 mientras estés usando un sketch con esa biblioteca. En Mega va a depender de la cantidad de servos…
  • SPI: si se usa comunicación SPI en la placa Arduino, se está usando el pin 11 para la función MOSI. Por eso no se puede usar ese pin PWM.
  • Tone: esta función emplea el Timer2 para operaro. Por eso, si se usa, estás inutilizando los pines 3 y 11 (o 9 y 10 para Mega).

Prueba práctica con Arduino

esquema Arduino PWM con LED

Si quieres ver insitu cómo trabaja PWM en Arduino, lo mejor que puedes hacer es conectar las puntas de medición de un voltímetro o polímetro (en función para medir voltaje) entre el pin PWM que hayas elegido usar y el pin de tierra o GND de la placa Arduino. De ese modo, en la pantalla del aparato de medición podrás ver cómo va variando el voltaje con una salida que es digital gracias a este truco PWM.

Puedes sustituir el voltímetro/polímetro por un LED para ver cómo varía la intensidad de la luz, por un motor DC, o por cualquier otro elemento que se te antoje. Yo lo he simplificado en el esquema con Fritzing con un LED sin más, pero que sepas que puede representar igualmente a las puntas de un polímetro…

Si usas un LED, recuerda la resistencia en el cátodo y GND.

Para el código fuente para controlar el microcontrolador de la placa Arduino para que funcione todo, deberías insertar esto en Arduino IDE (en este caso he usado el pin PWM 6 de Arduino UNO):


const int analogOutPin = 6;
byte outputValue = 0;  
 
void setup()
{  
   Serial.begin(9600);        
   pinMode(ledPIN , OUTPUT); 
 
   bitSet(DDRB, 5);       // LED o voltímetro
   bitSet(PCICR, PCIE0);       
   bitSet(PCMSK0, PCINT3);     
}
 
void loop() 
{
   if (Serial.available()>0)  
   {
      if(outputValue >= '0' && outputValue <= '9')
      {
         outputValue = Serial.read();   // Leemos la opción
         outputValue -= '0';      // Restamos '0' para convertir a un número
         outputValue *= 25;      // Multiplicamos x25 para pasar a una escala 0 a 250
         analogWrite(ledPIN , outputValue);
      }
   }
}  
 
ISR(PCINT0_vect)
{
   if(bitRead(PINB, 3))
   { 
      bitSet(PORTB, 5);   // LED on 
   }
   else
   { 
      bitClear(PORTB, 5); // LED off  
   } 
} 
Te aconsejo que juegues con los valores y vayas viendo los resultados en la luz o voltímetro. El programa puede recibir valores de 0 a 9 para que puedas ver cómo varía todo. Para más información, te aconsejo el curso de Arduino que tenemos en descarga gratuita…

Sé el primero en comentar

Deja tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.