ボードごとのスケッチ例

内蔵センサ―を読み取るなど、特定のボードで動作するスケッチ例を示します。


Author: Karl Söderby、Last revision: 2024/03/01


この記事では、特定のボードで動作するスケッチ例を示します。個々のボードには、各ピンがどのようなアドレスになるかのGPIOマップもあります。

Nano RP2040 Connect

Nano RP2040 Connect

Nano RP2040 Connect

GPIOマップ

Nano RP2040 ConnectとRP2040マイクロコントローラーのピンアウトは大きく異なります。例えば、ArduinoピンアウトのD2を使うには、実際には、25番ピンを使う必要があります。

1
2
# Defining "D2" on the Arduino Nano RP2040 Connect
p0 = Pin(25, Pin.OUT)

ボードのピンを使う前に、ArduinoのピンアウトとRP2040のピンアウトの関係を理解するのに、以下の表を見ておくことは有用です。

Arduino RP2040 Usage
TX GPIO0 UART/TX
RX GPIO1 UART/RX
D2 GPIO25 GPIO
D3 GPIO15 GPIO
D4 GPIO16 GPIO
D5 GPIO17 GPIO
D6 GPIO18 GPIO
D7 GPIO19 GPIO
D8 GPIO20 GPIO
D9 GPIO21 GPIO
D10 GPIO5 GPIO
D11 GPIO7 SPI/COPI
D12 GPIO4 SPI/CIPO
D13 GPIO6 SPI/SCK
D14/A0 GPIO26 ADC/RP2040
D15/A1 GPIO27 ADC/RP2040
D16/A2 GPIO28 ADC/RP2040
D17/A3 GPIO29 ADC/RP2040
D18/A4 GPIO12 I2C
D19/A5 GPIO13 I2C
D20/A6 GPIO36 ADC/NINA-W102
D21/A7 GPIO35 ADC/NINA-W102

Analog Read

i
注意: これは、ナイトリービルドでだけ利用可能です。このリンクを参照してください。

アナログピンを読み取るには、ADC.read_u16コマンドを使います。このコマンドは指定したアナログピンを読み、0-65535の間の整数値を返します。これを使うには、machineモジュールから、ADCをインポートする必要があります。

1
2
3
4
5
from machine import ADC

while True:
    adc = ADC("A4")
    adc.read_u16()

センサー

慣性計測装置(LSM6DSOX)

加速度センサーとジャイロスコープの値をシリアルモニターに表示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import time
from lsm6dsox import LSM6DSOX

from machine import Pin, I2C
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))

while (True):
    print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel()))
    print('Gyroscope:     x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro()))
    print("")
    time.sleep_ms(100)

マイク(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
57
58
59
60
import image, audio, time
from ulab import numpy as np
from ulab import scipy as sp

CHANNELS = 1
FREQUENCY = 32000
N_SAMPLES = 32 if FREQUENCY == 16000 else 64
SCALE = 2
SIZE = (N_SAMPLES * SCALE) // CHANNELS

raw_buf = None
fb = image.Image(SIZE+(50*SCALE), SIZE, image.RGB565, copy_to_fb=True)
audio.init(channels=CHANNELS, frequency=FREQUENCY, gain_db=16)

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, len(fft_buf)):
        img.draw_line(i*SCALE, SIZE, i*SCALE, SIZE-int(fft_buf[i]) * SCALE, color, SCALE)

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 * SCALE, 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)
        draw_audio_bar(fb, l_lvl, 25*SCALE)
        if CHANNELS == 2:
            draw_audio_bar(fb, r_lvl, 25 * SCALE)
        fb.flush()

# Stop streaming
audio.stop_streaming()

通信

I2C

I2Cバスに接続されているデバイスをスキャンします。

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

i2c_list    = [None, None]
i2c_list[0] = I2C(0, scl=Pin(13), sda=Pin(12), freq=100_000)
i2c_list[1] = I2C(1, scl=Pin(7), sda=Pin(6), freq=100_000)

for bus in range(0, 2):
    print("\nScanning bus %d..."%(bus))
    for addr in i2c_list[bus].scan():
        print("Found device at address %d:0x%x" %(bus, addr))

UART

TXピンとRXピンを通じてデータを読み書きするには、uart.read()uart.write()を追加います。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from machine import UART, Pin
import time

uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))

while True:
   uart.write('hello') # writes 5 bytes
   val = uart.read(5)  # reads up to 5 bytes
   print(val) # prints data
   time.sleep(1)

無線

以下は、Nano RP2040 Connect上のNINA-W102モジュールを使った無線接続の例です。

i
注意: この例を使うには、ファームウェアを更新する必要があります。Nano RP2040 Connect NINAファームウェアを更新するを参照してください。

Wi-Fi AP Mode

ボードをアクセスポイントにします。

 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
57
58
59
60
61
# Wi-Fi AP Mode Example
#
# This example shows how to use Wi-Fi in Access Point mode.
import network, socket, sys, time, gc

SSID ='My_Nano_RP2040_Connect'   # Network SSID
KEY  ='1234567890'  # Network key (must be 10 chars)
HOST = ''           # Use first available interface
PORT = 8080         # Arbitrary non-privileged port

