Arduino Nano RP2040 Connect¶
Advertencia
Esta placa ya no tiene soporte. La última versión de firmware de OpenMV para la Arduino Nano RP2040 Connect es la 4.7.0. No se publicarán más actualizaciones de firmware, correcciones de errores ni nuevas funciones para este objetivo. La información que aparece a continuación se conserva para los usuarios que utilicen la versión 4.7.0 o anteriores.
La Arduino Nano RP2040 Connect es una placa de 45 × 18 mm con factor de forma Arduino Nano construida en torno al Raspberry Pi RP2040 — un doble ARM Cortex‑M0+ que funciona a 133 MHz con 264 KB de SRAM interna. El WiFi y el BLE provienen de un módulo U‑blox NINA‑W102, y la placa incorpora una IMU de 6 ejes LSM6DSOX y un micrófono PDM MP34DT06. El firmware de OpenMV controla todos estos elementos desde MicroPython.
Para ver la hoja de datos completa, fotos y dimensiones, consulta la página del producto Arduino Nano RP2040 Connect.
Aspectos destacados¶
Raspberry Pi RP2040 doble ARM Cortex‑M0+ a 133 MHz con 264 KB de SRAM interna.
16 MB de memoria flash QSPI externa.
Módulo U‑blox NINA‑W102 que proporciona Wi‑Fi b/g/n de 2,4 GHz y Bluetooth 4.2 (BR/EDR + LE).
IMU de 6 ejes LSM6DSOX y micrófono PDM MP34DT06.
Conector Micro USB para alimentación, programación y un REPL CDC.
22 pines de E/S de usuario en los conectores estándar Nano —
TX/RX,D2–D13(digitales),A0–A7(analógicos).
Distribución de pines¶
Referencia de pines¶
Nombre del pin |
Referencia |
Función |
|---|---|---|
TX |
3,3 V |
UART0 TX / SPI0 RX / I2C0 SDA / PWM0 A |
RX |
3,3 V |
UART0 RX / SPI0 CS / I2C0 SCL / PWM0 B |
D2 |
3,3 V |
SPI1 CS / UART1 RX / I2C0 SCL / PWM4 B |
D3 |
3,3 V |
SPI1 TX / UART0 RTS / I2C1 SCL / PWM7 B |
D4 |
3,3 V |
SPI0 RX / UART0 TX / I2C0 SDA / PWM0 A |
D5 |
3,3 V |
SPI0 CS / UART0 RX / I2C0 SCL / PWM0 B |
D6 |
3,3 V |
SPI0 SCK / UART0 CTS / I2C1 SDA / PWM1 A |
D7 |
3,3 V |
SPI0 TX / UART0 RTS / I2C1 SCL / PWM1 B |
D8 |
3,3 V |
SPI0 RX / UART1 TX / I2C0 SDA / PWM2 A |
D9 |
3,3 V |
SPI0 CS / UART1 RX / I2C0 SCL / PWM2 B |
D10 |
3,3 V |
SPI0 CS / UART1 RX / I2C0 SCL / PWM2 B |
D11 |
3,3 V |
SPI0 TX / UART1 RTS / I2C1 SCL / PWM3 B |
D12 |
3,3 V |
SPI0 RX / UART1 TX / I2C0 SDA / PWM2 A |
D13 |
3,3 V |
SPI0 SCK / UART1 CTS / I2C1 SDA / PWM3 A |
D14 / A0 |
3,3 V |
ADC / SPI1 SCK / UART1 CTS / I2C1 SDA / PWM5 A |
D15 / A1 |
3,3 V |
ADC / SPI1 TX / UART1 RTS / I2C1 SCL / PWM5 B |
D16 / A2 |
3,3 V |
ADC / SPI1 RX / UART0 TX / I2C0 SDA / PWM6 A |
D17 / A3 |
3,3 V |
ADC / SPI1 CS / UART0 RX / I2C0 SCL / PWM6 B |
D18 / A4 / SDA |
3,3 V |
ADC / I2C0 SDA / SPI1 RX / UART0 TX / PWM6 A |
D19 / A5 / SCL |
3,3 V |
ADC / I2C0 SCL / SPI1 CS / UART0 RX / PWM6 B |
D20 / A6 |
3,3 V |
ADC / GPIO |
D21 / A7 |
3,3 V |
ADC / GPIO |
RESET |
3,3 V |
pulsa el botón RESET de la placa o conéctalo a GND para reiniciar |
REC |
3,3 V |
BOOTSEL — pon en alto al encender para entrar en el gestor de arranque (bootloader) ROM del RP2040 |
LED_BUILTIN |
— |
LED de usuario naranja en |
LED_RED |
— |
Canal rojo del LED RGB |
LED_GREEN |
— |
Canal verde del LED RGB |
LED_BLUE |
— |
Canal azul del LED RGB |
Advertencia
Los pines de E/S de la Nano RP2040 Connect son solo de 3,3 V — no toleran 5 V. Aplicar 5 V en ellos dañará el RP2040.
Pines de alimentación¶
VIN — entrada de 4 – 20 V. Alimenta la placa a través del regulador conmutado integrado. También se alimenta a través de un diodo desde el raíl de 5 V del USB, por lo que el USB y
VINpueden estar presentes al mismo tiempo sin retroalimentarse entre sí.+5V — no conectado de forma predeterminada.
+3V3 — salida del regulador de 3,3 V.
AREF — pin de referencia analógica. No está conectado al RP2040 en esta placa — el ADC siempre se referencia a 3,3 V.
GND — tierra común.
La Nano RP2040 Connect puede alimentarse a través de cualquiera de estas vías:
Micro USB — suministra 5 V al regulador integrado.
Pin VIN — aplica una fuente regulada de 4 – 20 V.
Nota
Un puente de soldadura en la parte inferior de la placa conecta +5V con el raíl de 5 V del USB. Ciérralo para que el pin del conector +5V lleve realmente 5 V.
Nota
Un puente de soldadura normalmente cerrado en la salida del regulador conmutado integrado de 4–20 V puede cortarse para desactivar el regulador, de modo que la placa pueda alimentarse directamente desde una fuente externa de 3,3 V en +3V3.
Pines de recuperación y depuración¶
RESET — tanto una almohadilla expuesta como un botón RESET momentáneo en la parte superior de la placa, conectados a la línea NRST del RP2040. Conecta a GND o pulsa el botón para reiniciar.
REC — almohadilla expuesta. Mantener
RECen alto al encender (o mientras se pulsa RESET) pone al RP2040 en su gestor de arranque (bootloader) ROM; la placa se vuelve a enumerar como una unidad de almacenamiento masivo USB llamadaRPI-RP2y acepta una imagen de firmware.uf2.
La Nano RP2040 Connect utiliza el reinicio de doble pulsación estándar de Arduino para entrar en el gestor de arranque (bootloader) de Arduino. Pulsa rápidamente el botón RESET dos veces — la placa se vuelve a enumerar por USB como un dispositivo UF2 y OpenMV IDE puede grabar una nueva imagen de firmware.
Las señales SWD del RP2040 están expuestas en almohadillas metalizadas en la parte trasera de la placa, justo debajo del módulo NINA. Todas las señales de depuración están referenciadas a 3,3 V.
Periféricos integrados¶
LEDs¶
La Nano RP2040 Connect tiene un LED RGB de usuario — controlado a través de los canales serigrafiados LED_RED, LED_GREEN y LED_BLUE — más un LED naranja independiente LED_BUILTIN en D13. Los cuatro son controlables por software a través de machine.LED:
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
LED("LED_BUILTIN").on()
Un LED de alimentación verde independiente en la placa se ilumina siempre que el raíl de +3,3 V está activo y no es controlable por el usuario.
Sensor de cámara¶
El firmware de OpenMV en la Nano RP2040 Connect admite el sensor CMOS paralelo OmniVision OV7670. La placa no tiene sensor de imagen integrado — conecta un módulo OV7670 a los pines del conector serigrafiados que se enumeran a continuación y contrólalo a través del módulo csi — sensores de cámara:
import csi
cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000) # let auto‑exposure settle
while True:
img = cam.snapshot()
Nota
El OV7670 utiliza 14 pines. El firmware los conecta de la siguiente manera:
Señal del sensor |
Pin de la Nano RP2040 |
|---|---|
D0 |
|
D1 |
|
D2 |
|
D3 |
|
D4 |
|
D5 |
|
D6 |
|
D7 |
|
HSYNC |
|
VSYNC |
|
PXCLK |
|
MXCLK |
|
POWER |
|
RESET |
|
SCL |
|
SDA |
|
El bus de control I²C del OV7670 se comparte con la IMU integrada y el ATECC608A en el I²C 0. El sensor está en la dirección de 7 bits 0x21 — los dispositivos de usuario en el bus 0 también deben evitar esta dirección cuando la cámara está conectada.
IMU¶
El acelerómetro + giroscopio de 6 ejes LSM6DSOX integrado está en I2C0. El machine.I2C(0) del port rp2 utiliza de forma predeterminada un conjunto de pines diferente, así que pasa explícitamente las almohadillas serigrafiadas SDA/SCL. Usa el controlador congelado lsm6dsox.LSM6DSOX:
import time
from machine import I2C, Pin
from lsm6dsox import LSM6DSOX
bus = I2C(0, scl=Pin("SCL"), sda=Pin("SDA"))
imu = LSM6DSOX(bus)
while True:
print(imu.accel()) # (x, y, z) in g
print(imu.gyro()) # (x, y, z) in deg/s
time.sleep_ms(100)
Micrófono¶
El micrófono PDM MP34DT06 integrado se captura a través de audio — Módulo de audio utilizando uno de los bloques PIO del RP2040:
import audio
from ulab import numpy as np
def loudness(pcmbuf):
samples = np.array(np.frombuffer(pcmbuf, dtype=np.int16), dtype=np.float)
rms = np.sqrt(np.mean(samples ** 2))
if rms > 10000:
print("Loud!", int(rms))
audio.init(channels=1, frequency=16000, gain_db=24)
audio.start_streaming(loudness)
while True:
pass
Wi‑Fi¶
El módulo NINA‑W102 integrado se expone a través de network — configuración de red como una interfaz de estación:
import network, time
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("ssid", "password")
while not wlan.isconnected():
time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])
Bluetooth¶
El mismo módulo NINA también expone Bluetooth 4.2 LE. Usa aioble — BLE asíncrono para un BLE compatible con asyncio — por ejemplo, anúnciate como periférico y espera a que un central se conecte:
import asyncio
import aioble
async def run():
while True:
conn = await aioble.advertise(250_000, name="Nano-RP2040")
print("Connected:", conn.device)
await conn.disconnected()
asyncio.run(run())
Referencia de buses¶
GPIO¶
Usa machine.Pin para leer o controlar cualquiera de los pines serigrafiados. Las salidas son CMOS de 3,3 V, con 50 mA totales de corriente de sumidero entre todos los GPIO.
from machine import Pin
out = Pin("D2", Pin.OUT)
out.on()
out.off()
out.value(1)
inp = Pin("D3", Pin.IN, Pin.PULL_UP)
print(inp.value())
Cualquier pin de entrada también puede disparar una interrupción en las transiciones de flanco:
def handler(pin):
print("triggered:", pin)
Pin("D3", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Bus |
TX |
RX |
|---|---|---|
UART0 |
TX |
RX |
Usa los nombres de serigrafía TX/RX con machine.UART:
from machine import UART
uart = UART(0, baudrate=115200)
uart.write("hello")
uart.read(5)
Nota
machine.UART(1) existe pero está reservado para el módulo NINA‑W102 integrado (el enlace BLE); no lo uses directamente.
I²C¶
Bus |
SDA |
SCL |
|---|---|---|
I2C0 |
|
|
I2C1 |
|
|
Ambos buses necesitan que sus pines se pasen explícitamente a machine.I2C:
from machine import I2C, Pin
bus0 = I2C(0, scl=Pin("SCL"), sda=Pin("SDA"), freq=400_000)
bus0.scan()
bus1 = I2C(1, scl=Pin("A1"), sda=Pin("A0"), freq=400_000)
bus1.scan()
Nota
Dos chips integrados comparten el bus 0 — los dispositivos de usuario en este bus deben evitar sus direcciones:
0x6A— IMU LSM6DSOX0x60— ATECC608A‑MAHDA‑T
Usar A0/A1 como I²C los consume para el bus, por lo que no pueden ser simultáneamente entradas ADC.
Nota
Las almohadillas SDA / SCL (bus 0) tienen resistencias pull‑up integradas a 3,3 V, por lo que no se necesitan pull‑ups externas para los dispositivos en ese bus. A0 / A1 (bus 1) no las tienen — añade pull‑ups externas al usar el bus 1.
El mismo hardware también puede usarse en modo objetivo (esclavo) a través de machine.I2CTarget para exponer una región de memoria a otro controlador I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(0, addr=0x42, mem=buf)
SPI¶
Bus |
MOSI |
MISO |
SCK |
CS |
|---|---|---|---|---|
SPI0 |
D11 |
D12 |
D13 |
D10 |
El port rp2 no preconfigura los pines del SPI0 en esta placa, así que pasa explícitamente las almohadillas serigrafiadas al crear el bus:
from machine import SPI, Pin
spi = SPI(0, baudrate=10_000_000,
sck=Pin("D13"), mosi=Pin("D11"), miso=Pin("D12"))
cs = Pin("D10", Pin.OUT, value=1) # CS is not driven by the SPI peripheral
cs.value(0)
spi.write(b"hello")
cs.value(1)
Nota
D13 funciona también como el LED naranja LED_BUILTIN — controlar el SPI en este bus hará parpadear el LED al ritmo del reloj del bus.
Nota
machine.SPI(1) existe pero está reservado para el módulo NINA‑W102 integrado (el enlace SPI Wi‑Fi/BLE); no lo uses directamente.
ADC¶
El RP2040 tiene cuatro canales ADC de 12 bits expuestos en A0–A3, todos referenciados a 3,3 V — read_u16 devuelve 0–65535 a lo largo de 0–3,3 V en el pin. El pin AREF de la placa no está conectado, por lo que la referencia siempre es 3,3 V:
from machine import ADC
import time
adc = ADC("A0")
while True:
voltage = adc.read_u16() * 3.3 / 65535
print(voltage)
time.sleep_ms(100)
PWM¶
Pin |
Slice / canal |
|---|---|
TX |
PWM0 A |
RX |
PWM0 B |
D2 |
PWM4 B |
D3 |
PWM7 B |
D4 |
PWM0 A |
D5 |
PWM0 B |
D6 |
PWM1 A |
D7 |
PWM1 B |
D8 |
PWM2 A |
D9 |
PWM2 B |
D10 |
PWM2 B |
D11 |
PWM3 B |
D12 |
PWM2 A |
D13 |
PWM3 A |
D14 / A0 |
PWM5 A |
D15 / A1 |
PWM5 B |
D16 / A2 |
PWM6 A |
D17 / A3 |
PWM6 B |
D18 / A4 / SDA |
PWM6 A |
D19 / A5 / SCL |
PWM6 B |
Controla cualquiera de ellos a través de machine.PWM:
from machine import Pin, PWM
pwm = PWM(Pin("D3"), freq=1_000, duty_u16=32768)
Nota
Varios pines comparten canales de slice PWM:
PWM0 A está en
TXyD4.PWM0 B está en
RXyD5.PWM2 A está en
D8yD12.PWM2 B está en
D9yD10.PWM6 A está en
D16/A2yD18/A4/SDA.PWM6 B está en
D17/A3yD19/A5/SCL.
Elige un solo consumidor por canal de slice. Los canales A y B dentro del mismo slice comparten su periodo (frecuencia) pero cada uno tiene su propio ciclo de trabajo.
Buses emulados por software (bit‑banged)¶
machine.SoftI2C y machine.SoftSPI funcionan en cualquier GPIO si necesitas un bus adicional.
Sensor térmico (externo)¶
El firmware incluye el controlador fir — controlador de sensor térmico (fir == infrarrojo lejano) para una cámara térmica AMG8833 de 8×8 conectada externamente. Conecta el módulo al bus I²C que se indica a continuación y luego lee fotogramas con fir.init() + fir.snapshot():
import time
import image
import fir
fir.init() # auto‑detects the sensor
clock = time.clock()
while True:
clock.tick()
try:
img = fir.snapshot(x_scale=5, y_scale=5,
color_palette=image.PALETTE_IRONBOW,
hint=image.BICUBIC,
copy_to_fb=True)
except OSError:
continue
print(clock.fps())
El controlador fir solo se comunica con el sensor a través del I²C 0 — conecta el módulo a las almohadillas serigrafiadas SCL / SDA. La dirección de 7 bits del sensor (0x69) no debe ser utilizada por ningún otro dispositivo en ese bus.
Temporización¶
time¶
El módulo time cubre retardos bloqueantes, ticks monotónicos y medición de tiempo transcurrido:
import time
time.sleep(1) # seconds
time.sleep_ms(500)
time.sleep_us(10)
start = time.ticks_ms()
# ...do work...
elapsed = time.ticks_diff(time.ticks_ms(), start)
Temporizadores virtuales¶
machine.Timer programa funciones de retorno (callbacks) periódicas o de un solo disparo sin consumir una ranura de temporizador de hardware. Pasa -1 como id para usar un temporizador virtual (de software):
from machine import Timer
one_shot = Timer(-1)
one_shot.init(period=5_000, mode=Timer.ONE_SHOT,
callback=lambda t: print("once"))
periodic = Timer(-1)
periodic.init(period=2_000, mode=Timer.PERIODIC,
callback=lambda t: print("tick"))
Los valores de periodo están en milisegundos. Llama a deinit() para detener y liberar la ranura.
Reloj en tiempo real¶
machine.RTC mantiene la hora del reloj a través de los reinicios. El RTC del RP2040 está ligado al oscilador del chip y no sobrevive a una pérdida total de alimentación — ajusta la hora en cada arranque en frío si es importante para tu aplicación:
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0)) # Y, M, D, weekday, h, m, s, subsec
print(rtc.datetime())
Watchdog¶
machine.WDT reinicia la placa si la aplicación se cuelga. Una vez iniciado, no puede detenerse ni reconfigurarse — aliméntalo periódicamente dentro de tu bucle principal:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
Información de arranque y tiempo de ejecución¶
Actualización de firmware (UF2)¶
La Nano RP2040 Connect utiliza el reinicio de doble pulsación estándar de Arduino para entrar en el gestor de arranque (bootloader) de Arduino. Pulsa rápidamente el botón de reinicio dos veces — la placa se vuelve a enumerar por USB como un dispositivo UF2 y OpenMV IDE puede grabar una nueva imagen de firmware.
Un script en ejecución puede volver a entrar en el gestor de arranque (bootloader) bajo demanda llamando a machine.bootloader():
import machine
machine.bootloader()
Sistema de archivos y orden de arranque¶
El firmware de la Nano RP2040 Connect monta un único sistema de archivos al arrancar:
Memoria flash interna — siempre montada en
/flashy usada como directorio de trabajo. Contienemain.pyyREADME.txtde forma predeterminada; se crea en el primer arranque.
Tras el montaje, el intérprete ejecuta entonces scripts desde /flash:
boot.pyse ejecuta en cada reinicio en caliente.main.pyse ejecuta solo en el arranque en frío, inmediatamente después deboot.py.
El main.py predeterminado que viene en una placa recién grabada simplemente hace parpadear el canal azul del LED RGB de usuario como una señal de actividad (dos pulsos cortos, un breve intervalo), de modo que puedes saber que el firmware arrancó correctamente sin ningún host conectado.
Cuando está conectada por USB, /flash se enumera como una unidad de almacenamiento masivo USB en el host, lo que te permite editar boot.py, main.py y cualquier otro archivo directamente. Expulsa la unidad antes de reiniciar la placa para que el host vuelque sus escrituras en caché.
Nota
Dado que el sistema operativo trata la unidad como un dispositivo de bloques pasivo, los archivos creados o modificados por el código que se ejecuta en la cámara no aparecerán hasta que el host vuelva a montar la unidad. Si tanto el sistema operativo como la cámara escriben en el mismo sistema de archivos al mismo tiempo, el sistema operativo ganará y sobrescribirá los cambios realizados por la cámara. Usa la tarjeta SD para cualquier dato que el script escriba de vuelta, y vuelve a montar antes de leer esos archivos desde el host.
Nota
El canal rojo del LED RGB de usuario puede iluminarse brevemente mientras el host lee o escribe en la unidad de almacenamiento masivo USB — esto es un indicador de actividad gestionado por el firmware, no un fallo.
Tamaños de almacenamiento¶
La Nano RP2040 Connect viene con:
/flash— sistema de archivos FAT de 14 MB, lectura/escritura.
La compilación de la Nano RP2040 no incluye un ROMFS; distribuye los módulos de Python y los modelos de ML directamente en /flash.
Bibliotecas de software¶
Consulta el índice de la biblioteca para ver la lista completa de módulos — incluidos los que son exclusivos de la compilación de la Nano RP2040 Connect.