Arduino Nano 33 BLE Sense

Waarschuwing

Dit board wordt niet langer ondersteund. De laatste OpenMV-firmwarerelease voor de Arduino Nano 33 BLE Sense is 4.7.0. Er worden geen verdere firmware-updates, bugfixes of nieuwe functies meer uitgebracht voor dit doel. De onderstaande informatie is bewaard gebleven voor gebruikers die 4.7.0 of eerder draaien.

De Arduino Nano 33 BLE Sense is een 45 × 18 mm board in Arduino-Nano-formfactor, gebouwd rond de Nordic Semiconductor nRF52840 — een enkele ARM Cortex‑M4 met FPU op 64 MHz met 256 KB intern SRAM en 1 MB intern flashgeheugen. BLE komt van de on‑die radio, en het board bevat een 9‑assige IMU, een LPS22HB-barometer, een HTS221 / HS3003 temperatuur- / vochtigheidssensor, een APDS9960 omgevingslicht- / kleur- / nabijheids- / gebarensensor, en een MP34DT05 PDM-microfoon. De OpenMV-firmware stuurt al deze aan vanuit MicroPython.

Arduino Nano 33 BLE Sense

Voor het volledige datasheet, foto’s en afmetingen zie de productpagina van de Arduino Nano 33 BLE Rev2.

Hoogtepunten

  • Nordic nRF52840 Cortex‑M4 met FPU op 64 MHz met 256 KB intern SRAM en 1 MB intern flashgeheugen.

  • Bluetooth LE 5.0 via de on‑die radio en de Nordic SoftDevice s140.

  • 9‑assige IMULSM9DS1 op Rev 1, BMI270 + BMM150 op Rev 2. De vastgelegde imu-driver detecteert beide bij het opstarten.

  • LPS22HB-barometer, HTS221 / HS3003 temperatuur- en vochtigheidssensor, APDS9960 omgevingslicht- / kleur- / nabijheids- / gebarensensor, en MP34DT05 PDM-microfoon.

  • Micro USB-connector voor voeding, programmeren en een CDC-REPL.

  • 22 gebruikers-I/O-pinnen op de standaard Nano-headers — TX/RX, D2D13 (digitaal), A0A7 (analoog).

Pinout

Pinout van de Arduino Nano 33 BLE Sense

Pinreferentie

Pinnaam

Referentie

Functie

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

druk op de RESET-knop op het board of trek naar GND om te resetten

LED_BUILTIN

Oranje gebruikers-LED op D13

LED_RED

Rood kanaal van de RGB-LED (actief laag)

LED_GREEN

Groen kanaal van de RGB-LED (actief laag)

LED_BLUE

Blauw kanaal van de RGB-LED (actief laag)

Waarschuwing

De I/O-pinnen van de Nano 33 BLE Sense zijn uitsluitend 3.3 V — ze zijn niet 5 V-tolerant. Het aanleggen van 5 V op deze pinnen beschadigt de nRF52840.

Voedingspinnen

  • VIN — 4.5 – 21 V ingang. Voedt het board via de regelaar op het board. Wordt ook via een diode gevoed vanaf de USB 5 V-rail, zodat USB en VIN tegelijk aanwezig kunnen zijn zonder elkaar terug te voeden.

  • +5V — standaard niet aangesloten.

  • +3V3 — uitgang van de 3.3 V-regelaar.

  • AREF — analoge referentiepin. Op dit board niet bedraad naar de nRF52840 — de ADC wordt altijd gerefereerd aan 3.3 V.

  • GND — gemeenschappelijke massa.

De Nano 33 BLE Sense kan via beide paden gevoed worden:

  • Micro USB — levert 5 V aan de regelaar op het board.

  • VIN-pin — leg een gestabiliseerde voeding van 4.5 – 21 V aan.

Notitie

Een soldeerbrug aan de onderkant van het board met het label VUSB verbindt +5V met de USB 5 V-rail. Sluit deze om de +5V-headerpin daadwerkelijk 5 V te laten voeren.

Notitie

