Arduino Nano 33 BLE Sense

Попередження

Ця плата більше не підтримується. Остання версія мікропрограми OpenMV для Arduino Nano 33 BLE Sense — 4.7.0. Для цієї цілі більше не буде виходити оновлень мікропрограми, виправлень помилок або нових функцій. Наведена нижче інформація збережена для користувачів, які використовують версію 4.7.0 або більш ранні.

Arduino Nano 33 BLE Sense — це плата формфактору Arduino Nano розміром 45 × 18 мм, побудована на основі Nordic Semiconductor nRF52840 — одноядерного ARM Cortex‑M4 з FPU, що працює на частоті 64 МГц із 256 КБ внутрішньої SRAM та 1 МБ внутрішньої флеш-пам’яті. Зв’язок Bluetooth забезпечується вбудованим радіомодулем; плата також оснащена 9-осьовим IMU, барометром LPS22HB, датчиком температури та вологості HTS221/HS3003, датчиком освітленості/кольору/наближення/жестів APDS9960 і PDM-мікрофоном MP34DT05. Мікропрограма OpenMV керує всіма цими пристроями через MicroPython.

Arduino Nano 33 BLE Sense

Повну документацію, фотографії та розміри дивіться на сторінці продукту Arduino Nano 33 BLE Rev2.

Основні характеристики

  • Nordic nRF52840 Cortex‑M4 з FPU на частоті 64 МГц із 256 КБ внутрішньої SRAM та 1 МБ внутрішньої флеш-пам’яті.

  • Bluetooth LE 5.0 через вбудований радіомодуль і Nordic SoftDevice s140.

  • 9-осьовий IMULSM9DS1 у Rev 1, BMI270 + BMM150 у Rev 2. Вморожений драйвер imu визначає тип при завантаженні.

  • LPS22HB барометр, HTS221 / HS3003 датчик температури та вологості, APDS9960 датчик освітленості / кольору / наближення / жестів і MP34DT05 PDM-мікрофон.

  • Micro USB роз’єм для живлення, програмування та CDC REPL.

  • 22 користувацьких виводи введення/виведення на стандартних роз’ємах Nano — TX/RX, D2D13 (цифрові), A0A7 (аналогові).

Розпіновка

Arduino Nano 33 BLE Sense Pinout

Довідник з виводів

Назва виводу

Довідник

Функція

TX

3.3 В

UART1 TX

RX

3.3 В

UART1 RX

D2

3.3 В

PWM

D3

3.3 В

PWM

D4

3.3 В

PWM

D5

3.3 В

PWM

D6

3.3 В

PWM

D7

3.3 В

PWM

D8

3.3 В

PWM

D9

3.3 В

PWM

D10

3.3 В

PWM

D11

3.3 В

PWM / SPI0 MOSI

D12

3.3 В

PWM / SPI0 MISO

D13

3.3 В

PWM / SPI0 SCK

A0

3.3 В

ADC / PWM

A1

3.3 В

ADC / PWM

A2

3.3 В

ADC / PWM

A3

3.3 В

ADC / PWM

A4 / I2C_SDA

3.3 В

ADC / PWM / I2C0 SDA

A5 / I2C_SCL

3.3 В

ADC / PWM / I2C0 SCL

A6

3.3 В

ADC / PWM

A7

3.3 В

ADC / PWM

RESET

3.3 В

натисніть кнопку RESET на платі або підключіть до GND для скидання

LED_BUILTIN

Помаранчевий користувацький світлодіод на D13

LED_RED

Червоний канал RGB-світлодіода (активний низький рівень)

LED_GREEN

Зелений канал RGB-світлодіода (активний низький рівень)

LED_BLUE

Синій канал RGB-світлодіода (активний низький рівень)

Попередження

Виводи введення/виведення Nano 33 BLE Sense розраховані лише на 3.3 В — вони несумісні з рівнями 5 В. Подача 5 В на них пошкодить nRF52840.

