Arduino Nano 33 BLE Sense

警告

本開發板已不再受支援。 Arduino Nano 33 BLE Sense 的最後一個 OpenMV 韌體版本為 4.7.0。此目標將不會再發布任何後續的韌體更新、錯誤修正或新功能。以下資訊是為仍在執行 4.7.0 或更早版本的使用者所保留。

Arduino Nano 33 BLE Sense 是一塊 45 × 18 mm 的 Arduino-Nano 外形規格開發板,以 Nordic Semiconductor 的 nRF52840 為核心——這是一顆單核心 ARM Cortex-M4,內建 FPU,執行時脈為 64 MHz,具有 256 KB 內部 SRAM 與 1 MB 內部快閃記憶體。BLE 來自晶片內建的無線電,而開發板上搭載了 9 軸 IMU、一顆 LPS22HB 氣壓計、一顆 HTS221 / HS3003 溫濕度感測器、一顆 APDS9960 環境光/色彩/接近/手勢感測器,以及一顆 MP34DT05 PDM 麥克風。OpenMV 韌體可從 MicroPython 驅動上述所有元件。

Arduino Nano 33 BLE Sense

完整的資料手冊、照片與尺寸請參閱 Arduino Nano 33 BLE Rev2 產品頁面

重點特色

  • Nordic nRF52840 Cortex-M4,內建 FPU,時脈 64 MHz,具有 256 KB 內部 SRAM1 MB 內部快閃記憶體

  • Bluetooth LE 5.0,透過晶片內建無線電與 Nordic SoftDevice s140 提供。

  • 9 軸 IMU——Rev 1 為 LSM9DS1,Rev 2 為 BMI270 + BMM150。凍結的 imu 驅動程式會在開機時偵測這兩種配置。

  • LPS22HB 氣壓計、HTS221 / HS3003 溫濕度感測器、APDS9960 環境光/色彩/接近/手勢感測器,以及 MP34DT05 PDM 麥克風。

  • Micro USB 連接器,用於供電、燒錄程式與 CDC REPL。

  • 標準 Nano 排針上的 22 支使用者 I/O 接腳——TX/RXD2D13(數位)、A0A7(類比)。

接腳圖

Arduino Nano 33 BLE Sense 接腳圖

接腳參考

接腳名稱

參考

功能

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

按下板上的 RESET 按鈕或拉至 GND 以重置

LED_BUILTIN

位於 D13 上的橘色使用者 LED

LED_RED

RGB LED 紅色通道(低電位有效)

LED_GREEN

RGB LED 綠色通道(低電位有效)

LED_BLUE

RGB LED 藍色通道(低電位有效)

警告

Nano 33 BLE Sense 的 I/O 接腳僅支援 3.3 V——它們不耐受 5 V。將 5 V 灌入這些接腳會損壞 nRF52840。

電源接腳

  • VIN——4.5 – 21 V 輸入。透過板上的穩壓器為開發板供電。同時也經由二極體從 USB 5 V 電源軌饋入,因此 USB 與 VIN 可以同時存在而不會互相反向灌電。

  • +5V——預設未連接。

  • +3V3——3.3 V 穩壓器輸出。

  • AREF——類比參考接腳。在此開發板上並未連接到 nRF52840——ADC 永遠以 3.3 V 為參考。

  • GND——共同接地。

Nano 33 BLE Sense 可透過以下任一路徑供電:

  • Micro USB——提供 5 V 給板上的穩壓器。

  • VIN 接腳——輸入經穩壓的 4.5 – 21 V 電源。

備註

開發板底部標示為 VUSB 的焊接跳線會將 +5V 橋接至 USB 5 V 電源軌。將其短接後,+5V 排針接腳才會實際輸出 5 V。

備註

板上 4.5–21 V 切換式穩壓器輸出端有一個常閉的焊接跳線,可將其切斷以停用穩壓器,如此開發板便能直接由 +3V3 上的外部 3.3 V 電源供電。