Een normaal gesloten soldeerbrug op de uitgang van de 4.5–21 V-schakelregelaar op het board kan worden doorgesneden om de regelaar uit te schakelen, zodat het board rechtstreeks gevoed kan worden vanaf een externe 3.3 V-voeding op +3V3.

Herstel- en debugpinnen

  • RESET — zowel een blootliggende pad als een tijdelijke RESET-knop aan de bovenkant van het board, verbonden met de resetlijn van de nRF52840. Trek naar GND of druk op de knop om te resetten.

De Nano 33 BLE Sense gebruikt de standaard dubbele tik-reset van Arduino om de bootloader van Arduino te starten. Druk snel tweemaal op de RESET-knop — het board gaat in bootloadermodus en OpenMV IDE kan een nieuwe firmware-image flashen.

De SWD-signalen van de nRF52840 liggen blootliggend op vertinde pads aan de achterkant van het board. Alle debugsignalen zijn 3.3 V-gerefereerd.

Randapparaten op het board

LEDs

De Nano 33 BLE Sense heeft een RGB-gebruikers-LED — aangestuurd via de op de print gemarkeerde kanalen LED_RED, LED_GREEN en LED_BLUE — plus een aparte oranje LED_BUILTIN op D13. Alle vier zijn softwarematig bestuurbaar via machine.LED

from machine import LED

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

Een aparte groene power-LED op het board brandt zodra de +3.3 V-rail actief is en is niet door de gebruiker te besturen.

Camerasensor

De OpenMV-firmware op de Nano 33 BLE Sense ondersteunt de OmniVision OV7670 parallelle CMOS-sensor. Het board heeft geen ingebouwde beeldsensor — bedraad een OV7670-module naar de hieronder vermelde, op de print gemarkeerde headerpinnen en stuur deze aan via de csi — camerasensoren-module:

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

Notitie

De OV7670 gebruikt 14 pinnen. De firmware bedraadt ze als volgt:

Sensorsignaal

Nano 33 BLE Sense-pin

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)

De I²C-besturingsbus van de OV7670 is dezelfde externe I²C 0 die op A5/A4 is uitgevoerd. De sensor bevindt zich op het 7‑bits adres 0x21 — gebruikersapparaten op die bus moeten dit adres vermijden wanneer de camera is aangesloten.

IMU

De 9‑assige IMU wordt blootgesteld via de vastgelegde imu-module, die automatisch detecteert of het board de LSM9DS1 (Rev 1) of de BMI270 + BMM150 (Rev 2) heeft en een uniforme imu.IMU-klasse presenteert. De sensoren zitten op de interne I²C 1-bus (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)

Voor directe toegang tot functies zoals tikdetectie of de FIFO, importeer de bijbehorende vastgelegde driver (lsm9ds1, bmi270 of bmm150) en instantieer deze op dezelfde bus.

Omgevingssensoren

De barometer (LPS22HB) en de temperatuur- / vochtigheidssensor (HTS221 op Rev 1, HS3003 op Rev 2) delen dezelfde interne I²C 1-bus als de 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)

Licht / kleur / nabijheid / gebaren

De Broadcom APDS9960 zit op dezelfde interne I²C 1-bus en biedt detectie van omgevingslicht, RGB-kleur, nabijheid en gebaren:

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)

Microfoon

De MP34DT05 PDM-microfoon op het board wordt vastgelegd via audio — Audio Module. Elke buffer komt binnen als signed‑16‑bits PCM-bytearray, klaar om in te voeren in ulab/numpy voor 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

De Bluetooth LE 5.0-radio van de nRF52840 draait op de Nordic SoftDevice s140 en wordt blootgesteld via de verouderde ubluepy-module — de moderne bluetooth / aioble — Async BLE-API’s zijn niet ingeschakeld in deze build. Zowel de rol peripheral (GATT-server, adverteren) als central (GAP-observer / scanner + verbinden) zijn beschikbaar.

Adverteer als peripheral met een enkele Environmental Sensing-service en een notificeerbaar temperatuurkenmerk — de event_handler-callback wordt geactiveerd bij verbinden, verbreken en CCCD-writes:

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

Scan in central-rol naar nabijgelegen adverterende apparaten:

from ubluepy import Scanner

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

