Skip to main content

XIAO ESP32C3 de Seeed Studio con MicroPython

MicroPython es un intérprete de Python con una función parcial de compilación de código nativo. Proporciona un subconjunto de las características de Python 3.5, diseñado para procesadores embebidos y sistemas con recursos limitados. Es diferente de CPython, y puedes leer más sobre las diferencias aquí.

Instalación de MicroPython

Instalar Esptool

Si aún no has instalado esptool.py, puedes hacerlo usando pip en tu PC:

pip install esptool

Descargar el firmware de MicroPython para XIAO ESP32C3

Debes descargar el archivo binario del firmware desde micropython.org.
Después de descargar el archivo bin correcto, navega hasta la carpeta y abre una terminal cmd allí.
Al momento de la última actualización, la versión más reciente del archivo binario es:

ESP32_GENERIC_C3-20230602-v1.23.0.bin

Conectar el XIAO ESP32C3 a tu PC

Debes mantener presionado el botón BOOT en tu placa XIAO ESP32C3 para entrar en el modo bootloader mientras lo conectas a tu PC mediante un cable USB tipo C.

Verificar el puerto

Encuentra todos los dispositivos seriales en tu PC.

  • Linux

En Linux, puedes usar el comando dmesg para ver los dispositivos conectados:

dmesg | grep tty

Alternativamente, puedes listar los dispositivos seriales con ls:

ls /dev/ttyS* /dev/ttyUSB*
  • Window

En Windows, puedes verificar los puertos seriales desde el Administrador de dispositivos. Busca la sección “Puertos (COM & LPT)” para ver los puertos disponibles. También puedes usar el comando mode en la Terminal (cmd) para listar los puertos:

mode
  • macOS

En macOS, puedes listar los puertos seriales disponibles con el comando ls:

ls /dev/cu*

Esto mostrará todos los dispositivos de puerto serial.

tip

Si el puerto está ocupado, puedes usar el siguiente comando para encontrar y cerrar los procesos que lo están usando (en macOS): Identificar los procesos que están utilizando el puerto:

lsof | grep port

Este comando lista los archivos abiertos y busca cualquier proceso que esté utilizando el puerto especificado. Encuentra el ID del proceso (PID) en la salida y termina el proceso:

kill -9 <PID>

Reemplaza PID con el número del proceso que deseas finalizar.

Borrar la memoria flash

esptool.py --chip esp32c3 --port /dev/cu.usbmodem11301 erase_flash

Reemplaza '/dev/cu.usbmodem11301' con el nombre correcto del puerto en tu sistema (por ejemplo, COM3 en Windows o /dev/ttyUSB0 en Linux).

Escribir la memoria flash

Graba el firmware en el XIAO ESP32C3:

esptool.py --chip esp32c3 --port /dev/cu.usbmodem11301 --baud 460800 write_flash -z 0x0 ESP32_GENERIC_C3-20240602-v1.23.0.bin

Nuevamente, reemplaza '/dev/cu.usbmodem11301' con el nombre correcto del puerto y 'ESP32_GENERIC_C3-20240602-v1.23.0.bin' con la ruta de tu archivo de firmware.

¡Ahora puedes comenzar a compilar scripts para el ESP32 con tu herramienta preferida!

Editores Recomendados para MicroPython

Aquí se enlistan algunas de las herramientas más populares.

1. Thonny

Instala y abre Thonny, luego configúralo siguiendo estas instrucciones:

pip install thonny
# Abre Thonny después de la instalación
thonny

Ve a Ejecutar --> Configurar intérprete y asegúrate de que la pestaña Intérprete en las opciones de Thonny se vea como en la imagen siguiente. Selecciona "CircuitPython (generic)" y el puerto correspondiente:

Haz clic en "OK" en el diálogo y deberías ver la consola de MicroPython en la parte inferior de la ventana de Thonny, como se muestra en la imagen siguiente.

Ingresa el script línea por línea en la Shell para obtener el tamaño de la memoria flash y SRAM:

import gc
gc.mem_free()

import esp
esp.flash_size()

¡Felicidades por haber configurado exitosamente MicroPython en tu XIAO ESP32C3 con Thonny!

2. Laboratorio de Arduino para MicroPython

Descarga el laboratorio de Arduino para MicroPython y conecta el dispositivo a tu PC.

Código como este:

from machine import Pin
import time

# Define el pin del LED
led = Pin(7, Pin.OUT) # Usa el número GPIO correcto en lugar de D10

# Parpadea el LED en un bucle
while True:
led.value(1) # Enciende el LED
time.sleep(1) # Espera un segundo
led.value(0) # Apaga el LED
time.sleep(1) # Espera un segundo