復原與除錯接腳

  • RESET——板子頂部同時有一個外露焊盤與一個瞬時 RESET 按鈕,兩者皆連到 nRF52840 的重置線。拉至 GND 或按下按鈕即可重置。

Nano 33 BLE Sense 使用 Arduino 標準的連按兩下重置來進入 Arduino 的開機載入程式。快速按兩下 RESET 按鈕——開發板便會進入開機載入程式模式,OpenMV IDE 即可燒錄新的韌體映像。

nRF52840 的 SWD 訊號外露於開發板背面的鍍層焊盤上。所有除錯訊號皆以 3.3 V 為參考

板載周邊裝置

LED

Nano 33 BLE Sense 具有一顆使用者 RGB LED——透過絲印的 LED_REDLED_GREENLED_BLUE 通道驅動——外加位於 D13 上一顆獨立的橘色 LED_BUILTIN。這四者皆可透過 machine.LED 以軟體控制:

from machine import LED

LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
LED("LED_BUILTIN").on()

開發板上另有一顆獨立的綠色電源 LED,只要 +3.3 V 電源軌有電就會亮起,且無法由使用者控制。

相機感測器

Nano 33 BLE Sense 上的 OpenMV 韌體支援 OmniVision OV7670 並列式 CMOS 感測器。開發板本身沒有板載影像感測器——請將 OV7670 模組接到下列絲印的排針接腳上,並透過 csi --- 相機感測器 模組驅動它:

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()

備註

OV7670 需要 14 支接腳。韌體按下列方式進行接線:

感測器訊號

Nano 33 BLE Sense 接腳

D0

D10

D1

TX

D2

RX

D3

D2

D4

D3

D5

D5

D6

D6

D7

D4

HSYNC

A1

VSYNC

D8

PXCLK

A0

MXCLK

D9

POWER

A3

RESET

A2

SCL

A5(I²C 0)

SDA

A4(I²C 0)

OV7670 的 I²C 控制匯流排與 A5/A4 上外露的外部 I²C 0 為同一條。該感測器位於 7 位元位址 0x21——當相機接線完成後,該匯流排上的使用者裝置必須避開此位址。

IMU

9 軸 IMU 透過凍結的 imu 模組對外提供,該模組會自動偵測開發板搭載的是 LSM9DS1(Rev 1)還是 BMI270 + BMM150(Rev 2),並提供統一的 imu.IMU 類別。這些感測器位於內部 I²C 1 匯流排(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)

若要直接存取諸如敲擊偵測或 FIFO 等功能,請匯入對應的凍結驅動程式(lsm9ds1bmi270bmm150),並在同一條匯流排上將其實體化。

環境感測器

氣壓計(LPS22HB)與溫濕度感測器(Rev 1 為 HTS221,Rev 2 為 HS3003)與 IMU 共用同一條內部 I²C 1 匯流排:

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)

光/色彩/接近/手勢

Broadcom 的 APDS9960 位於同一條內部 I²C 1 匯流排上,提供環境光、RGB 色彩、接近與手勢感測功能:

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)

麥克風

板上的 MP34DT05 PDM 麥克風透過 audio --- 音訊模組 擷取。每個緩衝區皆以帶符號 16 位元 PCM bytearray 形式抵達,可直接饋入 ulab/numpy 進行 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

nRF52840 的 Bluetooth LE 5.0 無線電執行於 Nordic SoftDevice s140 之上,並透過舊版的 ubluepy 模組對外提供——此版本並未啟用較新的 bluetooth / aioble --- 非同步 BLE API。周邊裝置(GATT 伺服器、廣播)與中央裝置(GAP 觀察者/掃描器 + 連線)角色皆可使用。

以周邊裝置角色廣播,提供單一的 Environmental Sensing 服務與一個可通知的溫度特徵值——event_handler 回呼函式會在連線、斷線與 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])

以中央裝置角色掃描附近正在廣播的裝置:

from ubluepy import Scanner

for entry in Scanner().scan(1_000):                  # 1 second window
    print(entry.addr(), entry.rssi(), "dBm")

