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.

Arduino Nano RP2040 Connect

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, D2D13 (digitales), A0A7 (analógicos).

Distribución de pines

Distribución de pines de la Arduino Nano RP2040 Connect

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 D13

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 Vno 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 VIN pueden 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 REC en 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 llamada RPI-RP2 y 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

D3

D1

D4

D2

D5

D3

D6

D4

D7

D5

D8

D6

D9

D7

D2

HSYNC

A1

VSYNC

A0

PXCLK

A3

MXCLK

A2

POWER

TX

RESET

RX

SCL

SDA (I²C 0)

SDA

SCL (I²C 0)

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

SDA / A4

SCL / A5

I2C1

A0

A1

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 LSM6DSOX

  • 0x60 — 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 Vread_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 TX y D4.

  • PWM0 B está en RX y D5.

  • PWM2 A está en D8 y D12.

  • PWM2 B está en D9 y D10.

  • PWM6 A está en D16/A2 y D18/A4/SDA.

  • PWM6 B está en D17/A3 y D19/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 /flash y usada como directorio de trabajo. Contiene main.py y README.txt de forma predeterminada; se crea en el primer arranque.

Tras el montaje, el intérprete ejecuta entonces scripts desde /flash:

  • boot.py se ejecuta en cada reinicio en caliente.

  • main.py se ejecuta solo en el arranque en frío, inmediatamente después de boot.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.