Виводи живлення

  • VIN — вхід 4.5–21 В. Живить плату через вбудований регулятор. Також підключений через діод від шини USB 5 В, тому USB та VIN можуть бути присутніми одночасно без зворотного живлення.

  • +5V — не підключений за замовчуванням.

  • +3V3 — вихід регулятора 3.3 В.

  • AREF — вивід аналогового опорного сигналу. Не підключений до nRF52840 на цій платі — АЦП завжди прив’язаний до 3.3 В.

  • GND — спільна земля.

Nano 33 BLE Sense може живитися двома способами:

  • Micro USB — подає 5 В на вбудований регулятор.

  • Вивід VIN — підключіть регульоване джерело 4.5–21 В.

Примітка

Паяний перемичка на нижній стороні плати з маркуванням VUSB з’єднує +5V з шиною USB 5 В. Замкніть її, щоб вивід +5V справді передавав 5 В.

Примітка

Нормально замкнена паяна перемичка на виході вбудованого імпульсного регулятора 4.5–21 В може бути розрізана, щоб відключити регулятор і живити плату безпосередньо від зовнішнього джерела 3.3 В через +3V3.

Виводи відновлення та налагодження

  • RESET — як відкритий контактний майданчик, так і кнопка миттєвої дії RESET на верхній стороні плати, підключені до лінії скидання nRF52840. Підключіть до GND або натисніть кнопку для скидання.

Nano 33 BLE Sense використовує стандартне для Arduino подвійне натискання RESET для входу в завантажувач Arduino. Швидко натисніть кнопку RESET двічі — плата увійде в режим завантажувача, і OpenMV IDE зможе прошити новий образ мікропрограми.

Сигнали SWD nRF52840 виведені на контактні майданчики на зворотній стороні плати. Усі сигнали налагодження мають рівень 3.3 В.

Вбудовані периферійні пристрої

Світлодіоди

Nano 33 BLE Sense має RGB-світлодіод для користувача — керований через канали LED_RED, LED_GREEN і LED_BLUE, позначені на шовкографії — а також окремий помаранчевий LED_BUILTIN на D13. Усі чотири програмно керуються через machine.LED

from machine import LED

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

Окремий зелений світлодіод живлення на платі світиться завжди, коли шина +3.3 В активна, і не підлягає програмному керуванню.

Датчик камери

Мікропрограма OpenMV для Nano 33 BLE Sense підтримує паралельний CMOS-датчик OmniVision OV7670. На платі немає вбудованого датчика зображення — підключіть модуль 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)

Шина керування I²C датчика OV7670 — це та сама зовнішня I²C 0, що виведена на A5/A4. Датчик має 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, імпортуйте відповідний вморожений драйвер (lsm9ds1, bmi270 або bmm150) та інстанціюйте його на тій самій шині.

Датчики середовища

Барометр (LPS22HB) і датчик температури/вологості (HTS221 у Rev 1, HS3003 у Rev 2) використовують ту саму внутрішню шину I²C 1, що й 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)

Освітленість / колір / наближення / жести

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)

Мікрофон

Вбудований PDM-мікрофон MP34DT05 зчитується через audio — Аудіомодуль. Кожен буфер надходить як знакові 16-бітні PCM bytearray, готові для передачі в ulab/numpy для ЦОС:

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

Радіомодуль Bluetooth LE 5.0 nRF52840 працює на Nordic SoftDevice s140 і доступний через застарілий модуль ubluepy — сучасні API bluetooth / aioble — Async BLE у цій збірці не підтримуються. Доступні обидва режими: периферійного пристрою (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 описано в довіднику ubluepyUUID, Service, Characteristic, Peripheral, Scanner, ScanEntry і простір імен constants.

Довідник по шинах

GPIO

Використовуйте machine.Pin для читання або керування будь-яким з виводів, позначених на шовкографії. Виходи — 3.3 В CMOS — 15 мА на вивід, 25 мА загалом по всіх 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())

Будь-який вхідний вивід також може генерувати переривання при переходах фронтів:

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

Використовуйте назви шовкографії TX/RX з machine.UART

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 на цій шині буде блимати світлодіодом у такт із тактовим сигналом шини.

ADC