完整的 API 請參閱 ubluepy 參考文件——UUIDServiceCharacteristicPeripheralScannerScanEntry,以及 constants 命名空間。

匯流排參考

GPIO

使用 machine.Pin 來讀取或驅動任何絲印的接腳。輸出為 3.3 V CMOS——每支接腳 15 mA,所有 GPIO 合計 25 mA。

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())

任何輸入接腳也可在邊緣轉態時觸發中斷:

def handler(pin):
    print("triggered:", pin)

Pin("D3", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

匯流排

TX

RX

UART1

TX

RX

搭配 machine.UART 使用絲印名稱 TX/RX:

from machine import UART

uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)

I²C

匯流排

SDA

SCL

I2C0

I2C_SDA / A4

I2C_SCL / A5

I2C1

P14

P15

這兩條匯流排都需要將其接腳明確傳遞給 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()

備註

匯流排 1 是位於 P14/P15 上的內部感測器匯流排(不在使用者排針上)——它服務於 IMU、氣壓計、環境感測器與 APDS9960。凍結的感測器驅動程式會直接使用它;使用者程式碼也可以掃描它,但這些位址已被板載感測器佔用。

SPI

匯流排

MOSI

MISO

SCK

CS

SPI0

D11

D12

D13

D10

CS 線並非由 SPI 周邊裝置驅動——請將 D10 設定為輸出,並在傳輸前後手動切換它:

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)

備註

D13 同時兼作橘色的 LED_BUILTIN——在此匯流排上驅動 SPI 會使該 LED 隨著匯流排時脈閃爍。

ADC

nRF52840 具有八個 12 位元 ADC 通道(SAADC),外露於 A0–A7 上,全部皆以 3.3 V 為參考——read_u16 會在接腳的 0–3.3 V 範圍內回傳 0–65535。開發板的 AREF 接腳未接線,因此參考永遠是 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

nRF52840 外露了四個 PWM 周邊裝置PWM0PWM3),每個驅動四個通道,總共構成 16 個硬體 PWM 槽位。與固定功能的連接埠不同,這些周邊裝置是透過 GPIOTE 矩陣繞送的——任何 GPIO 都可以是 PWM 輸出,因此不存在接腳對切片的固定對應。這份彈性的代價是矽晶片中內建的兩項限制:

  • 同一模組內的所有四個通道共用單一的週期/頻率

  • 每個通道都有各自的工作週期與極性。

在概念上,這 16 個槽位看起來像這樣:

模組

Ch 0

Ch 1

Ch 2

Ch 3

PWM0

工作週期

工作週期

工作週期

工作週期

PWM1

工作週期

工作週期

工作週期

工作週期

PWM2

工作週期

工作週期

工作週期

工作週期

PWM3

工作週期

工作週期

工作週期

工作週期

每一列以同一個頻率執行;一列中的四格各自驅動一支獨立選定的接腳,並擁有自己的工作週期。不同的列可以以完全不同的頻率執行。

透過 machine.PWM 驅動任何絲印的接腳(或板載 LED):

from machine import Pin, PWM

pwm = PWM(Pin("D3"), freq=1_000, duty_u16=32768)

警告

每次呼叫進行自動配置時都會消耗一整個模組。 當你在不帶 device=/channel= 關鍵字引數的情況下建立 PWM 時,驅動程式會抓取第一個空閒的模組,並僅將你的接腳繫結到其通道 0。該模組剩下的三個通道會閒置,且只能透過明確的 device=/channel= 才能存取。這使得未經輔助的 PWM(Pin(...)) 呼叫在驅動程式拋出 ValueError: all PWM devices in use 之前,最多只能進行 次——即便技術上仍有十二個槽位是空閒的。

若要使用超過四個 PWM,或刻意讓多支接腳共用同一頻率,請傳入 device(0–3)與 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)

工作週期接受 duty(0–100%)、duty_u16(0–65535)或 duty_ns。加上 invert=1 可翻轉輸出極性(對低電位有效的 RGB LED 很方便)。

