Nano 33 BLE Sense Python®ガイド

Python®スクリプトを使ってNano 33 BLE Senseの機能を利用する方法を学びます。


AUTHOR: Karl Söderby、LAST REVISION: 2022/12/15 18:35


Nano 33 BLE Sense

Nano 33 BLE Sense

Nano 33 BLE Senseボードは、人気のPython®プログラミング言語を使ってプログラムすることができます。より具体的には、MicroPythonのOpenMVの派生をサポートします。MicroPythonは、Python®言語の実装で、マイクロコントローラーで動作するように設計されています。この記事では、汎用のGPIO制御、搭載されているセンサーの読取、Wi-Fi/BLE通信などの、Nano 33 BLEで直接動作する多くのスクリプト例があります。

  • ArduinoとPython®についてもっと読みたければ、ArduinoボードでMicroPythonを参照してください。ここでは、遅延(delay)や割り込みの使い方、ピンの値を読む方法、多くの汎用関数などの多くの有用な例があります。

必要なハードウェアとソフトウェア

i
このガイドには、OpenMVとMicroPythonのインストール方法は含んでいません。詳細はOpenMVを始めるを参照してください。

API

以下には、Nano 33 BLE Senseボードにロードできる多くの有用な例があります。これらの例の多くは、OpenMVリポジトリから取得しました。このリポジトリには、他のボード用の多くの有用な例もあります。

i
この記事では、Nano 33 BLE Senseボード用の例だけを記載しています。遅延(delay)やピンの入出力の使い方をさらに知りたければ、ArduinoボードでMicroPythonを参照してください。

ピン制御

Nano 33 BLE SenseとNRF52840マイクロコントローラのピンアウトは全く異なります。例えば、ArduinoのピンアウトでD2を使うときは、実際には43番ピンを使います。

1
2
# Defining "D2" on the Nano 33 BLE Sense
p0 = Pin(43, Pin.OUT)
i
Nano 33 BLE SenseボードのMicroPythonポートでは、ピンアウトはNordic NRF52840(マイクロコントローラ)のものと同じです。このセクションで他のピンの指定方法を説明します。

ピンマップ

ボードのピンを使い始める前に、ArduinoのピンアウトとNRF52840のピンアウトの関係を理解しておくことは有効です。

Arduino nRF52840
TX 35
RX 42
D2 43
D3 44
D4 47
D5 45
D6 46
D7 23
D8 21
D9 27
D10 34
D11 33
D12 40
D13 13
D14/A0 4
D15/A1 5
D16/A2 30
D17/A3 29
D18/A4 31
D19/A5 2
D20/A6 28
D21/A7 3

アナログピン

Nano BLE Senseのアナログピンを読むには、以下のピンから選ぶことができます。

  • A0 - 4
  • A1 - 5
  • A2 - 30
  • A3 - 29
  • A4 - 31
  • A5 - 2
  • A6 - 28
  • A7 - 3

これらを定義するには、machineモジュールをインポートし、ピンを以下のように定義する必要があります。

1
2
3
4
import machine

adc_pin = machine.Pin(29)
adc = machine.ADC(adc_pin)

アナログピンを読むには、以下を使ってください。

1
reading = adc.read_u16() #16-bit resolution (0-65535)

以下のスクリプトは、ArduinoNano BLE SenseのA3ピンを読み、その値を端末に表示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import machine
import time

adc_pin = machine.Pin(29) # A3
adc = machine.ADC(adc_pin)

while True:
    reading = adc.read_u16()     
    print("ADC: ",reading)
    time.sleep_ms(500)

LED制御

Nano BLE Senseには、利用できる3つの異なるLEDがあります。RGBと内蔵LED、電源LEDです。

LEDモジュールをインポートすれば、RGBと内蔵LEDにアクセスできます。

1
2
3
4
5
6
from board import LED

led_red = LED(1) # red LED
led_green = LED(2) # green LED
led_blue = LED(3) # blue LED
led_builtin = LED(4) # classic built-in LED (also accessible through pin 13)