3. Pymakr en Visual Studio Code

  • Instalar Pymakr
    Sigue las instrucciones de instalación para instalar Pymakr.

  • Conectar tu XIAO ESP32C3 a tu computadora.

  • Crear un nuevo proyecto
    Abre VS Code y crea un nuevo proyecto para tu microcontrolador.

  • Agregar un nuevo archivo Python Crea un nuevo archivo Python dentro de tu proyecto.

  • Subir el script al MCU y compilar el script
    Usa la extensión Pymakr en VS Code para cargar el script en el microcontrolador y compilarlo directamente desde el editor.

4. uPtCraft IDE

Información de Pines/Puertos

Empezando con MicroPython en el XIAO ESP32C3

Aquí tienes una referencia rápida para la operación del ESP32 con micropython.
Para más información sobre las bibliotecas de micropython.

Control general de la placa

El REPL de MicroPython (Read-Eval-Print-Loop) está en UART0 (GPIO1=TX, GPIO3=RX) con una velocidad de baudios de 115200. La opción de autocompletar con la tecla de tabulación es útil para descubrir qué métodos tiene un objeto. El modo de pegado (ctrl-E) es útil para pegar un bloque grande de código Python en el REPL.

Puedes usar la función dir() en MicroPython (similar a Python) para listar los atributos y métodos de un objeto.
Por ejemplo, ingresa dir(machine) en la consola:

Uso del modulo machine:

import machine
machine.freq() # obtener la frecuencia actual del CPU, para el esp32c3 es 160000000
machine.freq(160000000) # establecer la frecuencia de la CPU a 160 MHz

El módulo esp:

import esp

esp.osdebug(None) # desactivar los mensajes de depuración del sistema operativo del proveedor
esp.osdebug(0) # redirigir los mensajes de depuración del sistema operativo del proveedor al UART(0)

# métodos de bajo nivel para interactuar con el almacenamiento flash
esp.flash_size() # obtener el tamaño del flash
esp.flash_user_start() # obtener el inicio del área de usuario en el flash
esp.flash_erase(sector_no) # borrar un sector del flash
esp.flash_write(byte_offset, buffer) # escribir en el flash
esp.flash_read(byte_offset, buffer) # leer del flash

El módulo esp32: El ESP32C3, ESP32S2 y ESP32S3 tienen un sensor de temperatura interno disponible que devuelve la temperatura en grados Celsius:

import esp32
esp32.mcu_temperature() # leer la temperatura interna del MCU, en Celsius

Red-WLAN

El módulo Network:

Más información en aquí.

import network

wlan = network.WLAN(network.STA_IF) # crear la interfaz de estación
wlan.active(True) # activar la interfaz
wlan.scan() # escanear puntos de acceso
wlan.isconnected() # verificar si la estación está conectada a un punto de acceso
wlan.connect('ssid', 'key') # conectarse a un punto de acceso
wlan.config('mac') # obtener la dirección MAC de la interfaz
wlan.ifconfig() # obtener las direcciones IPv4 de la interfaz

ap = network.WLAN(network.AP_IF) # crear la interfaz de punto de acceso
ap.config(ssid='ESP-AP') # configurar el SSID del punto de acceso
ap.config(max_clients=10) # establecer cuántos clientes pueden conectarse a la red
ap.active(True) # activar la interfaz

Una función útil para conectarse a tu red WiFi local es:

def do_connect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('conectando a la red...')
wlan.connect('ssid', 'key') #reemplaza ssid y clave
while not wlan.isconnected():
pass
print('configuración de red:', wlan.ifconfig())

Retardos y temporización

El módulo time:

import time

time.sleep(1) # dormir durante 1 segundo
time.sleep_ms(500) # dormir durante 500 milisegundos
time.sleep_us(10) # dormir durante 10 microsegundos
start = time.ticks_ms() # obtener el contador de milisegundos
delta = time.ticks_diff(time.ticks_ms(), start) # calcular la diferencia de tiempo

Temporizadores

El puerto ESP32 tiene cuatro temporizadores de hardware. Utiliza la clase con un ID de temporizador de 0 a 3 (inclusive):

from machine import Timer

tim0 = Timer(0)
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))

tim1 = Timer(1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))

El período está en milisegundos.

Los temporizadores virtuales no son compatibles actualmente en este puerto.

Pines y GPIOs

La clase machine.Pin:

from machine import Pin

p2 = Pin(2, Pin.OUT) # crear un pin de salida en GPIO2
p2.on() # establecer el pin en "encendido" (alto)
p2.off() # establecer el pin en "apagado" (bajo)
p2.value(1) # establecer el pin en alto/encendido

