MicroPythonのマイクロファン専用ファームウェア

ドライバとライブラリ

MicroPythonで入出力装置やセンサーを使用したプログラミングを行う際には、一般的に、あらかじめそれらを制御するドライバーやライブラリを開発ボードに組み込んでおく必要があります。このため、使用する入出力装置やセンサーに対応した適切なドライバーやライブラリを探して取得し、さらに開発ボードのファイルシステムに登録しておくことは、特に初心者にとっては面倒な作業になります。

マイクロファンは、このような面倒な準備作業を軽減できるように、マイクロファンの開発ボード専用のMicroPythonファームウェアを配布しています。このファームウェアには、マイクロファンの開発ボードで標準的に使用する入出力装置やセンサーなどのドライバーやライブラリがあらかじめ組み込まれており、開発ボードに専用ファームウェアを書き込めば、その開発ボードで使用する様々な入出力装置やセンサーを使用したプログラムをすぐに開発することができるようになります。

専用ファームウェアの取得

マイクロファンの専用ファームウェアは以下のページから取得できるので、マイクロファンの開発ボードに書き込んでご利用ください。下記のページには、ドライバーやライブラリの組込み以外のマイクロファンの専用ファームウェアの追加機能なども記載されているのでご確認ください。

ファームウェアの書き込み

マイクロファン専用ファームウェアの開発ボードへの書き込みは、オリジナルのファームウェアの書き込み同様に行うことができます。

具体的には、BOOTボタンを押した状態で、開発ボードをUSBケーブルでPCに接続します。そうすると、開発ボードはPCによってUSBディスクとして認識され、ディスクの中身を示すファイルエクスプローラーのウィンドウが開きます。

このウィンドウに専用ファームウェアのファイルをドラッグアンドドロップすることにより、開発ボードへのファームウェアの書き込みを行うことができます。


MicroPythonプログラミング

以下に、専用ファームウェアを書き込んだ開発ボードの使用法を説明します。専用ファームウェアの固有機能を使っている部分があるので、MicroPythonのオリジナルのファームウェアを書き込んだ開発ボードではここで示す方法では利用できないことがあります。

ここでのプログラム例の多くは、RP2040-UNO(-PLUS)にOLEDディスプレイが接続されていることを前提にしています。

また、センサー類や圧電スピーカーは、RP2040-UNOには装備されていませんが、SENSOR-PLUSを接続することで、RP2040-UNO-PLUSと同様に利用することができます。

以下にMicroPythonのプログラム例を示しますが、合わせてMicroPythonのサイトのRP2040用クイックリファレンスのページもご参照ください。


LED

LEDの点灯

RP2040-UNO(-PLUS)開発ボードには、マイクロコントローラから点滅を指示できるLEDが搭載されています。そのLEDをMicroPythonで操作する方法を示します。

RP2040のMicroPythonでは、一般的にはLEDが接続されている端子番号を使用して、制御用端子の指定や制御を行います。マイクロファンのRP2040-UNO(-PLUS)開発ボード用ファームウェアでは、LED制御用の端子に、'LED', 'LED1', 'D13' という機能名が付けられており、端子番号ではなく機能名で指定することができます。(もちろん、従来通り、端子番号(この場合は10)で指定することもできます。)

from machine import Pin
import time

led1 = Pin('LED1', Pin.OUT) # 'D13'でも10でもよい
led1.on()
time.sleep_ms(1000) # 1000ms, 1秒待つ
led1.off()

このプログラムは、単純に1秒ごとにLEDのON, OFFを行っています。

マイクロファンはいくつかのRP2040開発ボードを提供しており、開発ボードによってLEDが接続されている端子番号が異なります。このため、LEDの操作をしようとすると、LEDの端子番号を確認したり、プログラムを他の開発ボードに移植しようとすると、端子番号を変更する必要があります。

しかしながら、マイクロファンのMicroPythonファームウェアでは、このように機能名でLEDを指定できるので、端子番号を調べたり、移植の際に端子番号を変更したりする必要がありません。

LEDの点滅

LEDを一定間隔で点滅するプログラムを示します。

from machine import Pin
import time

led1 = Pin('LED1', Pin.OUT)
while True:
    led1.on()
    time.sleep_ms(1000) # 1000ms, 1秒待つ
    led1.off()
    time.sleep_ms(1000)

# CTRL-Cで中断

LEDの明暗制御

LEDはPWMを使用して、単純に点灯、消灯だけでなく、明暗の度合いを制御できます。