電源LEDを利用するには、Pinモジュールをインポートする必要があります。

1
2
3
from machine import Pin

led_pwr = Pin(41, Pin.OUT)

RGB

全てのRGB LEDを0.25秒毎に点滅させます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from board import LED
import time 

led_red = LED(1)
led_green = LED(2)
led_blue = LED(3)

while (True):
   
    # Turn on LEDs
    led_red.on()
    led_green.on()
    led_blue.on()

    # Wait 0.25 seconds
    time.sleep_ms(250)
    
    # Turn off LEDs
    led_red.off()
    led_green.off()
    led_blue.off()

    # Wait 0.25 seconds
    time.sleep_ms(250)

内蔵LED

伝統的なBlinkの例です。内蔵LEDを0.25秒毎に点滅させます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from board import LED
import time 

led_builtin = LED(4)

while (True):
   
    # Turn on LED
    led_builtin.on()

    # Wait 0.25 seconds
    time.sleep_ms(250)
    
    # Turn off LED
    led_builtin.off()

    # Wait 0.25 seconds
    time.sleep_ms(250)

センサー

Nano 33 BLE Senseには、いくつかのセンサーが搭載されています。以下のスクリプトで、それぞれのセンサーからデータを取得することができます。

IMU(LSM9DS1)

LSM9DS1 IMUモジュールから、加速度センサーと磁気センサー、ジャイロスコープデータを取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import time
import lsm9ds1
from machine import Pin, I2C

bus = I2C(1, scl=Pin(15), sda=Pin(14))
lsm = lsm9ds1.LSM9DS1(bus)

