対象開発ボード

STM32-UNO-PLUS

STM32-UNO


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

ドライバとライブラリ

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

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

専用ファームウェア

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

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

STM32-UNO(-PLUS)へのMicroPythonファームウェアの書き込み法は、以下のページを参照してください。


MicroPythonプログラミング

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

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

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

以下にMicroPythonのプログラム例を示しますが、合わせてMicroPythonのサイトのSTM32用クイックリファレンスのページもご参照ください。(STM32を使用したMicroPythonのリファレンスボードはpyboardと呼ばれています。このため、STM32の開発ボードの名前がpyboardと書かれています)

端子の割り当て

端子機能名端子名備考
SW1
SW2
PB10
PB1
負倫理
負論理、STM32-UNO-PLUSのみ
LED1
LED2
LED3
LED4, RGB
PB13
PA13
PA14
PB2
正論理
正論理
正論理
WS2812B(NeoPixel), CN4
I2C(3)OLEDディスプレイ、温度・湿度センサー、加速度センサー
SNDPC8 圧電スピーカー、STM32F446-UNO-PLUSのみ
SNDPB9 圧電スピーカー、STM32F412-UNO-PLUSのみ
BRTPB0明るさセンサー(フォトトランジスタ)、アナログ値、STM32-UNO-PLUSのみ

LED

LEDの点灯

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

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

from machine import Pin
import time

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

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

マイクロファンはいくつかのSTM32開発ボードを提供しており、開発ボードによって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の明暗を制御するプログラムを示します。

ここで使用しているPWMドライバーは、マイクロファンが提供しており専用ファームウェアに組み込まれているドライバーで、STM32用のオリジナルのMicroPythonには含まれていません。

from machine import Pin
from stm32pwm import PWM
import time

led1 = PWM('PB13', freq=1000) # LED2, LED3にはPWM機能がないので使えない

delta = 1
duty = 0
while True:
    duty += delta
    if duty == 100:
        delta = -1
    elif duty == 0:
        delta = 1
    led1.duty_percent(duty) # 0-100
    time.sleep_ms(5)

# CTRL-Cで中断

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

なお、LED2, LED3の端子PA13, PA14にはハードウェア的にPWMの機能が組み込まれていないので、PWMで明暗制御をすることはできません。


スイッチ

スイッチによる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'という機能名が割り当てられているため、その機能名で端子を指定することができます。

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


圧電スピーカー

アプリケーションで使用できる圧電スピーカーは、STM32-UNOには装備されていませんが、必要に応じて購入して適当な端子(出力端子)に接続して使用することができます。

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

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

異なる周波数の音の出力

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

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

from tone import TONE
import time

snd = TONE('SND') # 圧電スピーカーを他の端子に接続した場合にはその端子名

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

スイッチによる音の出力

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

TONEに指定する端子名は、STM32F446-UNO(-PLUS)では'PC8'、STM32F412-UNO(-PLUS)では'PB9'となります。

from machine import Pin
from tone import TONE
import time

snd=TONE('SND') # 圧電スピーカーを他の端子に接続した場合にはその端子名
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ディスプレイは、CN2に接続して使用します。

OLEDディスプレイを使用するためには、そのドライバーが必要ですが、マイクロファンのMicroPythonファームウェアには、あらかじめOLEDディスプレイ用のドライバーが内蔵されているので、そのインストール作業などを行うことなく利用することができます。

ここで使用例を示すssd1306の説明書を以下に示すので、参考にしてください。

OLEDディスプレイ表示用のドライバは、FrameBufferというクラスをベースに作成されています。したがって、OLEDディスプレイ表示用のドライバで使用できるメソッド(文字の表示やグラフィックス)の多くは、FrameBufferの説明書で確認することができます。以下にFrameBufferの説明書を示すので、参考にしてください。

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

コントローラにSSD1306を使用した0.96インチのOLEDディスプレイに文字列を表示するプログラム例を示します。

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

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

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

oled.text('-STM32-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()

ssd1306での文字出力は、文字を出力する座標を毎回指定する必要があります。グラフィックス表示と合わせて文字表示をする場合には役立ちますが、文字だけを出力する場合には、少々面倒です。

また、文字もグラフィックスも、表示の指示をしただけではOLEDディスプレイの画面に表示されず、show()メソッドを呼び出した時点で初めてすべての表示指示が画面に反映されます。

OLEDディスプレイへのコンソール的文字表示

何を言っているかわかりにくいのですが、OLEDディスプレイに文字を表示する際に、文字を表示する座標を明示せずに出力できる機能を備えたドライバを作成しました。oledcsもマイクロファンのMicroPythonファームウェアに組み込まれているので、導入作業などをせずに利用できます。

利用法は簡単で、単に出力したい文字列をprintln()あるいはprint()メソッドで出力するだけです。文字の出力位置は、ドライバが自動的に管理してくれますし、いちいちshow()メソッドを利用する必要もありません。

メッセージやデータをOLEDディスプレイに表示する場合には、ssd1306を使用するよりも、oledcsを使用したほうが手軽で便利でしょう。なお、oledcsはssd1306を継承して作成されているため、ssd1306の機能もそのまま利用できます。

from machine import I2C
from oledcs import OLEDCS_I2C
import time

i2c = I2C(3)
oled = OLEDCS_I2C(128, 64, i2c)

oled.println('123456789012345678901234567890')
time.sleep(3)

for i in range(1,20):
    oled.print('OLED-')
    oled.println('{:.3f}'.format(1/i))
time.sleep(3)

oled.println('OLEDCS Driver for MicroPython')

oledcsの詳細は、以下のページをご参照ください。

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

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

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

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

from machine import I2C
from oledjp import OLEDJP_I2C

i2c = I2C(3)
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ディスプレイへのグラフィックス表示

コントローラにSSD1306を使用した0.96インチのOLEDディスプレイにグラフィックス表示するプログラム例です。

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

i2c = I2C(3)
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ディスプレイは、CN3に接続して使用します。

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

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

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

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

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

spi = SPI(1, baudrate=25_000_000)

tft=TFT(spi,'SPI1_DC','SPI1_MISO','SPI1_CS',(128,128))
tft.initb2() # TFTの初期化、画面の端にノイズが出るようであれば変更
# tft.initr()
tft.rgb(False) # 色の並び
# tft.rgb(True)
tft.rotation(1) # 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), "STM32-UNO", TFT.YELLOW, sysfont, 2)
v += sysfont["Height"] * 3
tft.text((0, v), "STM32F446RE 180MHz", TFT.WHITE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "STM32F412RE 100MHz", TFT.WHITE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "512KROM, 256,128KRAM", 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), "STM32-UNO-PLUS", TFT.WHITE, sysfont)
v += sysfont["Height"]
tft.text((0, v), "TEMP,HUM,ACC,BRT SNSR", TFT.WHITE, sysfont)

気温・湿度センサー

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

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

気温・湿度・明るさ表示

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

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

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

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

i2c = I2C(3)
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は、STM32-UNOには装備されていません。

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

傾き表示

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

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

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

i2c = I2C(3)
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)
    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(3)
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

STM32-UNOは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をキャンドルの様に光らせるプログラム例です。

下記ページのプログラムでNeoPixelコンストラクタの引数として指定するLEDの端子機能名は、'LED4'に変更してください。

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

CN4のRGB (PB2) にカラー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('PA1',8,8) # STM32-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ライブラリは専用ファームウェアにあらかじめ組み込まれているので、事前の準備などなく使用することができます。