Zie de ubluepy-referentie voor de volledige API — UUID, Service, Characteristic, Peripheral, Scanner, ScanEntry, en de constants-namespace.

Busreferentie

GPIO

Gebruik machine.Pin om een van de op de print gemarkeerde pinnen te lezen of aan te sturen. Uitgangen zijn 3.3 V CMOS — 15 mA per pin, 25 mA totaal over alle GPIO’s.

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

Elke ingangspin kan ook een interrupt activeren bij flankovergangen:

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

UART1

TX

RX

Gebruik de printnamen TX/RX met machine.UART

from machine import UART

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

I²C

Bus

SDA

SCL

I2C0

I2C_SDA / A4

I2C_SCL / A5

I2C1

P14

P15

Beide bussen vereisen dat hun pinnen expliciet worden doorgegeven aan 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()

Notitie

Bus 1 is de interne sensorbus op P14/P15 (niet op de gebruikers-headers) — deze bedient de IMU, barometer, omgevingssensor en APDS9960. De vastgelegde sensordrivers gebruiken deze rechtstreeks; gebruikerscode kan deze ook scannen, maar de adressen zijn al in gebruik door de sensoren op het board.

SPI

Bus

MOSI

MISO

SCK

CS

SPI0

D11

D12

D13

D10

De CS-lijn wordt niet aangestuurd door het SPI-randapparaat — configureer D10 als uitgang en schakel deze handmatig rond de overdracht:

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)

Notitie

D13 fungeert tevens als de oranje LED_BUILTIN — het aansturen van SPI op deze bus laat de LED knipperen op het ritme van de busklok.

ADC

De nRF52840 heeft acht 12‑bits ADC-kanalen (SAADC) uitgevoerd op A0–A7, alle 3.3 V-gerefereerdread_u16 retourneert 0–65535 over 0–3.3 V op de pin. De AREF-pin van het board is niet bedraad, dus de referentie is altijd 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

De nRF52840 stelt vier PWM-randapparaten beschikbaar (PWM0PWM3), die elk vier kanalen aansturen, voor in totaal 16 hardware-PWM-slots. Anders dan bij poorten met vaste functie lopen de randapparaten via de GPIOTE-matrix — elke GPIO kan een PWM-uitgang zijn, dus er is geen pin-naar-slice-toewijzing. De prijs van die flexibiliteit zijn twee in het silicium ingebakken beperkingen:

  • Alle vier kanalen binnen een module delen een enkele periode/frequentie.

  • Elk kanaal heeft zijn eigen duty cycle en polariteit.

Conceptueel zien de 16 slots er zo uit:

Module

Kn 0

Kn 1

Kn 2

Kn 3

PWM0

duty

duty

duty

duty

PWM1

duty

duty

duty

duty

PWM2

duty

duty

duty

duty

PWM3

duty

duty

duty

duty

Elke rij draait op één frequentie; de vier cellen in een rij sturen elk een onafhankelijk gekozen pin aan met een eigen duty cycle. Verschillende rijen kunnen op volledig verschillende frequenties draaien.

Stuur een willekeurige op de print gemarkeerde pin (of de LED’s op het board) aan via machine.PWM

from machine import Pin, PWM

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

Waarschuwing

Automatische toewijzing verbruikt een hele module per aanroep. Wanneer u een PWM aanmaakt zonder de kwargs device=/channel=, pakt de driver de eerste vrije module en bindt uw pin alleen aan diens kanaal 0. De overige drie kanalen van die module blijven ongebruikt en zijn alleen bereikbaar via expliciete device=/channel=. Dat beperkt ongeholpen PWM(Pin(...))-aanroepen tot vier voordat de driver ValueError: all PWM devices in use opwerpt — ook al zijn er technisch nog twaalf slots vrij.

Om meer dan vier PWM’s te gebruiken, of om bewust een frequentie te delen over pinnen, geeft u device (0–3) en channel (0–3) door:

# 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 cycle accepteert duty (0–100%), duty_u16 (0–65535) of duty_ns. Voeg invert=1 toe om de uitgangspolariteit om te keren (handig voor de actief-lage RGB-LED).

Notitie