p3 = Pin(3, Pin.IN) # crear un pin de entrada en GPIO3
print(p3.value()) # obtener el valor, 0 o 1

p4 = Pin(4, Pin.IN, Pin.PULL_UP) # habilitar la resistencia interna de pull-up
p5 = Pin(5, Pin.OUT, value=1) # establecer el pin en alto al crearlo
p6 = Pin(6, Pin.OUT, drive=Pin.DRIVE_3) # establecer la máxima fuerza de conducción

Los pines disponibles son de los siguientes rangos (inclusive): 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 21. Estos corresponden a los números reales de los pines GPIO del chip ESP32C3.

UART (bus serie)

La clase machine.UART:

from machine import UART

uart1 = UART(1, baudrate=9600, tx=21, rx=20)
uart1.write('hello') # escribir 5 bytes
uart1.read(5) # leer hasta 5 bytes

El ESP32C3 tiene un UART de hardware. Los pines disponibles para el UART son los siguientes:

UARTPin
TX21
RX20

PWM (Modulación por ancho de pulso)

PWM se puede habilitar en todos los pines habilitados para salida. La frecuencia base puede variar de 1 Hz a 40 MHz, pero hay una compensación; a medida que aumenta la frecuencia base, la resolución del ciclo de trabajo disminuye.

La clase machine.PWM:

from machine import Pin, PWM

pwm2 = PWM(Pin(2), freq=5000, duty_u16=32768) # crear objeto PWM a partir de un pin
freq = pwm2.freq() # obtener la frecuencia actual
pwm2.freq(1000) # establecer la frecuencia PWM entre 1Hz y 40MHz

duty = pwm2.duty() # obtener el ciclo de trabajo actual, rango 0-1023 (predeterminado 512, 50%)
pwm2.duty(256) # establecer el ciclo de trabajo de 0 a 1023 como una relación duty/1023 (ahora 25%)

duty_u16 = pwm2.duty_u16() # obtener el ciclo de trabajo actual, rango 0-65535
pwm2.duty_u16(2**16*3//4) # establecer el ciclo de trabajo de 0 a 65535 como una relación duty_u16/65535 (ahora 75%)

duty_ns = pwm2.duty_ns() # obtener el ancho del pulso actual en ns
pwm2.duty_ns(250_000) # establecer el ancho del pulso en nanosegundos entre 0 y 1_000_000_000/freq (ahora 25%)

pwm2.deinit() # apagar PWM en el pin

pwm3 = PWM(Pin(3), freq=20000, duty=512) # crear y configurar en un solo paso
print(pwm3) # ver la configuración del PWM

Este código te permite configurar y controlar señales PWM en los pines del ESP32C3, ajustando parámetros como la frecuencia, el ciclo de trabajo (duty cycle) y el ancho del pulso.

Los chips ESP tienen diferentes periféricos de hardware:

Especificación de HardwareESP32C3ESP32
Número de grupos (modos de velocidad)12
Número de timers por grupo44
Númweo de canales por grupo68
Diferentes frecuencias de PWM (grupos * timers)48
Total de canales PWM (pines, duties) (grupos * canales)616

ADC (Conversión de Analógico a Digital)

En el XIAO ESP32C3, la funcionalidad ADC está disponible en los pines 2, 3 y 4.

note

A3 (GP105) - Utiliza ADC2, que puede volverse inoperativo debido a señales de muestreo incorrectas. Para lecturas analógicas, utiliza ADC1 (A0/A1/A2) en su lugar. Consulta la hoja de datos del XIAO ESP32C3.

La clase machine.ADC:

from machine import ADC

adc = ADC(pin) # crea un objeto ADC que actúa sobre un pin
val = adc.read_u16() # lee un valor analógico sin procesar en el rango de 0 a 65535
val = adc.read_uv() # lee un valor analógico en microvoltios

SPI

Bus SPI por software

SPI por software (utilizando "bit-banging") funciona en todos los pines y se accede a través de la clase machine.SoftSPI:

from machine import Pin, SoftSPI

# construir un bus SoftSPI en los pines dados
# la polaridad es el estado inactivo de SCK
# phase=0 significa muestrear en el primer flanco de SCK, phase=1 significa en el segundo
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(2), mosi=Pin(4), miso=Pin(6))

spi.init(baudrate=200000) # establecer la velocidad de baudios

spi.read(10) # leer 10 bytes en MISO
spi.read(10, 0xff) # leer 10 bytes mientras se envía 0xff en MOSI

