Micropython: Uso del PWM en ESP8266

La técnica de PWM (Pulse Width Modulation o Modulación por ancho de Pulso) es ampliamente utilizada con distintos microcontroladores para varias aplicaciones, como por ejemplo, simular una salida analógica a partir de un pin digital para controlar el brillo de luces o la velocidad de un motor de corriente continua. En este artículo veremos como usar un PWM en el ESP8266 programándolo con MicroPython.

Tal vez te interesen estos artículos anteriores relacionados con este tema…

La forma de generar las señales PWM varía de un microcontrolador a otro. Por ejemplo, en algunos como el ESP32 o el AT mega 328, esto se logra gracias a un módulo implementado en hardware. En otros, como el ESP8266 que no tienen ese módulo, las señales se producen recurriendo al software. En este artículo veremos un ejemplo basado en ESP8266 así que revisaremos algunos detalles de este SoC que pueden llegar a cambiar si se utiliza un procesador diferente.

En Micropython, para definir una salida con funciones de PWM, debemos emplear la clase PWM que se incluye en el módulo machine y que debemos importar al comienzo de nuestro programa:

from machine import PWM

Lo mas probable es que también usemos la clase Pin, así que podemos incluir las dos juntas:

from machine import Pin, PWM

Para crear un objeto PWM (o instanciarlo como se dice) deberemos llamar al constructor con el mismo nombre con los siguientes parámetros:

nombre = PWM (pin, frecuencia, duty)

Donde:

nombre: Identificador del objeto PWM

pin: Número físico del pin donde funcionará el PWM.

frecuencia: Frecuencia de funcionamiento del PWM, entre 1 y 1000 Hz.

duty: ciclo de trabajo del PWM. Puede variar desde 0 (OFF) a 1023 (todo ON)

Importante

En el caso del ESP8266, los pines 0, 2, 4, 5, 12, 13, 14 y 15 pueden comportarse como PWM

Ejemplos:

Definición de un pin de salida y luego configuración del PWM en ese pin. Frecuencia de 1KHz y ciclo de trabajo del 50% (512).

Led = Pin (5, Pin.OUT, value=0)
LedPWM = PWM (Led, freq=1000, duty=512)

Definición directa del PWM y el pin, con los mismos valores.

LedPWM = PWM (Pin(5), freq=1000, duty=512)

Un objeto PWM creado cuenta con los siguientes métodos:

freq (frecuencia)

Establece la frecuencia de los PWM. Si se modifica un PWM, se cambia la frecuencia de todos los PWM que se hayan definido.

Ejemplo:

LedPWM.freq (500)

duty (ciclo_de_trabajo)

Establece el ciclo de trabajo de un PWM (entre 0 y 1023)

Ejemplo:

LedPWM.duty (100)

init (frecuencia, duty)

Reinicializa el PWM con los valores que se suministren.

Ejemplo:

LedPWM = PWM (Pin(5), freq=1000, duty=512)  #PWM en el pin 5
LedPWM.init (freq=500, duty=100)  #Cambia los valores

deinit ()

Desconecta un PWM del pin donde se había definido, liberando ese pin para otra aplicación

En el siguiente ejemplo se configura un PWM, luego se lo desconecta y se controla el pin con el método on(). Si no se realiza el deinit antes, no se puede encender el led.

Led = Pin (5, Pin.OUT)
LedPWM = PWM (Led, freq=1000, duty=512)  #PWM en el pin 5

LedPWM.deinit ()
Led.on ()

Vamos a aplicar lo que hemos visto hasta ahora en un sencillo ejemplo que controla el brillo de un led conectándolo a un pin configurado como PWM a través de dos teclas.

El circuito es el que se ve en las imágenes siguientes. Tiene las dos teclas que conectan las entradas D2 (GPIO4) y D3 (GPIO0) a GND al ser pulsadas, ya que (como veremos mas adelante) las mismas tienen activadas las resistencias internas de PULL_UP y un led con su resistencia limitadora de corriente en el pin D1 (GPIO5).

Circuito de ejemplo
Esquemático del ejemplo
Pines del Nodemcu (adaptado de www.theengineeringprojects.com)

El programa, escrito usando Thonny puede verse en el siguiente listado. En las primeras líneas importamos los módulos y clases que vamos a necesitar. La variable Brillo se inicializa a cero, será usada luego para contener el valor del ciclo de trabajo del PWM.

A continuación se define la salida LedPWM en el pin 5 (D1) y las dos entradas Boton_UP y Boton_DN en D3 y D2 respectivamente, con las resistencias de PULL_UP activadas.

Luego tenemos la definición de dos funciones que implementan un “debounce” o eliminación de rebotes elemental en las entradas. Lo que hacen es, cuando detectan que la entrada se activa (nivel bajo) hacer un retado de 0.01 segundos (10 milisegundos) y luego volver a comprobar el valor. Si la entrada sigue activa, se toma la pulsación de la tecla como válida.

Luego entramos en un bucle infinito en el que se actualiza el PWM con la variable Brilloy se revisan las dos teclas. Si se pulsa la tecla “DN” y Brillo es mayor que cero, se la decrementa. Si se pulsa la tecla “UP” y Brillo es menor a 1024 (el valor máximo del ciclo de trabajo del PWM), se la incrementa.

from machine import Pin, PWM
from time import sleep

Brillo = 0  #Brillo del LED

LedPWM = PWM (Pin(5), freq=1000, duty=Brillo)  #PWM en el pin 5

Boton_UP = Pin (0, Pin.IN, pull=Pin.PULL_UP)  #Tecla en D3 
Boton_DN = Pin (4, Pin.IN, pull=Pin.PULL_UP)  #Tecla en D2

def Pulsa_UP ():
     if (Boton_UP.value()==1):
         return 0
     else:
         sleep (0.01)
         if (Boton_UP.value()==1):
             return 0
         else:
             return 1

def Pulsa_DN ():
     if (Boton_DN.value()==1):
         return 0
     else:
         sleep (0.01)
         if (Boton_DN.value()==1):
             return 0
         else:
             return 1

while (True):

    LedPWM.duty (Brillo)  #Actualizar brillo del led 

    if (Pulsa_DN()==1 and  Brillo!=0):
        Brillo=Brillo-1
        print (Brillo) 

    if (Pulsa_UP()==1 and Brillo<1024):     
        Brillo=Brillo+1     
        print (Brillo)

En el video se puede ver el circuito en funcionamiento

Espero que les haya sido de utilidad el artículo, en otras entregas seguiremos viendo mas características de MicroPython.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: