Arduino Nano 33 BLE Sense

Varning

Detta kort stöds inte längre. Den sista OpenMV-firmware-utgåvan för Arduino Nano 33 BLE Sense är 4.7.0. Inga ytterligare firmware-uppdateringar, buggfixar eller nya funktioner kommer att släppas för detta mål. Informationen nedan bevaras för användare som kör 4.7.0 eller tidigare.

Arduino Nano 33 BLE Sense är ett 45 × 18 mm kort i Arduino-Nano-formfaktor byggt kring Nordic Semiconductors nRF52840 — en enkel ARM Cortex‑M4 med FPU som kör på 64 MHz med 256 KB internt SRAM och 1 MB internt flashminne. BLE kommer från radion på chipet, och kortet bär en 9‑axlig IMU, en LPS22HB barometer, en HTS221 / HS3003 temperatur‑ / fuktsensor, en APDS9960 sensor för omgivningsljus / färg / närhet / gester och en MP34DT05 PDM-mikrofon. OpenMV-firmware driver alla dessa från MicroPython.

Arduino Nano 33 BLE Sense

För fullständigt datablad, foton och dimensioner, se produktsidan för Arduino Nano 33 BLE Rev2.

Höjdpunkter

  • Nordic nRF52840 Cortex‑M4 med FPU på 64 MHz med 256 KB internt SRAM och 1 MB internt flashminne.

  • Bluetooth LE 5.0 via radion på chipet och Nordic SoftDevice s140.

  • 9‑axlig IMULSM9DS1 på Rev 1, BMI270 + BMM150 på Rev 2. Den infrysta imu-drivrutinen avsöker båda vid uppstart.

  • LPS22HB barometer, HTS221 / HS3003 temperatur‑ och fuktsensor, APDS9960 sensor för omgivningsljus / färg / närhet / gester och MP34DT05 PDM-mikrofon.

  • Micro USB-kontakt för ström, programmering och en CDC-REPL.

  • 22 användar-I/O-stift på standard-Nano-anslutningarna — TX/RX, D2D13 (digitala), A0A7 (analoga).

Stiftkonfiguration

Stiftkonfiguration för Arduino Nano 33 BLE Sense

Stiftreferens

Stiftnamn

Referens

Funktion

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

tryck på RESET-knappen på kortet eller dra till GND för att återställa

LED_BUILTIN

Orange användar-LED på D13

LED_RED

Röd kanal på RGB-LED (aktiv låg)

LED_GREEN

Grön kanal på RGB-LED (aktiv låg)

LED_BLUE

Blå kanal på RGB-LED (aktiv låg)

Varning

I/O-stiften på Nano 33 BLE Sense är endast 3,3 V — de är inte 5 V-toleranta. Att driva 5 V in i dem skadar nRF52840.

Strömstift

  • VIN — 4,5 – 21 V ingång. Driver kortet genom regulatorn på kortet. Matas även via en diod från USB:s 5 V-skena, så USB och VIN kan vara närvarande samtidigt utan att backmata varandra.

  • +5V — inte ansluten som standard.

  • +3V3 — utgång från 3,3 V-regulatorn.

  • AREF — analog referensstift. Inte kopplad till nRF52840 på detta kort — ADC:n refereras alltid till 3,3 V.

  • GND — gemensam jord.

Nano 33 BLE Sense kan drivas via endera vägen:

  • Micro USB — levererar 5 V till regulatorn på kortet.

  • VIN-stift — driv en reglerad matning på 4,5 – 21 V.

Anteckning

En lödbygel på kortets undersida märkt VUSB bryggar +5V till USB:s 5 V-skena. Stäng den för att få +5V-anslutningsstiftet att faktiskt bära 5 V.

Anteckning

En normalt sluten lödbygel på utgången från kortets switchade 4,5–21 V-regulator kan klippas för att inaktivera regulatorn, så att kortet kan drivas direkt från en extern 3,3 V-matning på +3V3.

Stift för återställning och felsökning

  • RESET — både en exponerad kontaktyta och en momentan RESET-knapp på kortets ovansida, kopplade till nRF52840:s återställningslinje. Dra till GND eller tryck på knappen för att återställa.

Nano 33 BLE Sense använder Arduinos standardmetod dubbeltryck-återställning för att gå in i Arduinos startladdare. Tryck snabbt på RESET-knappen två gånger — kortet går in i startladdarläge och OpenMV IDE kan flasha en ny firmware-image.

nRF52840:s SWD-signaler är exponerade på pläterade kontaktytor på kortets baksida. Alla felsökningssignaler är 3,3 V-refererade.

Kringutrustning på kortet

LED-lampor

Nano 33 BLE Sense har en användar-RGB-LED — driven via de silktryckta kanalerna LED_RED, LED_GREEN och LED_BLUE — plus en separat orange LED_BUILTIND13. Alla fyra är programstyrbara via machine.LED

from machine import LED

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

En separat grön ström-LED på kortet lyser närhelst +3,3 V-skenan är uppe och är inte användarstyrbar.

Kamerasensor

OpenMV-firmware på Nano 33 BLE Sense stöder den parallella CMOS-sensorn OmniVision OV7670. Kortet har ingen bildsensor på kortet — koppla en OV7670-modul till de silktryckta anslutningsstiften som listas nedan och driv den via modulen csi — kamerasensorer

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

Anteckning

OV7670 tar 14 stift. Firmware kopplar dem enligt följande:

Sensorsignal

Nano 33 BLE Sense-stift

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:s I²C-styrbuss är samma externa I²C 0 som exponeras på A5/A4. Sensorn sitter på 7‑bitarsadressen 0x21 — användarenheter på den bussen måste undvika denna adress när kameran är inkopplad.

IMU

Den 9‑axliga IMU:n exponeras via den infrysta imu-modulen, som automatiskt detekterar om kortet har LSM9DS1 (Rev 1) eller BMI270 + BMM150 (Rev 2) och presenterar en enhetlig imu.IMU-klass. Sensorerna sitter på den interna I²C 1-bussen (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)

För direkt åtkomst till funktioner som tryckdetektering eller FIFO:n, importera den matchande infrysta drivrutinen (lsm9ds1, bmi270 eller bmm150) och instansiera den på samma buss.

Miljösensorer

Barometern (LPS22HB) och temperatur‑ / fuktsensorn (HTS221 på Rev 1, HS3003 på Rev 2) delar samma interna I²C 1-buss som IMU:n:

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)

Ljus / färg / närhet / gester

Broadcoms APDS9960 sitter på samma interna I²C 1-buss och tillhandahåller avkänning av omgivningsljus, RGB-färg, närhet och gester:

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)

Mikrofon

MP34DT05 PDM-mikrofonen på kortet fångas via audio — Ljudmodul. Varje buffert anländer som signerad 16‑bitars PCM bytearray, redo att matas in i ulab/numpy för 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:s Bluetooth LE 5.0-radio körs på Nordic SoftDevice s140 och exponeras via den äldre ubluepy-modulen — de moderna API:erna bluetooth / aioble — Asynkron BLE är inte aktiverade i denna build. Både peripheral-rollen (GATT-server, annonsering) och central-rollen (GAP-observatör / scanner + anslut) är tillgängliga.

Annonsera som en peripheral med en enda Environmental Sensing-tjänst och en notifierbar temperaturkarakteristik — återanropet event_handler aktiveras vid anslutning, frånkoppling och CCCD-skrivningar:

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

Skanna efter närliggande annonserande enheter i central-rollen:

from ubluepy import Scanner

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

Se ubluepy-referensen för det fullständiga API:et — UUID, Service, Characteristic, Peripheral, Scanner, ScanEntry och namnrymden constants.

Bussreferens

GPIO