備註

由於頻率是每個模組的屬性,在某個模組的任一通道上呼叫 pwm.freq(new_freq) 都會為整個模組重新執行 nrfx_pwm_init,並改變共用該模組的其他每個通道所看到的頻率。

備註

允許的頻率範圍大約為 4 Hz 到 5.3 MHz,由 16 MHz 基礎時脈搭配 1/2/4/8/16/32/64/128 的預除頻器與一個 15 位元的週期計數器衍生而來。驅動程式會自動挑選最接近的除數——freq() 回報的是請求的值,而非實際能達到的精確值。

軟體位元模擬匯流排

如果你需要額外的匯流排,machine.SoftI2Cmachine.SoftSPI 可在任何 GPIO 上運作。

熱感測器(外接)

韌體包含 fir --- 熱感測器驅動程式 (fir == far infrared,遠紅外線) 驅動程式,可用於外接接線的熱成像儀:

  • MLX90621——16 × 4 紅外線陣列

  • MLX90640——32 × 24 紅外線陣列

  • MLX90641——16 × 12 紅外線陣列

  • AMG8833——8 × 8 紅外線陣列

將模組接到開發板的 I²C 匯流排,並以 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())

fir 驅動程式僅透過 I²C 0 與感測器通訊——請將模組接到 I2C_SCL / I2C_SDA 焊盤(A5 / A4)。

計時

time

time 模組涵蓋阻塞式延遲、單調遞增的計時刻度,以及經過時間的量測:

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)

虛擬計時器

machine.Timer 可在不佔用硬體計時器槽位的情況下排程週期性或單次的回呼函式。將 -1 作為 id 傳入即可使用虛擬(軟體)計時器:

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"))

週期值的單位為毫秒。呼叫 deinit() 可停止並釋放槽位。

即時時鐘

machine.RTC 可在多次重置之間維持實際時間。nRF52840 的 RTC 連接到晶片內建振盪器,無法在完全斷電後保留——如果這對你的應用很重要,請在每次冷開機時都設定一次時間:

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())

看門狗

如果應用程式當機,machine.WDT 會重置開發板。一旦啟動,它就無法停止或重新設定——請在主迴圈中定期餵食它:

from machine import WDT

wdt = WDT(timeout=5_000)   # 5 second window
while True:
    # ...do work...
    wdt.feed()

開機與執行階段資訊

韌體更新

Nano 33 BLE Sense 使用 Arduino 標準的連按兩下重置來進入 Arduino 的開機載入程式。快速按兩下 RESET 按鈕——開發板便會進入開機載入程式模式,OpenMV IDE 即可燒錄新的韌體映像。

執行中的指令碼可透過呼叫 machine.bootloader() 隨時重新進入開機載入程式:

import machine

machine.bootloader()

檔案系統與開機順序

Nano 33 BLE Sense 韌體在開機時會掛載單一個檔案系統:

  • 內部快閃記憶體——永遠掛載於 /flash,並作為工作目錄使用。預設存放 main.pyREADME.txt;於最初次開機時建立。

掛載完成後,直譯器接著會從 /flash 執行指令碼:

  • boot.py 會在每一次軟重置時執行。

  • main.py 僅在冷開機時執行,緊接在 boot.py 之後。

全新燒錄的開發板上隨附的預設 main.py 只會將使用者 RGB LED 的藍色通道作為心跳閃爍(兩次短脈衝、短暫間隔),讓你在不連接任何主機的情況下就能判斷韌體是否乾淨地開機。

在此開發板上,/flash 不會以 USB 大容量儲存裝置的形式對外提供。

儲存空間大小

Nano 33 BLE Sense 出廠時隨附:

  • /flash——64 KB FAT 檔案系統,可讀寫。

Nano 33 BLE Sense 的版本不包含 ROMFS;請直接將 Python 模組放在 /flash 上。

軟體程式庫

完整的模組清單請參閱 程式庫索引——包括哪些模組是 Nano 33 BLE Sense 版本所獨有的。