PWMを使用してLEDの明暗を制御するプログラムを示します。

from machine import Pin, PWM
import time

led1 = PWM(Pin('LED1'), freq=1000)

delta = 100
duty = 0
while True:
    duty += delta
    if duty == 65500:
        delta = -100
    elif duty == 0:
        delta = 100
    led1.duty_u16(duty) # 0-65535
    time.sleep_ms(2)

# CTRL-Cで中断

LEDをPWMで制御するように初期化し、Whileループの中で、PWMのデューティー比を増減させて、LEDの明暗を変化させています。


スイッチ

アプリケーションで使用できるスイッチは、RP2040-UNOには装備されていません。

スイッチによるLEDの点灯

スイッチを押したときにLEDが点灯し、スイッチを離したときにLEDが消灯するプログラムを以下に示します。

from machine import Pin

led1 = Pin('LED1', Pin.OUT)
sw1 = Pin('SW1', Pin.IN)
while True:
    led1.value(not sw1.value())

# CTRL-Cで中断

スイッチもLEDと同様に、端子番号で指定・制御することができますが、マイクロファンのファームウェアでは、SW1に'SW1'という機能名が割り当てられているため、その機能名で端子を指定することができます。

RP2040-UNO-PLUSのSW1は負論理となっており、スイッチが押されたときにoffもしくは0、離されている時にonもしくは1となります。このプログラムでは、正論理のLEDを接続している場合のもので、負論理のスイッチの読み取り結果を 'not' を付けて正論理に変換してLEDの引数としています。


圧電スピーカー

アプリケーションで使用できる圧電スピーカーは、RP2040-UNOには装備されていません。

明るく光るLEDは出力装置として魅力的ですが、音を出す圧電スピーカーも電子工作では外せませんね。圧電スピーカーは圧電素子を使ったスピーカーで、RP2040-UNO-PLUSに搭載されているものは直径が1センチ程度の小さなものです。

圧電スピーカーを操作するTONEドライバーは、マイクロファンのファームウェアにあらかじめ組み込まれているため、改めて導入する必要などはありません。

RP2040-UNOには、初期状態では搭載されていませんが、必要に応じて購入して適当な端子(出力端子)に接続して使用することができます。

異なる周波数の音の出力

周波数が100Hzから1000Hzまで、100Hzごとに周波数を上げて音を出力するプログラム例を示します。(実際に出力される音(の高さ)は、圧電スピーカーの特性によるのか、ちょっと違和感があります。)

RP2040-UNO-PLUSの圧電スピーカーを使用する場合のプログラム例を示します。RP2040-UNOで圧電スピーカーを使用する場合には、TONEの引数として、圧電スピーカー接続した端子の端子番号か端子名を指定してください。

from tone import TONE
import time

snd = TONE('SND') # RP2040-UNOの端子に接続した場合にはその端子番号か端子名

for hz in range(100,1001,100): # 100Hz -1000Hz
    snd.on(hz)
    time.sleep_ms(500)
    
snd.off()

RP2040-UNO-PLUS用のファームウェアを使用している場合、圧電スピーカーが接続されている端子には'SND'という機能名が割り当てられているので、25のような端子番号の代わりに、'SND'を指定できます。

スイッチによる音の出力

スイッチを押すと音が鳴るプログラム例を示します。

from machine import Pin
from tone import TONE
import time

snd=TONE('SND') # RP2040-UNOの端子に接続した場合にはその端子番号か端子名
sw1=Pin('SW1', Pin.IN)

while True:
    if (sw1.value() == 0): # スイッチが押されたとき
        snd.on(400)
    else:
        snd.off()
    time.sleep_ms(100)

# CTRL-Cで中断

カエルの歌

TONEでは、音の周波数だけでなく音名を指定することができます。

皆様ご存じカエルの歌です。お楽しみください。

以下のサイトの音符を利用させていただきました。

from tone import TONE
import time

snd=TONE('SND')

kaeru = [ 'ド4', 'レ4', 'ミ4', 'ファ4', 'ミ4', 'レ4', 'ド4', 'ド4',
'ミ4', 'ファ4', 'ソ4', 'ラ4', 'ソ4', 'ファ4', 'ミ4', 'ミ4',
'ド4', '休符', 'ド4', '休符', 'ド4', '休符', 'ド4', '休符', 
'ド4', 'レ4', 'ミ4', 'ファ4', 'ミ4', 'レ4', 'ド4', 'ド4']