Använd machine.Pin för att läsa eller driva något av de silktryckta stiften. Utgångar är 3,3 V CMOS — 15 mA per stift, 25 mA totalt över alla GPIO:er.

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

Vilket ingångsstift som helst kan även utlösa ett avbrott vid kantövergångar:

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

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

UART

Buss

TX

RX

UART1

TX

RX

Använd silktrycksnamnen TX/RX med machine.UART

from machine import UART

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

I²C

Buss

SDA

SCL

I2C0

I2C_SDA / A4

I2C_SCL / A5

I2C1

P14

P15

Båda bussarna behöver få sina stift uttryckligen angivna till 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()

Anteckning

Buss 1 är den interna sensorbussen på P14/P15 (inte på användaranslutningarna) — den betjänar IMU:n, barometern, miljösensorn och APDS9960. De infrysta sensordrivrutinerna använder den direkt; användarkod kan också skanna den men adresserna är redan upptagna av sensorerna på kortet.

SPI

Buss

MOSI

MISO

SCK

CS

SPI0

D11

D12

D13

D10

CS-linjen drivs inte av SPI-kringutrustningen — konfigurera D10 som en utgång och växla den manuellt runt överföringen:

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)

Anteckning

D13 fungerar också som den orange LED_BUILTIN — att driva SPI på denna buss får LED:en att blinka i takt med bussklockan.

ADC

nRF52840 har åtta 12‑bitars ADC-kanaler (SAADC) exponerade på A0–A7, alla 3,3 V-refereraderead_u16 returnerar 0–65535 över 0–3,3 V vid stiftet. Kortets AREF-stift är inte kopplat, så referensen är alltid 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 exponerar fyra PWM-kringutrustningar (PWM0PWM3), som var och en driver fyra kanaler, för totalt 16 hårdvaru-PWM-platser. Till skillnad från portar med fast funktion routas kringutrustningarna genom GPIOTE-matrisen — vilken GPIO som helst kan vara en PWM-utgång, så det finns ingen mappning från stift till skiva. Priset för den flexibiliteten är två begränsningar inbakade i kislet:

  • Alla fyra kanaler inuti en modul delar en enda period/frekvens.

  • Varje kanal har sin egen pulskvot och polaritet.

Konceptuellt ser de 16 platserna ut så här:

Modul

Ka 0

Ka 1

Ka 2

Ka 3

PWM0

pulskvot

pulskvot

pulskvot

pulskvot

PWM1

pulskvot

pulskvot

pulskvot

pulskvot

PWM2

pulskvot

pulskvot

pulskvot

pulskvot

PWM3

pulskvot

pulskvot

pulskvot

pulskvot

Varje rad körs på en frekvens; de fyra cellerna i en rad driver var och en ett oberoende valt stift med sin egen pulskvot. Olika rader kan köras på helt olika frekvenser.

Driv vilket silktryckt stift som helst (eller LED:erna på kortet) via machine.PWM

from machine import Pin, PWM

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

Varning

Automatisk allokering förbrukar en hel modul per anrop. När du skapar en PWM utan nyckelorden device=/channel= tar drivrutinen den första lediga modulen och binder ditt stift enbart till dess kanal 0. De återstående tre kanalerna i den modulen ligger oanvända och är endast nåbara via uttryckliga device=/channel=. Detta begränsar oassisterade PWM(Pin(...))-anrop till fyra innan drivrutinen kastar ValueError: all PWM devices in use — även om tolv platser tekniskt sett fortfarande är lediga.

För att använda fler än fyra PWM:er, eller för att avsiktligt dela en frekvens över stift, ange device (0–3) och 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)

Pulskvot accepterar duty (0–100 %), duty_u16 (0–65535) eller duty_ns. Lägg till invert=1 för att vända utgångens polaritet (praktiskt för den aktiv-låga RGB-LED:en).

Anteckning