# Init wlan module and connect to network
wlan = network.WLAN(network.AP_IF)
wlan.active(True)
wlan.config(essid=SSID, key=KEY, security=wlan.WEP, channel=2)
print("AP mode started. SSID: {} IP: {}".format(SSID, wlan.ifconfig()[0]))

def recvall(sock, n):
    # Helper function to recv n bytes or return None if EOF is hit
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            raise OSError("Timeout")
        data.extend(packet)
    return data

def start_streaming(server):
    print ('Waiting for connections..')
    client, addr = server.accept()

    # set client socket timeout to 5s
    client.settimeout(5.0)
    print ('Connected to ' + addr[0] + ':' + str(addr[1]))

    # FPS clock
    clock = time.clock()
    while (True):
        try:
            # Read data from client
            data = recvall(client, 1024)
            # Send it back
            client.send(data)
        except OSError as e:
            print("start_streaming(): socket error: ", e)
            client.close()
            break

while (True):
    try:
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Bind and listen
        server.bind([HOST, PORT])
        server.listen(1)

        # Set server socket to blocking
        server.setblocking(True)
        while (True):
            start_streaming(server)
    except OSError as e:
        server.close()
        print("Server socket error: ", e)

Wi-Fi®スキャン

利用可能なネットワークをスキャンします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Scan Example

# This example shows how to scan for Wi-Fi networks.

import time, network

wlan = network.WLAN(network.STA_IF)
wlan.active(True)

print("Scanning...")
while (True):
    scan_result = wlan.scan()
    for ap in scan_result:
        print("Channel:%d RSSI:%d Auth:%d BSSID:%s SSID:%s"%(ap))
    print()
    time.sleep_ms(1000)

HTTPリクエスト

HTTPリクエストします(この例ではgoogleに)。

i
注意: SSIDとKEYに、ネットワーク名とパスワードを設定してください。
 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
import network, socket

# AP info
SSID='' # Network SSID
KEY=''  # Network key

PORT = 80
HOST = "www.google.com"

# Init wlan module and connect to network
print("Trying to connect. Note this may take a while...")

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, KEY)

# We should have a valid IP now via DHCP
print("Wi-Fi Connected ", wlan.ifconfig())

# Get addr info via DNS
addr = socket.getaddrinfo(HOST, PORT)[0][4]
print(addr)

# Create a new socket and connect to addr
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)

# Set timeout
client.settimeout(3.0)

# Send HTTP request and recv response
client.send("GET / HTTP/1.1\r\nHost: %s\r\n\r\n"%(HOST))
print(client.recv(1024))

# Close socket
client.close()

NTP(Network Time Protocol)

i
注意: SSIDとKEYに、ネットワーク名とパスワードを設定してください。

インターネットから正確な日時を取得します。

 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
# NTP Example
#
# This example shows how to get the current time using NTP

import network, usocket, ustruct, utime

# AP info
SSID='' # Network SSID
KEY=''  # Network key

TIMESTAMP = 2208988800

# Init wlan module and connect to network
print("Trying to connect... (may take a while)...")

wlan = network.WLAN()
wlan.active(True)
wlan.connect(SSID, key=KEY, security=wlan.WPA_PSK)

# We should have a valid IP now via DHCP
print(wlan.ifconfig())

# Create new socket
client = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
client.bind(("", 8080))
#client.settimeout(3.0)

# Get addr info via DNS
addr = usocket.getaddrinfo("pool.ntp.org", 123)[0][4]

# Send query
client.sendto('\x1b' + 47 * '\0', addr)
data, address = client.recvfrom(1024)

# Print time
t = ustruct.unpack(">IIIIIIIIIIII", data)[10] - TIMESTAMP
print ("Year:%d Month:%d Day:%d Time: %d:%d:%d" % (utime.localtime(t)[0:6]))

ターミナルに、以下のフォーマットで表示されます。

1
Year:2021 Month:8 Day:10 Time: 7:56:30

Bluetooth® Low Energy

この例では、ボードをスマートフォンと接続し、内蔵LEDを制御します。nRF Connectアプリケーションを使うことを推奨します。

i
以下のスクリプトをロードした後は、利用可能なデバイス一覧に、"Nano RP2040 Connect"と表示されるはずです。内蔵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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import bluetooth
import random
import struct
import time
from ble_advertising import advertising_payload
from machine import Pin
from micropython import const

LED_PIN = 6

_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)

_FLAG_READ = const(0x0002)
_FLAG_WRITE = const(0x0008)
_FLAG_NOTIFY = const(0x0010)
_FLAG_INDICATE = const(0x0020)

_SERVICE_UUID = bluetooth.UUID(0x1523)
_LED_CHAR_UUID = (bluetooth.UUID(0x1525), _FLAG_WRITE)
_LED_SERVICE = (_SERVICE_UUID, (_LED_CHAR_UUID,),)