for s in kaeru:
    snd.on(s)
    time.sleep_ms(400)

snd.off()

圧電スピーカーの周波数特性なのか、方形波の高調波成分のせいなのか、そもそも、周波数リストの数値誤りなのか、ちょっと違う感じもありますが、楽しめましたか?

それから、音符の長さを一定にしている都合で、あからさまに表現が異なるところがありますがご容赦ください。:-P


OLEDディスプレイ

OLEDディスプレイは、CN6に接続して使用します。

OLEDディスプレイへの文字表示

OLEDディスプレイに文字列を表示するプログラム例です。

I2Cクラスの引数は、複数あるI2Cチャネルの番号を指定するだけで、具体的な端子などを指定する必要はありません。RP2040-UNO(-PLUS)のCN6にOLEDディスプレイを接続する場合には、0番を指定します。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)

oled.text('-RP2040-UNO-', 8, 0)
oled.text('MicroFan', 32, 8)
oled.text('OLED Display', 0, 16)
oled.text('Piezo Speaker', 0, 24)
oled.text('Brightness SNSR', 0, 32)
oled.text('Temp. Hum. SNSR ', 0, 40)
oled.text('Accelerometer', 0, 48)
oled.text('WS2812 RGB LED', 0, 56)
oled.show()

OLEDディスプレイへの日本語表示

OLEDディスプレイに日本語列を表示するプログラム例です。

日本語表示機能を持ったOLEDドライバoledjpや日本語フォントは、MicroPythonのファームウェアにあらかじめ組み込まれていますので、それらの導入作業をしなくても、プログラムを動かすことができます。

oledjpは、ssd1306の上位互換ドライバとなっていますので、ssd1306ドライバを使っているプログラムでは、日本語を使っていなくてもssd1306をoledjpに置き換えてもかまいません。

from machine import I2C
from oledjp import OLEDJP_I2C

i2c = I2C(0)
oled = OLEDJP_I2C(128, 64, i2c) # 日本語表示機能付きOLEDドライバ
oled.setFont(OLEDJP_I2C.MISAKI) # 日本語フォントの利用設定

str = "マイクロファンのSTM32開発ボードにはフラッシュが8MB装備されています。また開発ボード上に直接OLEDやTFTのディスプレイを接続でき、開発ボード単体でセンサの値や処理結果などを手軽に表示できます。WS2812BカラーLEDも装備しています。"
oled.print(str)

OLEDドライバoledjpに関しては以下のページをご参照ください。

OLEDディスプレイへのグラフィックス表示

OLEDディスプレイにグラフィックス表示するプログラム例です。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import time

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)

oled.fill(0) # 画面のクリア
for y in range(0,64,8):
    oled.line(0,0,127,y,1) # 斜線
    oled.show()

for x in range(127,0,-8):
    oled.line(0,0,x,63,1) # 斜線
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(0,32,4):
    oled.rect(64-n*2,32-n,n*4,n*2,1) # 方形
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(0,32,2):
    oled.fill_rect(64-n*2,32-n,n*4,n*2,1) # 塗潰し方形
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(2,32,2):
    oled.ellipse(64,32,n*4,n*2,1) # 楕円
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(2,18,2):
    oled.ellipse(64,32,n*4,n*2,1,True) # 塗潰し楕円
    oled.show()


TFTディスプレイ

TFTディスプレイは、CN5に接続して使用します。

TFTディスプレイへの文字表示

TFTディスプレイに文字列を表示するプログラム例です。

SPIクラスの引数は、複数あるSPIチャネルの番号を指定するだけで、具体的な端子などを指定する必要はありません。RP2040-UNO(-PLUS)のCN5にTFTディスプレイを接続する場合には、0番を指定します。

一方で、TFTクラスの初期化時には、いくつかの制御用の端子と、画面のピクセル数を指定する必要があります。

from st7735v2 import TFT
from sysfont import sysfont
from machine import SPI,Pin

spi = SPI(0, baudrate=25_000_000)

tft=TFT(spi,'SPI0_DC','SPI0_MISO','SPI0_CS',(128,128))
tft.initb2() # TFTの初期化、画面の端にノイズが出るようであれば変更
# tft.initr()
tft.rgb(False) # 色の並び
# tft.rgb(True)
tft.rotation(0) # 0-3, 画面の回転

tft.fill(TFT.BLACK)