while (True):
    #for g,a in lsm.iter_accel_gyro(): print(g,a)    # using fifo
    print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel()))
    print('Magnetometer:  x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_magnet()))
    print('Gyroscope:     x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro()))
    print("")
    time.sleep_ms(500)

温度と湿度(HTS221)

HTS221センサーから、温度と湿度の値を取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import time
import hts221
from machine import Pin, I2C

bus = I2C(1, scl=Pin(15), sda=Pin(14))
hts = hts221.HTS221(bus)

while (True):
    rH   = hts.humidity()
    temp = hts.temperature()
    print ("rH: %.2f%% T: %.2fC" %(rH, temp))
    time.sleep_ms(100)

気圧(LPS22)

LPS22センサーから、気圧の値を取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import time
import lps22h
from machine import Pin, I2C

bus = I2C(1, scl=Pin(15), sda=Pin(14))
lps = lps22h.LPS22H(bus)

while (True):
    pressure = lps.pressure()
    temperature = lps.temperature()
    print("Pressure: %.2f hPa Temperature: %.2f C"%(pressure, temperature))
    time.sleep_ms(100)

環境光(APDS9960)

APDS9960センサーから、環境光の値を取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from time import sleep_ms
from machine import Pin, I2C
from apds9960.const import *
from apds9960 import uAPDS9960 as APDS9960

bus = I2C(1, sda=Pin(13), scl=Pin(14))
apds = APDS9960(bus)

print("Light Sensor Test")
print("=================")
apds.enableLightSensor()

while True:
    sleep_ms(250)
    val = apds.readAmbientLight()
    print("AmbientLight={}".format(val))

近接センサー(APDS9960)

APDS9960センサーから、近接値を読み取ります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from time import sleep_ms
from machine import Pin, I2C

from apds9960.const import *
from apds9960 import uAPDS9960 as APDS9960

bus = I2C(1, sda=Pin(13), scl=Pin(14))
apds = APDS9960(bus)

apds.setProximityIntLowThreshold(50)

print("Proximity Sensor Test")
print("=====================")
apds.enableProximitySensor()

while True:
    sleep_ms(250)
    val = apds.readProximity()
    print("proximity={}".format(val))

マイク(MP34DT05)

以下の例は、OpenMVのフレームバッファウインドウ(右上の角)から利用できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import image, audio, time
from ulab import numpy as np
from ulab import scipy as sp

CHANNELS = 1
SIZE = 256//(2*CHANNELS)

raw_buf = None
fb = image.Image(SIZE+50, SIZE, image.RGB565, copy_to_fb=True)
audio.init(channels=CHANNELS, frequency=16000, gain_db=80, highpass=0.9883)

def audio_callback(buf):
    # NOTE: do Not call any function that allocates memory.
    global raw_buf
    if (raw_buf == None):
        raw_buf = buf

# Start audio streaming
audio.start_streaming(audio_callback)

def draw_fft(img, fft_buf):
    fft_buf = (fft_buf / max(fft_buf)) * SIZE
    fft_buf = np.log10(fft_buf + 1) * 20
    color = (0xFF, 0x0F, 0x00)
    for i in range(0, SIZE):
        img.draw_line(i, SIZE, i, SIZE-int(fft_buf[i]), color, 1)

def draw_audio_bar(img, level, offset):
    blk_size = SIZE//10
    color = (0xFF, 0x00, 0xF0)
    blk_space = (blk_size//4)
    for i in range(0, int(round(level/10))):
        fb.draw_rectangle(SIZE+offset, SIZE - ((i+1)*blk_size) + blk_space, 20, blk_size - blk_space, color, 1, True)

while (True):
    if (raw_buf != None):
        pcm_buf = np.frombuffer(raw_buf, dtype=np.int16)
        raw_buf = None

        if CHANNELS == 1:
            fft_buf = sp.signal.spectrogram(pcm_buf)
            l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100)
        else:
            fft_buf = sp.signal.spectrogram(pcm_buf[0::2])
            l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100)
            r_lvl = int((np.mean(abs(pcm_buf[0::2])) / 32768)*100)

        fb.clear()
        draw_fft(fb, fft_buf)
        draw_audio_bar(fb, l_lvl, 0)
        if CHANNELS == 2:
            draw_audio_bar(fb, r_lvl, 25)
        fb.flush()

# Stop streaming
audio.stop_streaming()

Bluetooth® Low Energy

この例では、スマホ経由でボードに接続し、内蔵LEDを制御することができます。nRF接続アプリを利用することをお勧めします。

i
以下のスクリプトをロードすると、利用可能なデバイスのリストに、あなたのボードが、"Nano 33 BLE Sense"として表示されます。内蔵LEDを制御するには、ペアリングする必要があります。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Use nRF Connect from App store, connect to the Nano and write 1/0 to control the LED.

import time
from board import LED
from ubluepy import Service, Characteristic, UUID, Peripheral, constants

def event_handler(id, handle, data):
    global periph
    global service
    if id == constants.EVT_GAP_CONNECTED:
        pass
    elif id == constants.EVT_GAP_DISCONNECTED:
        # restart advertisement
        periph.advertise(device_name="Nano 33 BLE Sense", services=[service])
    elif id == constants.EVT_GATTS_WRITE:
        LED(1).on() if int(data[0]) else LED(1).off()

# start off with LED(1) off
LED(1).off()

notif_enabled = False
uuid_service = UUID("0x1523")
uuid_led     = UUID("0x1525")

service = Service(uuid_service)
char_led = Characteristic(uuid_led, props=Characteristic.PROP_WRITE)
service.addCharacteristic(char_led)

periph = Peripheral()
periph.addService(service)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33 BLE Sense", services=[service])

while (True):
    time.sleep_ms(500)

まとめ

この記事では、OpenMV IDEでNano BLE Senseボードを制御するいくつかのスクリプトを概観しました。ArduinoボードでMicroPythonには、他のボード用のガイドや、Python®を学習するための有用なリンクもあります。

オリジナルのページ

https://docs.arduino.cc/tutorials/nano-33-ble-sense/ble-sense-python-api

最終更新日

March 7, 2023

inserted by FC2 system