class BLETemperature:
    def __init__(self, ble, name="NANO RP2040"):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(self._irq)
        ((self._handle,),) = self._ble.gatts_register_services((_LED_SERVICE,))
        self._connections = set()
        self._payload = advertising_payload(name=name, services=[_SERVICE_UUID])
        self._advertise()

    def _irq(self, event, data):
        # Track connections so we can send notifications.
        if event == _IRQ_CENTRAL_CONNECT:
            conn_handle, _, _ = data
            self._connections.add(conn_handle)
        elif event == _IRQ_CENTRAL_DISCONNECT:
            conn_handle, _, _ = data
            self._connections.remove(conn_handle)
            # Start advertising again to allow a new connection.
            self._advertise()
        elif event == _IRQ_GATTS_WRITE:
            Pin(LED_PIN, Pin.OUT).value(int(self._ble.gatts_read(data[-1])[0]))
            
    def _advertise(self, interval_us=500000):
        self._ble.gap_advertise(interval_us, adv_data=self._payload)

if __name__ == "__main__":
    ble = bluetooth.BLE()
    temp = BLETemperature(ble)
    
    while True:
        time.sleep_ms(1000)

Nano 33 BLE

Nano 33 BLE

Nano 33 BLE

GPIOマップ

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

1
2
# Defining "D2" on the Nano 33 BLE
p0 = Pin(43, Pin.OUT)

Nano 33 BLEのMicroPythonポーティングでは、ピンアウトは、Nordic NRF52840マイクロコントローラーと同じです。 以下のGPIOマップで、異なるピンの対応関係を示しています。

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

Analog Read

i
注意: これは、ナイトリービルドでだけ利用可能です。

LED制御

Nano 33 BLEでは、RGBと内蔵LED、電源LEDの異なる3種類のLEDが利用できます。

LEDモジュールをインポートすれば、RGBと内蔵LED、電源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

0.25秒ごとに全てのRGB 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
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

いつもの点滅の例です。0.25秒ごとに内蔵LEDを点滅させます。

 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には、いくつかのセンサーを搭載しています。以下のスクリプトは、それぞれのセンサーにアクセスするのに使います。

慣性計測装置(LSM9DS1, BMI270 + BMM150)

IMUの、加速度センサーと磁気センサー、ジャイロスコープの値を取得します。

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

bus = I2C(1, scl=Pin(15), sda=Pin(14))
imu = imu.IMU(bus)

