Micropython: Manejo de pines

Micropython: Manejo de pines

Tabla de Contenido

Note

En este artículo aprenderás que es la clase Pin de Micropython 🐍 y como esta gestiona las diferentes funcionalidades genéricas de los pines de cualquier tipo de chip. Además, verás ejemplos de cómo configurarla y usarla con la RP2040.

¿Qué es la clase Pin?

Empecemos definiendo qué es un pin dentro de nuestro microcontrolador (uM), un pin hace referencia a una interfaz I/O asociada a un pin físico de nuestro uM. Con él podemos interactuar con el mundo real, ya sea leyendo o escribiendo señales digitales, o incluso analógicas.

La clase Pin es una de las principales clases que provee Micropython 🐍, ya que es la que nos permitirá interactuar con los pines de nuestros uM. Esta clase se encuentra en el paquete machine.

Instancia de la Clase Pin

La clase Pin, tiene la siguiente firma de constructor

class Pin(id, mode=-1, pull=-1, *, value=None, drive=0, alt=-1)

En donde:

controla cuál será el comportamiento del pin. En Micropython 🐍 encuentras constantes que te ayudan a establecer el funcionamiento:

  • id es el unico parámetro obligatorio y hace referencia al pin que quieres controlar. Cada uM tiene su propio mapeo de pines, por lo que deberás de consultar la documentación de tu uM para saber que pines puedes controlar.
  • mode* controla cuál será el comportamiento del pin. En Micropython 🐍 encuentras constantes que te ayudan a establecer el funcionamiento:
    • Pin.IN establece el pin como entrada.
    • Pin.OUT establece el pin como salida.
    • Pin.OPEN_DRAIN establece el pin como salida de tipo Open-drain (colector abierto), lo que significa que, si la salida está en nivel bajo, es un cero lógico, y si está en alto (1), se configura como alta impedancia.
    • Pin.ALT establece el pin para funcionar de manera alterna, utilizando un propósito específico del hardware.
    • Pin.ALT_OPEN_DRAIN es la combinación de Pin.ALT y Pin.OPEN_DRAIN
    • Pin.ANALOG establece el pin como entrada analógica
  • pull* activas o no la opción de usar una resistencia de pull-up o pull-down, sus opciones validas son:
    • Pin.PULL_UP
    • Pin.PULL_DOWN
    • None = No se activa ninguna resistencia, es el valor por defecto
  • value es el valor inicial que quieres asignar al pin y solo funciona cuando el pin es configurado como salida, es decir que Pin.OUT o Pin.OPEN_DRAIN
  • drive se utiliza para especificar la fuerza de la salida del pin. Esto es importante cuando conectas el pin a circuitos que tienen diferentes requerimientos de corriente. Los valores típicos para drive son algo así como Pin.DRIVE_0, Pin.DRIVE_1, etc., donde los números más altos representan una mayor capacidad de corriente de salida.
  • alt* cuando el pin está configurado como Pin.ALT o Pin.ALT_OPEN_DRAIN, este parámetro se utiliza para especificar la función alternativa que se desea utilizar.

Note

* No todos los pines tiene disponibles todas las configuraciones descritas, para validarlo debes de consultar la documentación de tu uM

Métodos de la Clase Pin

Pin.init

Pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1)

Una vez tengas una instancia de la clase Pin, puedes cambiar su configuración inicial usando el método init el cual recibe los mismos atributos del constructor salvo el identificador id. Un ejemplo de su uso sería

from machine import Pin

led = Pin(25)
led.init(mode=Pin.OUT, value=True)

En el ejemplo anterior, estoy creando una instancia asociada al pin 25 (mapeado de mi uM) y posteriormente configurándolo con el método init

Pin.value

Pin.value([x])

Este método se utiliza para leer o escribir el valor del pin. Si no se pasa ningún parámetro, el método se comporta como un lector. Si se pasa un valor, el método se comporta como un escritor. Un ejemplo de su uso sería

from machine import Pin

led = Pin(25, Pin.OUT)
led.value(1)