buf = bytearray(50) # crear un buffer
spi.readinto(buf) # leer en el buffer dado (lee 50 bytes en este caso)
spi.readinto(buf, 0xff) # leer en el buffer dado y enviar 0xff en MOSI

spi.write(b'12345') # escribir 5 bytes en MOSI

buf = bytearray(4) # crear un buffer
spi.write_readinto(b'1234', buf) # escribir en MOSI y leer desde MISO en el buffer
spi.write_readinto(buf, buf) # escribir buf en MOSI y leer MISO de vuelta en buf

Bus SPI por hardware

El bus SPI por hardware se accede a través de la clase machine.SPI y tiene los mismos métodos que el SPI por software mencionado anteriormente:

from machine import Pin, SPI

hspi = SPI(1, 10000000) # crear un objeto SPI con velocidad de baudios de 10 MHz
hspi = SPI(1, 10000000, sck=Pin(8), mosi=Pin(10), miso=Pin(9)) # configurar pines específicos para SCK, MOSI y MISO
SPIPin
SCKD8
MOSID10
MISOD9

Bus I2C por software

El bus I2C por software (utilizando bit-banging) funciona en todos los pines capaces de salida y se accede a través de la clase machine.SoftI2C:

from machine import Pin, SoftI2C

i2c = SoftI2C(scl=Pin(7), sda=Pin(6), freq=100000) # crear un bus I2C en los pines SCL y SDA con frecuencia de 100 kHz

i2c.scan() # escanear dispositivos conectados al bus I2C

i2c.readfrom(0x3a, 4) # leer 4 bytes del dispositivo con dirección 0x3a
i2c.writeto(0x3a, '12') # escribir '12' al dispositivo con dirección 0x3a

buf = bytearray(10) # crear un búfer de 10 bytes
i2c.writeto(0x3a, buf) # escribir el búfer dado al periférico

Bus I2C por hardware

El controlador se accede a través de la clase machine.I2C y tiene los mismos métodos que el bus I2C por software mencionado anteriormente:

from machine import Pin, I2C
i2c = I2C(0, scl=Pin(7), sda=Pin(6), freq=400000) # crear un bus I2C en los pines SCL y SDA con frecuencia de 400 kHz
I2CGPIOPin
SCLGPIO7D5
SDAGPIO6D4

Placa de expansión base para XIAO

Requisitos previos:

XIAO ESP32C3
con pines soldados
Placa de Expansión para XIAOSensor Grove Light

Leer los datos del sensor de luz

import time
from machine import Pin, ADC

# Inicializar la entrada analógica en el pin 2 (corresponde a A0)
entrada_analogica = ADC(Pin(2))
entrada_analogica.atten(ADC.ATTN_11DB) # Configurar el rango de entrada (0-3.6V)

def obtener_tension(pin):
# Convertir el valor crudo del ADC a tensión
return (pin.read() / 4095) * 3.3

while True:
# Leer el valor analógico crudo
valor_crudo = entrada_analogica.read()
# Convertir el valor crudo a tensión
tension = obtener_tension(entrada_analogica)

# Imprimir el valor crudo y la tensión en la consola serial
print("[Luz] Valor crudo: {:5d} Tensión: {:.2f}V".format(valor_crudo, tension))

# Esperar un corto período de tiempo antes de leer nuevamente
time.sleep(1)

Encender la pantalla OLED

Conecta tu XIAO ESP32C3, abre Thonny y haz clic en la esquina inferior derecha para configurar el intérprete. Selecciona el intérprete - Micropython (ESP32) y Puerto >>> Haz clic en OK.

Si todo va bien, verás la salida en la terminal. Instala las bibliotecas necesarias Haz clic en "Herramientas" >>> Haz clic en "Gestión de paquetes" >>> Ingresa el nombre de la biblioteca >>> Haz clic en "Buscar micropython-lib y PyPl".

Ejecuta el script y flashea a la placa. Después de terminar de programar, haz clic en el botón verde para ejecutar el script.

import time
from machine import Pin, SoftI2C
import ssd1306
import math

# Asignación de pines
i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) # Ajusta los números de los pines según tus conexiones
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)

oled.fill(0) # Limpiar la pantalla
oled.text("¡Hola, Seeder!", 10, 15)
oled.text("/////", 30, 40)
oled.text("(`3`)y", 30, 55)
oled.show() # Mostrar el texto

¡Gracias por leer este artículo! No dudes en compartir tus pensamientos en los comentarios.

Recursos

Soporte Técnico y Discusión de Productos

¡Gracias por elegir nuestros productos! Estamos aquí para brindarte diferentes tipos de soporte y asegurarnos de que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a distintas preferencias y necesidades.

Loading Comments...