while (True):
    print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.accel()))
    print('Gyroscope:     x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.gyro()))
    print('Magnetometer:  x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.magnet()))
    print("")
    time.sleep_ms(100)

温度と湿度(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 Connectアプリケーションを使うことを推奨します。

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)

Portenta H7

Portenta H7

Portenta H7

GPIOマップ

ほとんどのピンは、ポート名か機能名で参照されています。Portenta H7の、どの機能がどのポートに関連するか、以下の表を見てください。

Arduino STM32H747
PA0 PA0
PA1 PA1
PA2 PA2
PA3 PA3
PA4 PA4
PA5 PA5
PA6 PA6
PA7 PA7
PA8 PA8
PA9 PA9
PA10 PA10
PA11 PA11
PA12 PA12
PA13 PA13
PA14 PA14
PA15 PA15
PB0 PB0
PB1 PB1
PB2 PB2
PB3 PB3
PB4 PB4
PB5 PB5
PB6 PB6
PB7 PB7
PB8 PB8
PB9 PB9
PB10 PB10
PB11 PB11
PB12 PB12
PB13 PB13
PB14 PB14
PB15 PB15
PC0 PC0
PC1 PC1
PC2 PC2
PC3 PC3
PC4 PC4
PC5 PC5
PC6 PC6
PC7 PC7
PC8 PC8
PC9 PC9
PC10 PC10
PC11 PC11
PC12 PC12
PC13 PC13
PC14 PC14
PC15 PC15
PD0 PD0
PD1 PD1
PD2 PD2
PD3 PD3
PD4 PD4
PD5 PD5
PD6 PD6
PD7 PD7
PD8 PD8
PD9 PD9
PD10 PD10
PD11 PD11
PD12 PD12
PD13 PD13
PD14 PD14
PD15 PD15
PE0 PE0
PE1 PE1
PE2 PE2
PE3 PE3
PE4 PE4
PE5 PE5
PE6 PE6
PE7 PE7
PE8 PE8
PE9 PE9
PE10 PE10
PE11 PE11
PE12 PE12
PE13 PE13
PE14 PE14
PE15 PE15
PF0 PF0
PF1 PF1
PF2 PF2
PF3 PF3
PF4 PF4
PF5 PF5
PF6 PF6
PF7 PF7
PF8 PF8
PF9 PF9
PF10 PF10
PF11 PF11
PF12 PF12
PF13 PF13
PF14 PF14
PF15 PF15
PG0 PG0
PG1 PG1
PG2 PG2
PG3 PG3
PG4 PG4
PG5 PG5
PG6 PG6
PG7 PG7
PG8 PG8
PG9 PG9
PG10 PG10
PG11 PG11
PG12 PG12
PG13 PG13
PG14 PG14
PG15 PG15
PH0 PH0
PH1 PH1
PH2 PH2
PH3 PH3
PH4 PH4
PH5 PH5
PH6 PH6
PH7 PH7
PH8 PH8
PH9 PH9
PH10 PH10
PH11 PH11
PH12 PH12
PH13 PH13
PH14 PH14
PH15 PH15
PI0 PI0
PI1 PI1
PI2 PI2
PI3 PI3
PI4 PI4
PI5 PI5
PI6 PI6
PI7 PI7
PI8 PI8
PI9 PI9
PI10 PI10
PI11 PI11
PI12 PI12
PI13 PI13
PI14 PI14
PI15 PI15
PJ0 PJ0
PJ1 PJ1
PJ2 PJ2
PJ3 PJ3
PJ4 PJ4
PJ5 PJ5
PJ6 PJ6
PJ7 PJ7
PJ8 PJ8
PJ9 PJ9
PJ10 PJ10
PJ11 PJ11
PJ12 PJ12
PJ13 PJ13
PJ14 PJ14
PJ15 PJ15
PK0 PK0
PK1 PK1
PK2 PK2
PK3 PK3
PK4 PK4
PK5 PK5
PK6 PK6
PK7 PK7
UART1_TX PA9
UART1_RX PA10
UART4_TX PA0
UART4_RX PI9
UART6_TX PG14
UART6_RX PG9
UART8_TX PJ8
UART8_RX PJ9
ETH_RMII_REF_CLK PA1
ETH_MDIO PA2
ETH_RMII_CRS_DV PA7
ETH_MDC PC1
ETH_RMII_RXD0 PC4
ETH_RMII_RXD1 PC5
ETH_RMII_TX_EN PG11
ETH_RMII_TXD0 PG13
ETH_RMII_TXD1 PG12
USB_HS_CLK PA5
USB_HS_STP PC0
USB_HS_NXT PH4
USB_HS_DIR PI11
USB_HS_D0 PA3
USB_HS_D1 PB0
USB_HS_D2 PB1
USB_HS_D3 PB10
USB_HS_D4 PB11
USB_HS_D5 PB12
USB_HS_D6 PB13
USB_HS_D7 PB5
USB_HS_RST PJ4
USB_DM PA11
USB_DP PA12
BOOT0 BOOT0
DAC1 PA4
DAC2 PA5
LEDR PK5
LEDG PK6
LEDB PK7
I2C1_SDA PB7
I2C1_SCL PB6
I2C3_SDA PH8
I2C3_SCL PH7
-WL_REG_ON PJ1
-WL_HOST_WAKE PJ5
-WL_SDIO_0 PC8
-WL_SDIO_1 PC9
-WL_SDIO_2 PC10
-WL_SDIO_3 PC11
-WL_SDIO_CMD PD2
-WL_SDIO_CLK PC12
-BT_RXD PF6
-BT_TXD PA15
-BT_CTS PF9
-BT_RTS PF8
-BT_REG_ON PJ12
-BT_HOST_WAKE PJ13
-BT_DEV_WAKE PJ14
-QSPI2_CS PG6
-QSPI2_CLK PF10
-QSPI2_D0 PD11
-QSPI2_D1 PD12
-QSPI2_D2 PF7
-QSPI2_D3 PD13

I/Oピン

I/Oピンを使うには、pybライブラリからPinモジュールをインポートする必要があります。

1
from pyb import Pin

Portentaのピンを参照するには、Pin()コンストラクタを使います。第一引数は、使いたいピンです。第二引数はmodeで、Pin.INPin.OUT_PPPin.OUT_ODPin.AF_PPPin.AF_ODPin.ANALOGのいずれかを設定します。ピンモードの説明は、ここにあります。第三引数は、pullで、プルモードを表し、Pin.PULL_NONEPin.PULL_UPPin.PULL_DOWNのいずれかを設定します。例:

1
pin0 = Pin('P0', mode, pull)

ピンの論理レベルを取得するには、.value()を呼び出します。これは、0か1を返し、Arduino用語での、LOWHIGHに対応します。

1
pin0.value()

PWM

PWMを使うには、pybtimePinTimerモジュールをインポートします。

1
2
3
import pyb
import time
from pyb import Pin, Timer

まず、PWMを使いたいピンを選択します。

1
pin1 = Pin("PC6", Pin.OUT_PP, Pin.PULL_NONE)

IDと周波数を指定したPWM用のタイマーを生成します。

1
timer1 = Timer(3, freq=1000)

その後、タイマーオブジェクトのPWMチャネルを開始します。

1
channel1 = timer1.channel(1, Timer.PWM, pin=pin1, pulse_width=0)

チャネルのパルス幅を取得、設定します。取得するときは引数は不要です。設定するには、値を引数に与えます。

1
channel1.pulse_width(Width)

RGB LED

Portenta H7は、アプリケーションからのフィードバックとして使える内蔵RGBを搭載しています。pybライブラリを使えば、Portentaで異なるLEDの色を簡単に定義することができます。

このためには、pybライブラリを使います。

1
import pyb

内蔵LEDで、異なる色を簡単に定義できます。

1
2
3
redLED = pyb.LED(1)
greenLED = pyb.LED(2)
blueLED = pyb.LED(3)

そして、スクリプト内で制御します。

1
2
3
4
5
6
7
8
redLED.on()
redLED.off()

greenLED.on()
greenLED.off()

blueLED.on()
blueLED.off()

LEDの輝度を任意に設定することもできます。範囲は0(オフ)から255(全灯)までです。異なるLEDの輝度を設定する例を以下に示します。

1
2
3
redLED.intensity(128)
greenLED.intensity(64)
blueLED.intensity(50)

.intensity()関数に引数を与えなければ、そのLEDの輝度を返します。

通信

他のArduino®と同様、Portenta H7は、異なるプロトコル用の専用のピンがあります。

SPI

Portenta H7でSPIに利用できるピンは、以下の通りです。

Pin Function
PI0 CS
PC3 COPI
PI1 CK
PC2 CIPO

ボード上で上記を探すには、GPIOマップを参照してください。

まず、pybから関連のモジュールをインポートします。

1
from pyb import SPI

SPIを初期化するときに設定する必要があるのはバスで、Portenta H7では、常に2です。これが唯一利用できるバスです。残りの引数はオプションです。必要に応じて、SPIデバイスのモード(SPI.MASTERSPI.SLAVE)、デバイスのボーレート、極性(0か1)、 アイドルクロックのロジックレベル(HIGHかLOW)、サンプルデータに対するフェーズ(最初のクロックエッジ(0)か、2番目のクロックエッジ(1))を設定することができます。

1
spi = SPI(2, SPI.MASTER, baudrate=100000, polarity=0, phase=0)

SPIでデータを送信するには、.send()に送信したいデータを引数に設定して、呼び出します。dataは送信するデータで、整数(dataInt)かバッファオブジェクト(dataBuffer)のどちらかです。timeoutはオプションで設定でき、送信の待ち時間のタイムアウトをミリ秒単位で示します。

1
2
3
dataInt = 21
dataBuffer = bytearray(4)
spi.send(data, timeout=5000)

同様に、SPIでデータを受信するには、recv()を呼び出します。dataは受信するバイト数で、整数(dataInt)か、buffer(dataBuffer)で、受信したデータが格納されます。timeoutはオプションで設定でき、受信の待ち時間のタイムアウトをミリ秒単位で示します。

1
2
3
dataInt = 0
dataBuffer = bytearray(4)
SPI.recv(data, timeout=5000)

I2C

Portenta H7で、I2C(Inter-Integrated Circuit)に使われるピンは以下の通りです。

Pin Function
PH8 SDA
PH7 SCL

ボード上で上記を探すには、GPIOマップを参照してください。

I2Cを使うには、適切なモジュールをインポートします。

1
from pyb import I2C

これで、I2Cオブジェクトを作成できるようになります。I2Cオブジェクトを作成するには、バスを指定する必要があります。バスは、I2Cを使うためのピンを示します。バスに3を指定すると、Portenta H7のSCLピンとSDAピンで、I2Cを開始します。Portenta H7には、4つのI2Cバスがあります。

1
i2c = I2C(3)

オブジェクトが作成されたので、初期化します。デバイスがコントローラー(I2C.MASTER)になるのか、リーダー(I2C.SLAVE)になるのか決める必要があります。リーダーデバイスの場合は、addressも指定します。必要ならば、ボーレートも設定します。

1
i2c.init(I2C.MASTER, addr=address, baudrate=100000)

バス上のデータを受信するには、.recv()関数を呼び出します。この関数では、dataは受信するバイト数で、整数(dataInt)か、buffer(dataBuffer)で、受信したデータが格納されます。addrは受信するアドレスで、コントローラーモードのときにだけ必要です。timeoutは、受信の待ち時間のタイムアウトをミリ秒単位で示します。以下のコードは、受信したデータを、OpenMVのシリアルモニタに表示します。

1
2
3
4
dataInt = 0
dataBuffer = bytearray(4)
receivedData = i2c.recv(data, addr=0, timeout=5000)
Print(receivedData)

バスにデータを送信するには、.send()関数を呼び出します。この関数では、dataは送信するデータで、整数(dataInt)か、buffer(dataBuffer)で、受信したデータが格納されます。addrは送信するアドレスで、コントローラーモードのときにだけ必要です。timeoutは、送信の待ち時間のタイムアウトをミリ秒単位で示します。

1
2
3
dataInt = 412
dataBuffer = bytearray(4)
i2c.send(data, addr=0, timeout=5000)

デバイスがI2Cバスに接続されていることを確認するには、.scan()関数が利用可能です。これは、0x01から0x7fまでの全てのIC2アドレスをスキャンし、反応のあったアドレスのリストを返します。これは、コントローラーモードのときにだけ動作します。

1
i2c.scan()

UART

Portenta H7で、UARTに使われるピンは以下の通りです。

Pin Function
PA10 RX
PA9 TX

ボード上で上記を探すには、GPIOマップを参照してください。

UARTを使うには、適切なモジュールをインポートします。

1
from pyb import UART

UARTオブジェクトを作成するには、UARTバスを指定する必要があります。Portenta H7には、3つのUARTバスがありますが、OpenMVで利用できるボードのピンは一つです。

1
uart = UART(1)

オブジェクトが生成されたので、initで初期化します。初期化の際には、baudrateと、bits(1文字が何ビット(7か8、9)かを示す)、parity(Noneか、0(even)、1(odd)、stop(ストップビットの数値で1か2)、flow(フロー制御を示し、0か、UART.RTS、UART.CTS、UART.RTS|UART.CTS)を設定できます。詳細はこちら)、timeout(最初の文字を送受信する際のタイムアウトをミリ秒単位で)、timeout_char(文字の送受信時のタイムアウトをミリ秒単位で)、read_buf_len(読み込みバッファ長で、0は未使用)を設定できます。

1
uart.init(baudrate, bits=8, parity=None, stop=1, timeout=0, flow=0, timeout_char=0, read_buf_len=64)

UARTから受信するには、.read()を呼び出します。bytesを指定すると、最大そのバイト数受信します。bytesを指定しないと、このメソッドは可能な限りデータを読みます。タイムアウトを超過すると、戻ります。以下のコード例は、uartからデータを読み、配列に格納し、シリアルターミナルに表示します。

1
2
3
array = bytearray(5)
uart.read(array)
print(array)

UARTに送信するには、.write()を呼び出します。この関数はバイトのbufferをバスに書き込みます。文字が7ビットか8ビットの場合は、各バイトは1文字です。文字が9ビットの場合は、1文字に2バイト使われ、bufferは偶数バイトです。

1
uart.write(buffer)

Wi-Fi®

Wi-Fi®を使うには、適切なモジュールをインポートします。

1
import network

その後、Wi-Fi®のネットワークSSIDを定義し変数に格納します。ネットワークパスワードも同様です。

1
2
SSID=''
PASSWORD=''

次に、WLANネットワークインターフェイスオブジェクトを作成します。引数には、network.STA_IFを指定します。これは、デバイスがクライアントで、Wi-Fi®アクセスポイントに接続することを示します。

1
wlan = network.WLAN(network.STA_IF)

ネットワークインターフェイスを活性化するには、.activateを、引数Trueで呼び出します。

1
wlan.active(True)

次に、どのネットワークに接続するかを決めます。ここでSSIDPASSWORD変数が役立ちます。

1
wlan.connect(SSID, PASSWORD, timeout=30000)

トラブルシューティングする場合は、.status()を使います。この関数は接続状態を表す値を返します。また接続に失敗したときに、何が間違っているのかも知らせます。

1
wlan.status()

オーディオ

Portenta H7でオーディオを使うには、audioモジュールをインポートします。他の有用なモジュールは、micro_speechで、GoogleのTensorFlow Lite for Microcontrollers Micro Speechの音声認識フレームワークを実行します。

1
import audio, micro_speech

次にオーディオオブジェクトを初期化します。初期化では、何チャネル使うかを決めます。これは、1か2です。frequencyは、サンプリング周波数です。高サンプリング周波数を使うと、ノイズフローが高くなり、サンプリング毎の有効ビットが少なくなります。デフォルトのオーディオサンプルは8ビットで、7ビットが有効なダイナミックレンジです。gain_dbはマイクのゲインを指定します。highpassはターゲットのサンプリング周波数でのハイパスフィルターのカットオフ周波数です。

1
audio.init(channels=2, frequency=16000, gain_db=24, highpass=0.9883)

オーディオオブジェクトを開放するときは、deint()を呼びます。

1
audio.deint()

micro_speechを使うには、micro_speechオブジェクトを作成します。このオブジェクトを作成して、speechに設定します。

1
speech = micro_speech.MicroSpeech()

次にmicro_speechオブジェクトで、ストリーミングを開始します。これは、audio.start_streaming()を呼び出します。micro_speechオブジェクトを引数にすることができ、オブジェクトをオーディをサンプルに格納します。MicroSpeechモジュールはオーディオサンプルのFFTを計算し、音声認識機能として、受信した音声サンプルの最後の100msを、FFTのスライディングウインドウを内部で保持します。

1
audio.start_streaming(speech.audio_callback)

オーディオストリーミングを停止するときは、stop_streaming()を呼び出します。

1
audio.stop_streaming()

Portenta C33

ピンアウトマッピング

Portenta C33は、物理的なピンの利用方法に、MKR形式のコネクターと、High-Densityコネクターの2種類あります。ほとんどのピンは、ポート名か関数で参照されます。以下の図では、Portenta C33 MKR形式のピンアウトを示しています。

Portenta C33 MKR形式のピンアウト

Portenta C33 MKR形式のピンアウト

MicroPythonでのPortenta C33 MKR形式のピンアウトは、以下の通りです。

Arduino Pin Mapping MicroPython Pin Mapping
P006/A0 P006
P005/A1 P005
P004/A2 P004
P002/A3 P002
P001/A4 P001
P015/A5 P015
P014/A6 P014
P105/D0 P105
P106/D1 P106
P111/D2 P111
P303/D3 P303
P401/D4 P401
P210/D5 P210
P602 P602
P110 P110
P408 P408
P407 P407
P315 P315
P204 P204
P900 P900
P402 P402
P601 P601

完全なMicroPythonのピンアウトはここを参照してください。

入出力ピン

machineモジュールのPinクラスが、Portenta C33ボードの入出力(I/O)ピンの制御に不可欠です。これらのピンは、センサーデータの読み取りやアクチュエーターの制御、他のハードウェアコンポーネントとのインターフェイスなどの幅広いアプリケーションに必要です。

ピンの初期化

MicroPythonで、Portenta C33ボードのI/Oピンを使い始めるには、machineモジュールのPinクラスを使い初期化する必要があります。ピン番号とモード(入出力等)を指定する必要があります。

1
2
3
4
from machine import Pin

# Initializing pin P107 as an output
p107 = Pin('P107', Pin.OUT)

ピンモードの設定

ピンは、入力か出力に設定できます。入力ピンの場合は、プルアップ抵抗やプルダウン抵抗を有効化するのが有用です。特に、ピンに接続している機械スイッチやボタンを読み取る際に、入力信号を安定化させます。

1
2
# Configuring pin P105 as an input with its pull-up resistor enabled
p105 = Pin('P105', Pin.IN, Pin.PULL_UP)

ピンの読み書き

デジタル値をピンから読み取るには、.value()メソッドを引数なしで使います。これは特に入力ピンで有用です。一方、デジタル値を書き込むには、.value()メソッドに引数を与えます。1を設定するとHIGHになり、0を設定するとLOWになります。これは、出力ピンに適用できます。

1
2
3
4
5
# Reading from P105
pin_value = p105.value()

# Writing to P107
p107.value(1)  # Set p2 to high

高度なピン設定

Pinクラスは、ピンの動的な設定変更ができ、割り込みのコールバックの設定もできます。この機能は、反応型や対話型のアプリケーションに不可欠です。

1
2
3
4
5
# Reconfiguring P105 as an input with a pull-down resistor
p105.init(Pin.IN, Pin.PULL_DOWN)

# Setting up an interrupt on P105
p105.irq(lambda p: print("- IRQ triggered!", p))

実用的な例

この例では、ボタンの状態を読むために一つのピンを入力に、LEDを制御するために別のピンを出力に設定します。ボタンを押すとLEDを点灯し、離すと消灯します。

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

# Configure pin P107 as an output (for the LED)
led = Pin('P107', Pin.OUT_PP)

# Configure pin P105 as input with pull-up resistor enabled (for the button)
button = Pin('P105', Pin.IN, Pin.PULL_UP)

while True:
    # Read the state of the button
    button_state = button.value()  
    if button_state == 0:
        # Turn on LED if button is pressed (button_state is LOW)
        led.value(1)  
    else:
        # Turn off LED if button is not pressed (button_state is HIGH)
        led.value(0) 

    # Short delay to debounce the button 
    time.sleep(0.1)

この実用的な例では、ボタンの状態によりLEDを制御することをデモします。P107に接続しているLEDは、プルアップ抵抗を有効にした入力に設定したP105から読み込むボタンの入力に応じて、点灯もしくは消灯します。メインループは連続してボタンの状態を調べます。ボタンを押すとLEDは点灯し、ボタンを離すとLEDは消灯します。ボタンからの誤ったトリガーを防ぎ安定した操作となるようにし、チャタリングを防ぐために、少しの遅延を含んでいます。

アナログ・デジタル変換器(ADC)

MicroPythonのADCクラスは、Portenta C33ボードのアナログ・デジタル変換器向けのインターフェイスを提供します。これにより、連続電圧の測定を可能とし、その値を離散値に変換します。この機能は、例えば、アナログセンサーから読み取る必要のあるアプリケーションで有用です。ADCクラスは、アナログピンから電圧をサンプリングし、のデジタル値に変換する、一つの単点を表現し、

Portenta C33で利用できるMicroPythonでのADCピンは、以下です。

Available ADC Pins
P006
P005
P004
P002
P001
P015
P014
P000

ADCを初期化する

Portenta C33ボードのADCを使うには、まず、指定するピンに紐づいたADCオブジェクトを作成します。このピンはアナログ値を読むのに使われます。

1
2
3
4
from machine import ADC

# Create an ADC object on a specific pin
adc = ADC(pin)

アナログ値を読む

read_u16()メソッドで、アナログ値を、(マイクロコントローラーが返す)生の値として読み取ります。このメソッドは、0-65535の整数値を返し、アナログ値を表現します。

1
2
# Reading a raw analog value
val = adc.read_u16()

実用的な例

この例は、Portenta C33ボードに接続したポテンショメーターから値を読みます。まず、ポテンショメーターをPortenta C33ボードに接続します。一つのピンをGNDに、もう一つを3V3に、真ん中のピンをP006などのアナログ値を読めるI/Oピンに接続します。ポテンショメーターを調整すると真ん中のピンの電圧が変化する、可変分圧器を構成します。

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

# Initialize the ADC on the potentiometer-connected pin
pot_pin = Pin('P006')
pot_adc = ADC(pot_pin)

while True:
    # Read the raw analog value
    raw_value = pot_adc.read_u16()
    print("- Potentiometer raw value:", raw_value)

    # Delay for readability
    time.sleep(0.1)

この例では、まず、必要なモジュールをインポートし、ポテンショメーターを接続しているピン(P006)のADCを設定します。ADCオブジェクト(pot_adc)は、ポテンショメーターとのインターフェイスです。ループ内では、ポテンショメーターからアナログ値をread_u16メソッドを使い、継続的に読みます。read_u16メソッドは、ポテンショメーターの位置により、065535の間の整数値を返します。アナログ値はコンソールに表示されます。短いディレイは出力が読み取れることを保証するために利用しています。

パルス幅変調(PWM)

パルス幅変調(PWM)はデジタルピンで、アナログ出力をエミュレートするメソッドです。LOWとHIGHを高速で切り替えることで実現します。2つのおもな要素がPWMの挙動を定義します。

  • 周波数: ピンのLOWとHIGHを切り替えるスピードです。
  • デューティー比: HIGH状態の期間と全体の期間との比です。デューティー比が100%のときは、常にHIGHとなり、0%のときは、常にLOWとなります。

Portenta C33で利用できるMicroPythonでのPWMピンは、以下です。

Available PWM Pins
P105
P106
P111
P303
P401
P601

PWMを設定する

PWMを使うには、ピンを初期化し、ピンに関連するPWMオブジェクトを作成します。

1
2
3
4
5
import machine

# Initialize a pin for PWM (e.g., pin P105)
p105 = machine.Pin('P105')
pwm1 = machine.PWM(p105)

PWMパラメータを設定する

PWMの周波数とデューティー比はアプリケーションの要件により決まります。

1
2
3
4
5
# Set the frequency to 500 Hz
pwm1.freq(500)

# Adjusting the duty cycle to 50 for 50% duty
pwm1.duty(50)

PWM設定を確認する

PWMオブジェクトの現在の設定を表示して確認できます。

1
2
# Will show the current frequency and duty cycle
print(pwm1)

周波数とデューティー比の値を取得します。

1
2
current_freq = pwm1.freq()
current_duty = pwm1.duty()

PWMを解除する

PWMが不要になれば、ピンを解除できます。

1
pwm1.deinit()

実用的な例

この例では、Portenta C33ボードのP105ピンに接続したLEDの輝度を、PWMを使い制御します。

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

# Configure the LED pin and PWM
led_pin = machine.Pin('P105')
led_pwm = machine.PWM(led_pin)
led_pwm.freq(500)

# Loop to vary brightness
while True:
    # Increase brightness
    for duty in range(100):
        led_pwm.duty(duty)
        time.sleep(0.001)

    # Decrease brightness
    for duty in range(100, -1, -1):
        led_pwm.duty(duty)
        time.sleep(0.001)

リアルタイムクロック

MicroPythonのRTCクラスは、Portenta C33ボードのリアルタイムクロックの管理・利用する手段を提供します。この機能は、メインプロセッサがアクティブでないときにも、正確に時間を測定する必要があるアプリケーションに不可欠です。RTCは、メインシステムとは独立して、正確な日時を保持します。バッテリーなどの電源に接続されている限り、ボードの電源を切っても、時刻を保持し続けます。

RTCを初期化する

RTCを使うには、まず、RTCオブジェクトを作成します。その後、オブジェクトは現在日時の読み書きに使います。

1
2
3
4
import machine

# Create an RTC object
rtc = machine.RTC()

日時を設定し、取得する

RTCを使えば、現在日時の設定と取得ができます。日時は8個の組を使ったフォーマットで表現します。

1
2
3
4
5
6
# Setting the RTC date and time
rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0))