v = 0
tft.text((0, v), "MicroFan", TFT.GREEN, sysfont, 2)
v += sysfont["Height"] * 2
tft.text((0, v), "RP2040-UNO", TFT.YELLOW, sysfont, 2)
v += sysfont["Height"] * 3
tft.text((0, v), "RP2040 133MHz", TFT.WHITE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "16KROM, 264KRAM", TFT.CYAN, sysfont)
v += sysfont["Height"]
tft.text((0, v), "8M Flash FS", TFT.CYAN, sysfont)
v += sysfont["Height"] * 2
tft.text((0, v), "OLED Display", TFT.PURPLE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "TFT Display", TFT.PURPLE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "WS2812B RGB LED", TFT.RED, sysfont)
v += sysfont["Height"] * 2
tft.text((0, v), "RP2040-UNO-PLUS", TFT.WHITE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "TEMP,HUM,ACC,BRT SNSR", TFT.WHITE, sysfont)

気温・湿度センサー

気温・湿度センサーAHT21と明るさセンサーは、RP2040-UNOには装備されていません。

気温・湿度センサーAHT21のドライバーに関しては以下のページをご参照ください。

気温・湿度・明るさ表示

OLEDディスプレイに気温・湿度センサーAHT21で得られた気温と湿度、明るさセンサー(フォトトランジスタ)で得られた明るさを表示するプログラム例です。

AHT21はI2Cで接続されており、OLEDディスプレイと同じ0番チャネルに接続されています。

明るさは、フォトトランジスタの出力電圧をAD変換で読み取って表示しています。明るさの範囲は0-1で、1に近い方が明るい状態を表します。

from machine import Pin, I2C, ADC
import time
from ssd1306 import SSD1306_I2C
from aht21 import AHT21

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
aht21 = AHT21(i2c)
brt = ADC(Pin('BRT'))

while True:
    oled.fill(0)
    oled.text('TEMP: {:.1f}\''.format(aht21.temperature),0,0)
    oled.text('HUM: {:.1f}%'.format(aht21.relative_humidity),0,16)
    oled.text('BRT: {:.3f}'.format(brt.read_u16()/65535),0,32)
    oled.show()
    time.sleep_ms(1000)

# CTRL-Cで終了

加速度センサー

加速度センサーKXTJ3は、RP2040-UNOには装備されていません。

加速度センサーKXTJ3のドライバーに関しては以下のページをご参照ください。

3軸の傾きを3個のカラーLEDで表示

加速度センサーのKXTJ3ドライバーは、3軸の加速度の計測値をそれぞれ-32768-32767の範囲で返します。また、計測加速度の設定値は2-16Gで設定できますが、初期状態では2Gの設定になっています。加速度の方向は、X軸が基板の縦方向、Y軸が横方向、Z軸が上下方向になっています。

以下のプログラムでは、各軸に対応するカラーLEDが、各軸の加速度がほぼ0の場合に青、正の値だと大きいほど明るい赤、負の値だと絶対値が大きいほど明るい緑に光ります。

水平の机の上などに基板を置くと、X,Y軸に対応する1番目と2番目のカラーLEDが青色に光ります。

from machine import Pin, I2C
from kxtj3 import KXTJ3
from neopixel import NeoPixel
import time

i2c = I2C(0)
acc = KXTJ3(i2c)

rgb = NeoPixel(Pin('RGB', Pin.OUT), 3) # 3ピクセル用の NeoPixel ドライバーをRGB端子に設定

while True:
    vacc = acc.getXYZ()
    x = int(vacc[0] / 32768 * 255) # 最大変位量を255に
    y = int(vacc[1] / 32768 * 255)
    z = int(vacc[2] / 32768 * 255)
    if abs(x) < 10: # ほぼ水平
        rgb[0] = (0,0,100) # 青で表示
    elif x > 0:
        rgb[0] = (x,0,0) # 傾きに応じて赤で表示
    else:
        rgb[0] = (0,-x,0) # 傾きに応じて緑で表示
    if abs(y) < 10:
        rgb[1] = (0,0,100)
    elif y > 0:
        rgb[1] = (y,0,0)
    else:
        rgb[1] = (0,-y,0)
    if abs(z) < 10:
        rgb[2] = (0,0,100)
    elif z > 0:
        rgb[2] = (z,0,0)
    else:
        rgb[2] = (0,-z,0)
    rgb.write() # 全ピクセルにデータ書込み
    time.sleep_ms(100)

傾き表示