nRF52840 має вісім 12-бітних каналів АЦП (SAADC), виведених на A0–A7, усі прив’язані до 3.3 Вread_u16 повертає 0–65535 в діапазоні 0–3.3 В на виводі. Вивід AREF плати не підключений, тому опорна напруга завжди 3.3 В:

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 слотів виглядають так:

Модуль

Кан. 0

Кан. 1

Кан. 2

Кан. 3

PWM0

робочий цикл

робочий цикл

робочий цикл

робочий цикл

PWM1

робочий цикл

робочий цикл

робочий цикл

робочий цикл

PWM2

робочий цикл

робочий цикл

робочий цикл

робочий цикл

PWM3

робочий цикл

робочий цикл

робочий цикл

робочий цикл

Кожен рядок працює на одній частоті; чотири комірки в рядку кожна керують незалежно обраним виводом із власним робочим циклом. Різні рядки можуть працювати на зовсім різних частотах.

Керуйте будь-яким виводом шовкографії (або вбудованими світлодіодами) через machine.PWM

from machine import Pin, PWM

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

Попередження

Автоматичне виділення займає цілий модуль за виклик. Коли ви створюєте PWM без аргументів device=/channel=, драйвер займає перший вільний модуль і прив’язує ваш вивід лише до каналу 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-світлодіода).

Примітка

Оскільки частота є властивістю всього модуля, виклик pwm.freq(new_freq) для будь-якого каналу модуля повторно запускає nrfx_pwm_init для всього модуля і змінює частоту для кожного іншого каналу, що ним користується.

Примітка

Допустимі частоти охоплюють приблизно від 4 Гц до 5.3 МГц, що визначаються базовим тактовим сигналом 16 МГц із попередніми дільниками 1/2/4/8/16/32/64/128 і 15-бітним лічильником періоду. Драйвер автоматично вибирає найближчий дільник — freq() повертає запитане значення, а не точно досяжне.

Програмно емульовані шини

machine.SoftI2C і machine.SoftSPI працюють на будь-якому GPIO, якщо вам потрібна додаткова шина.

Тепловий датчик (зовнішній)

Мікропрограма включає драйвер fir — драйвер теплового датчика (fir == далекий інфрачервоний діапазон) для зовнішньо підключених теплових сенсорів:

  • 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 як ідентифікатор, щоб використовувати віртуальний (програмний) таймер:

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 зберігає астрономічний час між скиданнями. RTC nRF52840 прив’язаний до внутрішнього осцилятора і не зберігає значення при повному відключенні живлення — встановлюйте час при кожному холодному завантаженні, якщо це важливо для вашого застосунку:

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 подвійне натискання RESET для входу в завантажувач Arduino. Швидко натисніть кнопку RESET двічі — плата увійде в режим завантажувача, і OpenMV IDE зможе прошити новий образ мікропрограми.

Запущений скрипт може повернутися до завантажувача на вимогу, викликавши machine.bootloader()

import machine

machine.bootloader()

Файлова система та порядок завантаження

Мікропрограма Nano 33 BLE Sense монтує єдину файлову систему при завантаженні:

  • Внутрішня флеш-пам’ять — завжди монтується в /flash і використовується як робочий каталог. За замовчуванням містить main.py та README.txt; створюється при першому завантаженні.

Після монтування інтерпретатор запускає скрипти з /flash:

  • boot.py виконується при кожному м’якому скиданні.

  • main.py виконується лише при холодному завантаженні, одразу після boot.py.

Стандартний main.py, що поставляється на щойно прошитій платі, просто блимає синім каналом RGB-світлодіода у ритмі серцебиття (два короткі спалахи, коротка пауза), щоб можна було переконатися в успішному завантаженні мікропрограми без підключення до хосту.

/flash не відображається як USB-накопичувач на цій платі.

Розміри сховищ

Nano 33 BLE Sense постачається з:

  • /flash — FAT-файлова система розміром 64 КБ, читання/запис.

Збірка Nano 33 BLE Sense не включає ROMFS; розміщуйте модулі Python безпосередньо в /flash.

Програмні бібліотеки

Повний список модулів, включно з тими, що унікальні для збірки Nano 33 BLE Sense, дивіться в індексі бібліотек.