Omdat frequentie een eigenschap per module is, zorgt het aanroepen van pwm.freq(new_freq) op een willekeurig kanaal van een module ervoor dat nrfx_pwm_init voor de hele module opnieuw wordt uitgevoerd en de frequentie verandert die elk ander kanaal dat de module deelt waarneemt.

Notitie

Toegestane frequenties bestrijken ruwweg 4 Hz tot 5.3 MHz, afgeleid van de basisklok van 16 MHz met prescalers 1/2/4/8/16/32/64/128 en een 15‑bits periodeteller. De driver kiest automatisch de dichtstbijzijnde deler — freq() rapporteert de gevraagde waarde, niet de exact haalbare.

Softwarematig bit-banged bussen

machine.SoftI2C en machine.SoftSPI werken op elke GPIO als u een extra bus nodig hebt.

Thermische sensor (extern)

De firmware bevat de fir — thermische sensor-driver (fir == far infrared)-driver voor extern bedrade thermische beeldsensoren:

  • MLX90621 — 16 × 4 IR-array

  • MLX90640 — 32 × 24 IR-array

  • MLX90641 — 16 × 12 IR-array

  • AMG8833 — 8 × 8 IR-array

Bedraad de module naar de I²C-bus van het board en lees frames met 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())

De fir-driver communiceert alleen met de sensor via I²C 0 — bedraad de module naar de I2C_SCL / I2C_SDA-pads (A5 / A4).

Timing

time

De time-module behandelt blokkerende vertragingen, monotone ticks en het meten van verstreken tijd:

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)

Virtuele timers

machine.Timer plant periodieke of eenmalige callbacks zonder een hardware-timerslot te verbruiken. Geef -1 door als id om een virtuele (software-)timer te gebruiken:

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

Periodewaarden zijn in milliseconden. Roep deinit() aan om te stoppen en het slot vrij te geven.

Real-time klok

machine.RTC houdt de kloktijd bij over resets heen. De RTC van de nRF52840 is verbonden met de on‑chip oscillator en overleeft volledig spanningsverlies niet — stel de tijd in bij elke koude start als dat belangrijk is voor uw toepassing:

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 reset het board als de toepassing vastloopt. Eenmaal gestart kan deze niet worden gestopt of geherconfigureerd — voed hem periodiek binnen uw hoofdlus:

from machine import WDT

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

Boot- en runtime-informatie

Firmware-update

De Nano 33 BLE Sense gebruikt de standaard dubbele tik-reset van Arduino om de bootloader van Arduino te starten. Druk snel tweemaal op de RESET-knop — het board gaat in bootloadermodus en OpenMV IDE kan een nieuwe firmware-image flashen.

Een draaiend script kan op verzoek opnieuw de bootloader binnengaan door machine.bootloader() aan te roepen:

import machine

machine.bootloader()

Bestandssysteem en bootvolgorde

De firmware van de Nano 33 BLE Sense koppelt bij het opstarten één bestandssysteem:

  • Intern flashgeheugen — altijd gekoppeld op /flash en gebruikt als werkmap. Bevat standaard main.py en README.txt; aangemaakt bij de allereerste boot.

Na het koppelen draait de interpreter vervolgens scripts vanaf /flash:

  • boot.py wordt uitgevoerd bij elke soft reset.

  • main.py wordt alleen bij een koude start uitgevoerd, direct na boot.py.

De standaard main.py die op een vers geflasht board wordt geleverd, laat alleen het blauwe kanaal van de RGB-gebruikers-LED knipperen als hartslag (twee korte pulsen, korte pauze), zodat u kunt zien dat de firmware schoon is opgestart zonder dat er een host is aangesloten.

/flash wordt op dit board niet beschikbaar gesteld als USB-massaopslagschijf.

Opslaggroottes

De Nano 33 BLE Sense wordt geleverd met:

  • /flash64 KB FAT-bestandssysteem, lezen/schrijven.

De build van de Nano 33 BLE Sense bevat geen ROMFS; lever Python-modules rechtstreeks op /flash.

Softwarebibliotheken

Zie de bibliotheekindex voor de volledige lijst met modules — inclusief welke uniek zijn voor de build van de Nano 33 BLE Sense.