print(led.value())

En el ejemplo, estamos creando un pin como salida y configurando su valor a 1, para luego leer el valor del pin.

Pin.on()

Este método es un atajo para configurar el valor del pin a 1, es decir, que el pin se configura en alto, lo cual sería lo mismo que hacer:

Pin.value(1)

Pin.off()

Este método es un atajo para configurar el valor del pin a 0, es decir, que el pin se configura en bajo, lo cual sería lo mismo que hacer:

Pin.value(0)

Pin.toggle()

Este método es un atajo para cambiar el valor del pin. Si el pin está en 1, lo cambia a 0 y viceversa, lo cual sería lo mismo que hacer:

Pin.value(not Pin.value())

Pin.irq()

Pin.irq(handler=None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, *, priority=1, wake=None, hard=False

Este método es muy importante, ya que sirve para configurar los pines para que sean asociados a interrupciones y poder ejecutar un callback cuando se cumpla una condición. Los parámetros que recibe son:

  • handler: Es un callable de python, es decir, una función o método de clase que recibe como parámetro únicamente un objeto de tipo Pin, que será la instancia del pin que activó la interrupción.

  • trigger: A través de este atributo controlaremos el tipo de comportamiento que se deberá cumplir para activar la interrupción. Para entender los posibles valores que podemos asignar, veamos primero cómo es una señal digital.Una señal digital oscila entre dos valores, 0 o 1, y la transición entre esos valores es lo que llamamos flancos. Como hay dos valores, tenemos 2 tipos de flancos. Los flancos de subida ocurren cuando cambiamos de 0 a 1 y los flancos de bajada cuando cambiamos de 1 a 0. De esta manera, en Micropython encontramos 4 tipos de activadores que podemos configurar en nuestra interrupción por pin:

    • Pin.IRQ_FALLING: Configura la interrupción para que se active cuando el pin cambie de 1 a 0
    • Pin.IRQ_RISING: Configura la interrupción para que se active cuando el pin cambie de 0 a 1
    • Pin.IRQ_LOW_LEVEL: Configura la interrupción para que se active cuando el pin se encuentre en 0
    • Pin.IRQ_HIGH_LEVEL: Configura la interrupción para que se active cuando el pin se encuentre en 1

    En el siguiente diagrama puedes visualizar las fases de la señal:

    Imagen guia del contenido de la página

Note

En el siguiente artículo te explico más del tema de interrupciones con Micropython 🐍.

Ejemplos prácticos de Pin con RP2040

En el siguiente embebido estamos creando un proyecto en la plataforma Wokwi , que nos permite simular proyectos con tarjetas como Arduino Uno, ESP32, Raspberry Pi Pico, entre otras, junto con un amplio conjunto de sensores y actuadores. En este caso, estamos utilizando una Raspberry Pi Pico y conjunto de LEDs y botones para mostrar cómo se puede controlar un pin con la clase Pin de Micropython 🐍

En el ejemplo podemos ver 4 casos de uso sencillos para la clase Pin

  1. Caso 1: Configuramos un pin como salida y lo encendemos en la función main en un intervalo de 500ms con la fuinción sleep
  2. Caso 2: Declaramos un pin como salida, pero primero instanciamos la clase Pin y luego configuramos el pin con el método init.
  3. Case 3: Configuramos dos pines con la clase Pin, uno como salida y otro como entrada. Leemos el valor del pin de entrada y lo asignamos al pin de salida
  4. Caso 4: Configuramos un pin como entrada y configuramos una interrupción para que se active cuando el pin cambie de 0 a 1. En el callback simplemente cambiamos el valor del pin de salida.

Note

  • En el siguiente enlace puedes ver el código fuente del proyecto en una nueva pestaña.
  • El caso 4 de nuestro proyecto funciona con interrupciones, y es posible que en la simulación no funcione correctamente debido a que no se está procesando el debounce del botón.

Info

Podrás encontrar toda la documentación de la clase Pin para micropython 🐍 en el siguiente link