OLEDディスプレイに3軸の加速度と、基板の傾きを表示するプログラム例です。

加速度センサーKXTJ3はI2Cで接続されており、OLEDディスプレイと同じ0番チャネルに接続されています。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
from kxtj3 import KXTJ3
import time
import math

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
acc = KXTJ3(i2c)

while True:
    oled.fill(0)
    vacc = acc.getXYZ()
    oled.text('X: {:.2f}'.format(vacc[0] / 16384), 0, 0)
    oled.text('Y: {:.2f}'.format(vacc[1] / 16384), 0, 16)
    oled.text('Z: {:.2f}'.format(vacc[2] / 16384), 0, 32)
    t = math.degrees(math.atan2(-vacc[1], vacc[0]))
    oled.text('DEG: {:.1f}'.format(t), 0, 48, 1)
    oled.show()
    time.sleep_ms(100)

水平儀

OLEDディスプレイに水平線を表示する(いわゆる水平儀)プログラム例です。

from machine import Pin, I2C
import time
from ssd1306 import SSD1306_I2C
from kxtj3 import KXTJ3
import math

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
acc = KXTJ3(i2c)

while True:
    oled.fill(0)
    vacc = acc.getXYZ()
    x = int(vacc[0] / 16384 * 40)
    y = int(vacc[1] / 16384 * 40)
    oled.line(64-x,32-y,64+x,32+y,1)
    oled.ellipse(64,32,40,40,1)
    t = math.degrees(math.atan2(-vacc[1], vacc[0]))
    oled.text('{:4.1f}'.format(t), 45, 36)
    oled.show()
    time.sleep_ms(100)

WS2812カラーLED

RP2040-SLIMは1個のカラーLEDのみを実装しています。

RGB表示

3個のWS2812タイプのカラーLEDに赤、緑、青色を出力するプログラム例です。

各LEDの明るさは、0-255の範囲で指定できますが、LEDの点灯確認目的であれば、10程度の明るさ指定でも十分な明るさで発光します。

# Ws2812 カラーLEDの点灯
from neopixel import NeoPixel
from machine import Pin

rgb = NeoPixel(Pin('RGB', Pin.OUT), 3)
rgb[0] = (10,0,0) # 赤
rgb[1] = (0,10,0) # 緑
rgb[2] = (0,0,10) # 青
rgb.write() # 全ピクセルにデータ書込み

neopixelライブラリの利用法は、以下のページをご参照ください。

1/fゆらぎを利用したLEDキャンドル

1/fゆらぎを利用して、1個のカラーLEDをキャンドルの様に光らせるプログラム例です。

カラーLEDマトリックス表示

CN4のRGB (24)にカラーLEDマトリックスを接続して使用することができます。カラーLEDマトリックスを利用すると、カラーLEDで文字やグラフィックス表示ができるようになります。

カラーLEDマトリックスはLEDMATRIXライブラリで操作することができ、LEDMATRIXライブラリは専用ファームウェアにあらかじめ組み込まれているので、事前の準備などなく使用することができます。

端子の信号線の電圧がWS2812Bに必要な5Vではなく3.3Vになってしまい定格での使用外(推奨はしませんが、ほとんどの場合うまく動くようです。)となってしまいますが、カラーLEDマトリックスは、他の端子に接続することもできます。特にCN2, CN3は、RCサーボの接続を意図したものですが、信号線の他に5Vの電源も接続されており、カラーLEDマトリックスの接続にうってつけです。

CN2に8x8のカラーLEDマトリックスを接続したプログラム例を次に示します。

from ledmatrix import LEDMATRIX
import time

# 8x8のカラーLEDマトリックスを使用
lmx = LEDMATRIX(1,8,8) # RP2040-UNO, CN2

lmx.line(0,0,7,7,LEDMATRIX.BLUE)
lmx.line(0,7,7,0,LEDMATRIX.BLUE)
lmx.show()
time.sleep_ms(1000)
lmx.rect(0,0,8,8,LEDMATRIX.GREEN)
lmx.show()
time.sleep_ms(1000)
lmx.text('A',0,0,LEDMATRIX.RED)
lmx.show()

カラーLEDマトリックスへの日本語表示

カラーLEDマトリックスで日本語表示することもできます。

カラーLEDマトリックスでの日本語表示はLEDMATRIXJPライブラリで行うことでき、LEDMATRIXJPライブラリは専用ファームウェアにあらかじめ組み込まれているので、事前の準備などなく使用することができます。