# Getting the current date and time
current_datetime = rtc.datetime()
print("- Current date and time:", current_datetime)

日時を表す8個の組のフォーマットは、以下の通りです。

(year, month, day, weekday, hours, minutes, seconds, subseconds)
(年, 月, 日, 曜日, 時, 分, 秒, 秒未満)

実用的な例

RTCの実用的なユースケースの一つに、読み込んだセンサーデータにタイムスタンプを付与することがあります。RTCに現在時刻を設定することで、センサー値に正確なタイムスタンプを付与してログに保存することができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import machine

# Initialize the RTC and set the current datetime
rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0))

# Function to read a sensor value (placeholder)
def read_sensor():
    # Replace with actual sensor reading logic
    return 42  

# Read sensor value and get the current time
sensor_value = read_sensor()
timestamp = rtc.datetime()

# Output the sensor value with its timestamp
print("- Sensor value at ", timestamp, ":", sensor_value)

この例では、全てのセンサーからの読取値に、データ解析やログに不可欠なタイムスタンプを付与します。メインシステムの電源状態とは独立して時刻を保持できるRTCの機能は、時刻に依存するアプリケーションを信頼のあるものにします。

オリジナルのページ

https://docs.arduino.cc/micropython/basics/board-examples/

最終更新日

April 14, 2024

inserted by FC2 system