Arduino Nano 33 BLE Sense¶
Aviso
Esta placa já não tem suporte. A última versão de firmware OpenMV para o Arduino Nano 33 BLE Sense é a 4.7.0. Não serão emitidas mais atualizações de firmware, correções de erros ou novas funcionalidades para este alvo. As informações abaixo são preservadas para utilizadores que executem a versão 4.7.0 ou anterior.
O Arduino Nano 33 BLE Sense é uma placa com fator de forma Arduino‑Nano de 45 × 18 mm, construída em torno do Nordic Semiconductor nRF52840 — um único ARM Cortex‑M4 com FPU a 64 MHz, com 256 KB de SRAM interna e 1 MB de flash interna. O BLE provém do rádio integrado no chip, e a placa inclui um IMU de 9 eixos, um barómetro LPS22HB, um sensor de temperatura/humidade HTS221 / HS3003, um sensor de luz ambiente/cor/proximidade/gesto APDS9960, e um microfone PDM MP34DT05. O firmware OpenMV controla todos estes componentes a partir do MicroPython.
Para a ficha de dados completa, fotografias e dimensões, consulte a página do produto Arduino Nano 33 BLE Rev2.
Destaques¶
Nordic nRF52840 Cortex‑M4 com FPU a 64 MHz com 256 KB de SRAM interna e 1 MB de flash interna.
Bluetooth LE 5.0 através do rádio integrado no chip e do Nordic SoftDevice s140.
IMU de 9 eixos —
LSM9DS1na Rev 1,BMI270+BMM150na Rev 2. O controlador frozenimudeteta ambos durante o arranque.LPS22HBbarómetro,HTS221/HS3003sensor de temperatura e humidade,APDS9960sensor de luz ambiente / cor / proximidade / gesto, e microfone PDM MP34DT05.Conector Micro USB para alimentação, programação e um REPL CDC.
22 pinos de I/O de utilizador nos headers Nano padrão —
TX/RX,D2–D13(digital),A0–A7(analógico).
Disposição dos pinos¶
Referência de pinos¶
Nome do pino |
Referência |
Função |
|---|---|---|
TX |
3,3 V |
UART1 TX |
RX |
3,3 V |
UART1 RX |
D2 |
3,3 V |
PWM |
D3 |
3,3 V |
PWM |
D4 |
3,3 V |
PWM |
D5 |
3,3 V |
PWM |
D6 |
3,3 V |
PWM |
D7 |
3,3 V |
PWM |
D8 |
3,3 V |
PWM |
D9 |
3,3 V |
PWM |
D10 |
3,3 V |
PWM |
D11 |
3,3 V |
PWM / SPI0 MOSI |
D12 |
3,3 V |
PWM / SPI0 MISO |
D13 |
3,3 V |
PWM / SPI0 SCK |
A0 |
3,3 V |
ADC / PWM |
A1 |
3,3 V |
ADC / PWM |
A2 |
3,3 V |
ADC / PWM |
A3 |
3,3 V |
ADC / PWM |
A4 / I2C_SDA |
3,3 V |
ADC / PWM / I2C0 SDA |
A5 / I2C_SCL |
3,3 V |
ADC / PWM / I2C0 SCL |
A6 |
3,3 V |
ADC / PWM |
A7 |
3,3 V |
ADC / PWM |
RESET |
3,3 V |
prima o botão RESET na placa ou ligue a GND para reiniciar |
LED_BUILTIN |
— |
LED de utilizador laranja em |
LED_RED |
— |
Canal vermelho do LED RGB (ativo em nível baixo) |
LED_GREEN |
— |
Canal verde do LED RGB (ativo em nível baixo) |
LED_BLUE |
— |
Canal azul do LED RGB (ativo em nível baixo) |
Aviso
Os pinos de I/O do Nano 33 BLE Sense são apenas 3,3 V — não são tolerantes a 5 V. Aplicar 5 V nos mesmos danificará o nRF52840.
Pinos de alimentação¶
VIN — entrada de 4,5 – 21 V. Alimenta a placa através do regulador integrado. Também alimentado via díodo a partir do barramento USB de 5 V, pelo que USB e
VINpodem estar presentes em simultâneo sem retroalimentação.+5V — não ligado por defeito.
+3V3 — saída do regulador de 3,3 V.
AREF — pino de referência analógica. Não ligado ao nRF52840 nesta placa — o ADC é sempre referenciado a 3,3 V.
GND — terra comum.
O Nano 33 BLE Sense pode ser alimentado através de qualquer um dos seguintes caminhos:
Micro USB — fornece 5 V ao regulador integrado.
Pino VIN — aplique uma fonte regulada de 4,5 – 21 V.
Nota
Um jumper de solda na face inferior da placa designado VUSB liga +5V ao barramento USB de 5 V. Feche-o para que o pino de header +5V transporte efetivamente 5 V.
Nota
Um jumper de solda normalmente fechado na saída do regulador de comutação integrado de 4,5–21 V pode ser cortado para desativar o regulador, permitindo alimentar a placa diretamente de uma fonte externa de 3,3 V em +3V3.
Pinos de recuperação e depuração¶
RESET — tanto um pad exposto como um botão RESET momentâneo na face superior da placa, ligado à linha de reset do nRF52840. Ligue a GND ou prima o botão para reiniciar.
O Nano 33 BLE Sense utiliza o duplo toque de reset padrão da Arduino para entrar no bootloader da Arduino. Prima rapidamente o botão RESET duas vezes — a placa entra em modo bootloader e o OpenMV IDE pode flashar uma nova imagem de firmware.
Os sinais SWD do nRF52840 estão expostos em pads metalizados na parte traseira da placa. Todos os sinais de depuração são referenciados a 3,3 V.
Periféricos integrados¶
LEDs¶
O Nano 33 BLE Sense possui um LED RGB de utilizador — controlado através dos canais LED_RED, LED_GREEN e LED_BLUE marcados na serigrafía — mais um LED_BUILTIN laranja separado em D13. Todos os quatro são controláveis por software através de machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
LED("LED_BUILTIN").on()
Um LED verde de alimentação separado na placa acende sempre que o barramento +3,3 V está ativo e não é controlável pelo utilizador.
Sensor de câmara¶
O firmware OpenMV no Nano 33 BLE Sense suporta o sensor CMOS paralelo OmniVision OV7670. A placa não possui sensor de imagem integrado — ligue um módulo OV7670 aos pinos de header indicados na serigrafía abaixo e controle-o através do 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
O OV7670 necessita de 14 pinos. O firmware liga-os da seguinte forma:
Sinal do sensor |
Pino do Nano 33 BLE Sense |
|---|---|
D0 |
|
D1 |
|
D2 |
|
D3 |
|
D4 |
|
D5 |
|
D6 |
|
D7 |
|
HSYNC |
|
VSYNC |
|
PXCLK |
|
MXCLK |
|
POWER |
|
RESET |
|
SCL |
|
SDA |
|
O barramento de controlo I²C do OV7670 é o mesmo I²C 0 externo exposto em A5/A4. O sensor está no endereço de 7 bits 0x21 — os dispositivos de utilizador nesse barramento devem evitar este endereço quando a câmara estiver ligada.
IMU¶
O IMU de 9 eixos é exposto através do módulo frozen imu, que deteta automaticamente se a placa tem o LSM9DS1 (Rev 1) ou o BMI270 + BMM150 (Rev 2) e apresenta uma classe imu.IMU unificada. Os sensores estão no barramento I²C 1 interno (P14 / P15):
import time
from machine import I2C, Pin
from imu import IMU
bus = I2C(1, scl=Pin("P15"), sda=Pin("P14"))
sensor = IMU(bus)
while True:
print(sensor.accel()) # (x, y, z) in g
print(sensor.gyro()) # (x, y, z) in deg/s
print(sensor.magnet()) # (x, y, z) magnetometer
time.sleep_ms(100)
Para acesso direto a funcionalidades como deteção de toque ou a FIFO, importe o controlador frozen correspondente (lsm9ds1, bmi270, ou bmm150) e instancie-o no mesmo barramento.
Sensores ambientais¶
O barómetro (LPS22HB) e o sensor de temperatura/humidade (HTS221 na Rev 1, HS3003 na Rev 2) partilham o mesmo barramento I²C 1 interno que o IMU:
import time
from machine import I2C, Pin
from lps22h import LPS22H
from hts221 import HTS221
bus = I2C(1, scl=Pin("P15"), sda=Pin("P14"))
lps = LPS22H(bus)
try:
hts = HTS221(bus)
except OSError:
from hs3003 import HS3003
hts = HS3003(bus)
while True:
print("pressure: %.2f hPa" % lps.pressure())
print("temperature: %.2f C" % lps.temperature())
print("humidity: %.2f %%" % hts.humidity())
time.sleep_ms(500)
Luz / cor / proximidade / gesto¶
O APDS9960 da Broadcom está no mesmo barramento I²C 1 interno e fornece deteção de luz ambiente, cor RGB, proximidade e gesto:
import time
from machine import I2C, Pin
from apds9960 import uAPDS9960 as APDS9960
bus = I2C(1, scl=Pin("P15"), sda=Pin("P14"))
apds = APDS9960(bus)
apds.enableLightSensor()
while True:
print("ambient light:", apds.readAmbientLight())
time.sleep_ms(250)
Microfone¶
O microfone PDM MP34DT05 integrado é capturado através de audio — Módulo de Áudio. Cada buffer chega como PCM de 16 bits com sinal em bytearray, pronto para alimentar ulab/numpy para processamento DSP:
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
Bluetooth¶
O rádio Bluetooth LE 5.0 do nRF52840 funciona com o Nordic SoftDevice s140 e é exposto através do módulo legacy ubluepy — as APIs modernas bluetooth / aioble — BLE Assíncrono não estão ativadas nesta compilação. Estão disponíveis os papéis de periférico (servidor GATT, advertise) e central (observador/scanner GAP + ligar).
Anuncie como periférico com um único serviço de Monitorização Ambiental e uma característica de temperatura com notificação — o callback event_handler é acionado em ligação, desligação e escritas no CCCD:
from ubluepy import Service, Characteristic, UUID, Peripheral, constants
from machine import LED
def event_handler(event_id, handle, data):
if event_id == constants.EVT_GAP_CONNECTED:
LED("LED_GREEN").on()
elif event_id == constants.EVT_GAP_DISCONNECTED:
LED("LED_GREEN").off()
periph.advertise(device_name="Nano 33", services=[svc])
svc = Service(UUID("181A")) # Environmental Sensing
char = Characteristic(UUID("2A6E"), # Temperature
props=Characteristic.PROP_NOTIFY | Characteristic.PROP_READ,
attrs=Characteristic.ATTR_CCCD)
svc.addCharacteristic(char)
periph = Peripheral()
periph.addService(svc)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33", services=[svc])
Pesquise dispositivos de anúncio próximos no papel central:
from ubluepy import Scanner
for entry in Scanner().scan(1_000): # 1 second window
print(entry.addr(), entry.rssi(), "dBm")
Consulte a referência ubluepy para a API completa — UUID, Service, Characteristic, Peripheral, Scanner, ScanEntry, e o espaço de nomes constants.
Referência de barramentos¶
GPIO¶
Use machine.Pin para ler ou controlar qualquer um dos pinos marcados na serigrafía. As saídas são CMOS a 3,3 V — 15 mA por pino, 25 mA no total em todos os 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())
Qualquer pino de entrada pode também disparar uma interrupção em transições de flanco:
def handler(pin):
print("triggered:", pin)
Pin("D3", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Barramento |
TX |
RX |
|---|---|---|
UART1 |
TX |
RX |
Use os nomes da serigrafía TX/RX com machine.UART
from machine import UART
uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)
I²C¶
Barramento |
SDA |
SCL |
|---|---|---|
I2C0 |
|
|
I2C1 |
|
|
Ambos os barramentos requerem que os seus pinos sejam passados explicitamente para machine.I2C
from machine import I2C, Pin
bus0 = I2C(0, scl=Pin("I2C_SCL"), sda=Pin("I2C_SDA"), freq=400_000)
bus0.scan()
bus1 = I2C(1, scl=Pin("P15"), sda=Pin("P14"), freq=400_000)
bus1.scan()
Nota
O Barramento 1 é o barramento interno de sensores em P14/P15 (não nos headers de utilizador) — serve o IMU, barómetro, sensor ambiental e APDS9960. Os controladores frozen de sensores utilizam-no diretamente; o código de utilizador também pode analisá-lo, mas os endereços já estão ocupados pelos sensores integrados.
SPI¶
Barramento |
MOSI |
MISO |
SCK |
CS |
|---|---|---|---|---|
SPI0 |
D11 |
D12 |
D13 |
D10 |
A linha CS não é controlada pelo periférico SPI — configure D10 como saída e alterne-a manualmente em torno da transferência:
from machine import SPI, Pin
spi = SPI(0, baudrate=10_000_000)
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 também funciona como o LED_BUILTIN laranja — operar SPI neste barramento fará piscar o LED em sincronia com o relógio do barramento.
ADC¶
O nRF52840 tem oito canais ADC de 12 bits (SAADC) expostos em A0–A7, todos referenciados a 3,3 V — read_u16 devolve 0–65535 para 0–3,3 V no pino. O pino AREF da placa não está ligado, pelo que a referência é sempre 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¶
O nRF52840 expõe quatro periféricos PWM (PWM0–PWM3), cada um a controlar quatro canais, para um total de 16 slots de hardware PWM. Ao contrário das portas de função fixa, os periféricos são encaminhados através da matriz GPIOTE — qualquer GPIO pode ser uma saída PWM, pelo que não existe mapeamento pino-para-fatia. O custo dessa flexibilidade são duas restrições incorporadas no silício:
Todos os quatro canais dentro de um módulo partilham um único período/frequência.
Cada canal tem o seu próprio ciclo de trabalho e polaridade.
Conceptualmente, os 16 slots têm o seguinte aspeto:
Módulo |
Ch 0 |
Ch 1 |
Ch 2 |
Ch 3 |
|---|---|---|---|---|
PWM0 |
duty |
duty |
duty |
duty |
PWM1 |
duty |
duty |
duty |
duty |
PWM2 |
duty |
duty |
duty |
duty |
PWM3 |
duty |
duty |
duty |
duty |
Cada linha funciona a uma frequência; as quatro células numa linha controlam cada uma um pino escolhido independentemente com o seu próprio ciclo de trabalho. Linhas diferentes podem funcionar a frequências completamente diferentes.
Controle qualquer pino marcado na serigrafía (ou os LEDs integrados) através de machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("D3"), freq=1_000, duty_u16=32768)
Aviso
A alocação automática consome um módulo inteiro por chamada. Quando cria um PWM sem os kwargs device=/channel=, o controlador ocupa o primeiro módulo livre e liga o seu pino apenas ao seu canal 0. Os três canais restantes desse módulo ficam inativos e só são acessíveis através de device=/channel= explícitos. Isso limita as chamadas PWM(Pin(...)) sem assistência a quatro antes de o controlador lançar ValueError: all PWM devices in use — mesmo que doze slots estejam tecnicamente ainda livres.
Para usar mais de quatro PWMs, ou para deliberadamente partilhar uma frequência entre pinos, passe device (0–3) e channel (0–3):
# Two PWMs on the same module → forced to share frequency,
# but each gets its own duty cycle.
pwm_a = PWM(Pin("D3"), device=0, channel=0,
freq=1_000, duty_u16=32768)
pwm_b = PWM(Pin("D5"), device=0, channel=1,
freq=1_000, duty_u16=16384)
# A third PWM on a separate module, free to pick any frequency.
pwm_c = PWM(Pin("D6"), device=1, channel=0,
freq=20_000, duty_u16=49152)
O ciclo de trabalho aceita duty (0–100%), duty_u16 (0–65535), ou duty_ns. Adicione invert=1 para inverter a polaridade de saída (útil para o LED RGB ativo em nível baixo).
Nota
Como a frequência é uma propriedade por módulo, chamar pwm.freq(new_freq) em qualquer canal de um módulo volta a executar nrfx_pwm_init para o módulo inteiro e altera a frequência vista por todos os outros canais que o partilham.
Nota
As frequências permitidas abrangem aproximadamente 4 Hz a 5,3 MHz, derivadas do relógio base de 16 MHz com prescalers 1/2/4/8/16/32/64/128 e um contador de período de 15 bits. O controlador escolhe automaticamente o divisor mais próximo — freq() reporta o valor pedido, não o valor exato alcançável.
Barramentos implementados por software¶
machine.SoftI2C e machine.SoftSPI funcionam em qualquer GPIO se precisar de um barramento extra.
Sensor térmico (externo)¶
O firmware inclui o controlador fir — driver de sensor térmico (fir == infravermelho longínquo) para imagers térmicos ligados externamente:
MLX90621 — matriz IR de 16 × 4
MLX90640 — matriz IR de 32 × 24
MLX90641 — matriz IR de 16 × 12
AMG8833 — matriz IR de 8 × 8
Ligue o módulo ao barramento I²C da placa e leia fotogramas com 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())
O controlador fir comunica com o sensor apenas através de I²C 0 — ligue o módulo aos pads I2C_SCL / I2C_SDA (A5 / A4).
Temporização¶
time¶
O módulo time cobre atrasos bloqueantes, ticks monotónicos e medição de tempo decorrido:
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 virtuais¶
machine.Timer agenda callbacks periódicos ou de disparo único sem consumir um slot de temporizador de hardware. Passe -1 como id para usar um temporizador virtual (por 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"))
Os valores de período estão em milissegundos. Chame deinit() para parar e libertar o slot.
Relógio em tempo real¶
machine.RTC mantém a hora do relógio de parede entre reinicializações. O RTC do nRF52840 está ligado ao oscilador interno e não sobrevive a perda total de alimentação — defina a hora em cada arranque a frio se for importante para a sua aplicação:
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 a placa se a aplicação ficar suspensa. Uma vez iniciado, não pode ser parado nem reconfigurado — alimente-o periodicamente dentro do seu ciclo principal:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
Informação de arranque e tempo de execução¶
Atualização de firmware¶
O Nano 33 BLE Sense utiliza o duplo toque de reset padrão da Arduino para entrar no bootloader da Arduino. Prima rapidamente o botão RESET duas vezes — a placa entra em modo bootloader e o OpenMV IDE pode flashar uma nova imagem de firmware.
Um script em execução pode voltar a entrar no bootloader a pedido chamando machine.bootloader()
import machine
machine.bootloader()
Sistema de ficheiros e ordem de arranque¶
O firmware do Nano 33 BLE Sense monta um único sistema de ficheiros no arranque:
Flash interna — sempre montada em
/flashe usada como diretório de trabalho. Contémmain.pyeREADME.txtpor defeito; criada no primeiro arranque.
Após a montagem, o interpretador executa scripts de /flash:
boot.pyé executado em cada reset suave.main.pyé executado apenas no arranque a frio, imediatamente apósboot.py.
O main.py padrão fornecido numa placa recém-flashada apenas faz piscar o canal azul do LED RGB de utilizador como sinal de vida (dois pulsos curtos, pausa curta), para que possa confirmar que o firmware arrancou corretamente sem qualquer dispositivo anfitrião ligado.
/flash não está exposta como unidade de armazenamento em massa USB nesta placa.
Tamanhos de armazenamento¶
O Nano 33 BLE Sense é fornecido com:
/flash— sistema de ficheiros FAT de 64 KB, leitura/escrita.
A compilação do Nano 33 BLE Sense não inclui uma ROMFS; distribua módulos Python diretamente em /flash.
Bibliotecas de software¶
Consulte o índice de bibliotecas para a lista completa de módulos — incluindo quais são exclusivos da compilação do Nano 33 BLE Sense.