Eftersom frekvens är en egenskap per modul kommer anrop av pwm.freq(new_freq)vilken kanal som helst i en modul att köra om nrfx_pwm_init för hela modulen och ändra frekvensen som ses av varje annan kanal som delar den.

Anteckning

Tillåtna frekvenser sträcker sig grovt från 4 Hz till 5,3 MHz, härledda från basklockan på 16 MHz med förskalare 1/2/4/8/16/32/64/128 och en 15‑bitars periodräknare. Drivrutinen väljer automatiskt närmaste delare — freq() rapporterar det begärda värdet, inte det exakt uppnåeliga.

Programvarustyrda bit-bangade bussar

machine.SoftI2C och machine.SoftSPI fungerar på vilken GPIO som helst om du behöver en extra buss.

Värmesensor (utanför kortet)

Firmware inkluderar drivrutinen fir — drivrutin för värmesensor (fir == far infrared) för externt kopplade värmekameror:

  • MLX90621 — 16 × 4 IR-matris

  • MLX90640 — 32 × 24 IR-matris

  • MLX90641 — 16 × 12 IR-matris

  • AMG8833 — 8 × 8 IR-matris

Koppla modulen till kortets I²C-buss och läs bildrutor med 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-drivrutinen kommunicerar endast med sensorn över I²C 0 — koppla modulen till kontaktytorna I2C_SCL / I2C_SDA (A5 / A4).

Tidtagning

time

time-modulen täcker blockerande fördröjningar, monotona tick och mätning av förfluten tid:

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)

Virtuella timers

machine.Timer schemalägger periodiska eller engångsåteranrop utan att förbruka en hårdvarutimerplats. Ange -1 som id för att använda en virtuell (programvaru-) timer:

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

Periodvärden anges i millisekunder. Anropa deinit() för att stoppa och frigöra platsen.

Realtidsklocka

machine.RTC håller väggklockstid över återställningar. nRF52840:s RTC är knuten till oscillatorn på chipet och överlever inte fullständig strömförlust — ställ in tiden vid varje kallstart om det är viktigt för din applikation:

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

Vakthund

machine.WDT återställer kortet om applikationen hänger sig. När den väl startats kan den inte stoppas eller konfigureras om — mata den periodiskt inuti din huvudloop:

from machine import WDT

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

Uppstarts- och körtidsinformation

Firmware-uppdatering

Nano 33 BLE Sense använder Arduinos standardmetod dubbeltryck-återställning för att gå in i Arduinos startladdare. Tryck snabbt på RESET-knappen två gånger — kortet går in i startladdarläge och OpenMV IDE kan flasha en ny firmware-image.

Ett körande skript kan återgå till startladdaren på begäran genom att anropa machine.bootloader()

import machine

machine.bootloader()

Filsystem och uppstartsordning

Nano 33 BLE Sense-firmware monterar ett enda filsystem vid uppstart:

  • Internt flashminne — alltid monterat på /flash och används som arbetskatalog. Innehåller main.py och README.txt som standard; skapas vid allra första uppstarten.

Efter montering kör tolken sedan skript från /flash:

  • boot.py körs vid varje mjuk återställning.

  • main.py körs endast vid kallstart, omedelbart efter boot.py.

Standard-main.py som levereras på ett nyflashat kort blinkar bara den blå kanalen på användar-RGB-LED:en som ett hjärtslag (två korta pulser, kort paus), så att du kan se att firmware startade rent utan någon ansluten värd.

/flash exponeras inte som en USB-masslagringsenhet på detta kort.

Lagringsstorlekar

Nano 33 BLE Sense levereras med:

  • /flash64 KB FAT-filsystem, läs/skriv.

Builden för Nano 33 BLE Sense inkluderar inte något ROMFS; leverera Python-moduler direkt på /flash.

Programvarubibliotek

Se biblioteksindexet för den fullständiga listan över moduler — inklusive vilka som är unika för Nano 33 BLE Sense-builden.