RP2040-UNOまたはSTM32-UNOにDML-STACK3Vを接続した場合を例として、MicroPythonでのDML-STACKのプログラミング例を紹介します。

DML-STACK3V + RP2040-UNO

これらのプログラミング例は、RP2040-UNOに弊社のMicroPythonのファームウェアを書き込んでいることを前提としています。

ドットマトリックスLEDの全点点灯

DML-STACKのドットマトリックスLEDは、操作に必要な信号線を削減するために、ダイナミック表示方式を取っています。このため、信号線の単純な操作では、横一列の8個のLEDのみを点灯させることができません。

まずは、ダイナミック表示方式で、ドットマトリックスLEDを全点点灯させる例を示します。

from machine import Pin
import time

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

for i in range(0,8):
    row[i].off()

# 表示するカラムを高速に切り替えダイナミック表示を行う
while True:
    for i in range(0,8):
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        time.sleep_ms(2)

最後の行のsleep_ms()の引数2を1000などの大きな数に変更すると、横一列の8個のLEDずつ点灯され、点灯される列が順番に切り替わる様子を確認できます。

ドット絵の表示

上記の例では、ドットマトリックスのすべてのLEDを点灯させましたが、任意のLEDの点灯・消灯を個別に制御する方法を示します。具体的には、単純な8x8ドットのモノクロのドット絵のデータを0,1で定義したデータ配列を定義し、0は消灯、1は点灯でLEDの表示を行う例を示します。

from machine import Pin
import array
import time

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [
                    0b00111100,
                    0b01000010,
                    0b10100001,
                    0b11010111,
                    0b10000101,
                    0b10111001,
                    0b01000010,
                    0b00111100 ])

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

while True:
    for i in range(0,8):
        for r in range(0,8): # いったん全灯消灯
            row[r].on()
        col[0].value(i & 1)  # 表示対象行を変更
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8): # 新たな行に対応した点灯データを設定
            row[r].value(not (matrix[7-i] & (1 << (7-r))))
        time.sleep_ms(2)

matrixに記録されるデータの0,1を書き換えることにより、望みの絵を表示させることができます。この場合も、最後のsleep_ms()の2を大きな数に変更することにより、ドット絵の横一列の8個のLEDずつ点灯され、点灯される列が順番に切り替わる様子を確認できます。

文字表示

A,B,Cの3種類だけですが、ドットマトリックスLEDに文字を表示させる例を示します。

from machine import Pin
import array
import time

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

# フォントデータ
font = array.array('B',
                   [0b00010000, # A
                    0b00101000,
                    0b01000100,
                    0b01000100,
                    0b01111100,
                    0b01000100,
                    0b01000100,
                    0b00000000,
                    0b01111000, # B
                    0b01000100,
                    0b01000100,
                    0b01111000,
                    0b01000100,
                    0b01000100,
                    0b01111000,
                    0b00000000,
                    0b00111000, # C
                    0b01000100,
                    0b01000000,
                    0b01000000,
                    0b01000000,
                    0b01000100,
                    0b00111000,
                    0b00000000,
                    ])

# フォントデータを表示バッファに書き込む
def set_font(n):
    for i in range(0,8):
        matrix[i] = font[n*8+i]

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

fi = 0
ct = time.ticks_ms() // 1000
while True:
    lt = ct
    ct = time.ticks_ms() // 1000
    if lt != ct: # 1秒に1回
        set_font(fi)
        fi += 1
        if fi > 2:
            fi = 0
    for i in range(0,8):
        for r in range(0,8):
            row[r].on()
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8):
            row[r].value(not (matrix[7-i] & (1 << (7-r))))
        time.sleep_ms(2)

ボールの表示

ボール(点)を表示する例を示します。ドットマトリックスLEDの左上を原点として、指定した座標のLEDを点灯させる方法が確認できます。

from machine import Pin
import array
import time

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

def display_ball(x, y):
    for i in range(0,8): # まず全灯消灯
        matrix[i] = 0
    matrix[y] = 1 << x   # 指定座標のLEDを点灯

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

# 左上が原点、座標値を変えて表示を確認して!
display_ball(0,0)

while True:
    for i in range(0,8):
        for r in range(0,8):
            row[r].on()
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8):
            row[r].value(not (matrix[7-i] & (1 << r)))
        time.sleep_ms(2)

display_ball(x,y)の引数を変更して、指定した座標のLEDが点灯することを確認してみてください。

ボールの移動操作:スイッチと圧電スピーカーの利用

表示されているボールを、スイッチを使って移動操作するプログラムを示します。

  • sw1を押すと上に、sw3を押すと下に移動
  • sw2を押した状態で、sw1を押すと左に、sw3を押すと右に移動

スイッチの初期化の際には、入力に設定するだけでなく内部プルアップも有効にします。これは、スイッチが接続されているA0-A2の信号線に外部プルアップ抵抗が接続されていないためです。外部プルアップ抵抗が接続されていないため、今回のプログラムと異なりスイッチを使用しないのであれば、A0-A2はデジタル入出力や、アナログ入力に使用することができます。(信号線を取り出しにくいですが…)

このプログラムでは、ボールがドットマトリックスLEDの上下左右の端にぶつかるとビープ音を出すようにしています。

from machine import Pin
import array
import sys
import time
from tone import TONE

if sys.platform.startswith('rp2'):
    snd = TONE('A3') #RP2040-UNO
else:
    snd = TONE('PA7') # STM32-UNO

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

def display_ball(x, y):
    for i in range(0,8):
        matrix[i] = 0
    matrix[y] = 1 << x

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

sw1 = Pin('A0', Pin.IN, Pin.PULL_UP) # 内部プルアップを有効化
sw2 = Pin('A1', Pin.IN, Pin.PULL_UP)
sw3 = Pin('A2', Pin.IN, Pin.PULL_UP)

bx = 3
by = 3
ct = time.ticks_ms() // 50
while True:
# ボールの位置の更新
    lt = ct
    ct = time.ticks_ms() // 50
    if lt != ct: # 0.05秒に1回
        if (sw1.value() == False) and (sw2.value() == False):
            bx += 1
            if bx > 7:
                snd.on(1000)
                bx = 7
                time.sleep_ms(5)
                snd.off()
        elif (sw3.value() == False) and (sw2.value() == False):
            bx -= 1
            if bx < 0:
                snd.on(1000)
                bx = 0
                time.sleep_ms(5)
                snd.off()
        if (sw1.value() == False) and (sw2.value() == True):
            by += 1
            if by > 7:
                snd.on(1000)
                by = 7
                time.sleep_ms(5)
                snd.off()
        elif (sw3.value() == False) and (sw2.value() == True):
            by -= 1
            if by < 0:
                snd.on(1000)
                by = 0
                time.sleep_ms(5)
                snd.off()
        display_ball(bx,by)
    # ダイナミック表示処理
    for i in range(0,8):
        for r in range(0,8):
            row[r].on()
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8):
            row[r].value(not (matrix[7-i] & (1 << r)))
        time.sleep_ms(2)

ボールの跳ね返り

ドットマトリックスLED内で、ボールを壁で跳ね返らせ、壁に当たるたびに衝突音を出す例を示します。

from machine import Pin
import array
import sys
import time
from tone import TONE

if sys.platform.startswith('rp2'):
    snd = TONE('A3') #RP2040-UNO
else:
    snd = TONE('PA7') # STM32-UNO

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

def display_ball(x, y):
    for i in range(0,8):
        matrix[i] = 0
    matrix[y] = 1 << x

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

bx = 0
dx = 0.6
by = 0
dy = 0.4
ct = time.ticks_ms() // 50
while True:
    # ボールの位置の更新
    lt = ct
    ct = time.ticks_ms() // 50
    if lt != ct: # 0.05秒に1回
        bx += dx
        by += dy
        if (bx > 8) or (bx < 0):
            snd.on(1000)
            dx = -dx
            bx += dx
            time.sleep_ms(5)
            snd.off()
        if (by > 8) or (by < 0):
            snd.on(1000)
            dy = -dy
            by += dy
            time.sleep_ms(5)
            snd.off()
        display_ball(int(bx),int(by))
    # ダイナミック表示処理
    for i in range(0,8):
        for r in range(0,8):
            row[r].on()
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8):
            row[r].value(not (matrix[7-i] & (1 << r)))
        time.sleep_ms(2)

ボールの転がり:加速度センサーの利用

DML-STACKに搭載されている加速度センサーを利用して、基板を傾けた方にボールが転がる例を示します。

from machine import Pin, I2C
import array
import sys
import time
from kxtj3 import KXTJ3
from tone import TONE

i2c = I2C(1)
acc = KXTJ3(i2c)

if sys.platform.startswith('rp2'):
    snd = TONE('A3') #RP2040-UNO
else:
    snd = TONE('PA7') # STM32-UNO

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

def display_ball(x, y):
    for i in range(0,8):
        matrix[i] = 0
    matrix[y] = 1 << x

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))

bx = 0
by = 0
ct = time.ticks_ms() // 50
while True:
# ボールの位置の更新
    lt = ct
    ct = time.ticks_ms() // 50
    if lt != ct: # 0.05秒に1回
        vacc = acc.getXYZ()
        ax = int(vacc[0] / 32768 * 255) # 最大変位量を255に
        ay = int(vacc[1] / 32768 * 255)

        if ay < -10:
            bx += 1
            if bx > 7:
                snd.on(1000)
                bx = 7
                time.sleep_ms(5)
                snd.off()
        elif ay > 10:
            bx -= 1
            if bx < 0:
                snd.on(1000)
                bx = 0
                time.sleep_ms(5)
                snd.off()
        if ax > 10:
            by += 1
            if by > 7:
                snd.on(1000)
                by = 7
                time.sleep_ms(5)
                snd.off()
        elif ax < -10:
            by -= 1
            if by < 0:
                snd.on(1000)
                by = 0
                time.sleep_ms(5)
                snd.off()
        display_ball(int(bx),int(by))
    # ダイナミック表示処理
    for i in range(0,8):
        for r in range(0,8):
            row[r].on()
        col[0].value(i & 1)
        col[1].value(i & 2)
        col[2].value(i & 4)
        for r in range(0,8):
            row[r].value(not (matrix[7-i] & (1 << r)))
        time.sleep_ms(2)

タイマー割り込みの利用

ドット絵の表示

ダイナミック表示の表示行の更新処理をタイマー割り込みで行う例を示します。

from machine import Pin, Timer
import array
import time

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [
                    0b00111100,
                    0b01000010,
                    0b10000001,
                    0b11101111,
                    0b10000001,
                    0b10100101,
                    0b01011010,
                    0b00111100 ])

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))
rowix = 0

def dml_refresh(t):
    global col, row, rowix, matrix
    for r in range(0,8): # いったん全灯消灯
        row[r].on()
    col[0].value(rowix & 1)  # 表示対象行を変更
    col[1].value(rowix & 2)
    col[2].value(rowix & 4)
    for r in range(0,8): # 新たな行に対応した点灯データを設定
        row[r].value(not (matrix[7-rowix] & (1 << (7-r))))
    rowix += 1
    if rowix > 7:
        rowix = 0

timer = Timer()
timer.init(period=2, callback=dml_refresh)

文字の表示

from machine import Pin, Timer
import array
import time

# ドットマトリックスに表示するデータバッファ
matrix = array.array('B',
                   [0, 1, 3, 7, 15, 31, 63, 127])

# ドットマトリックスLEDのカラム端子を出力に設定
col = []
for i in range(2,5):
    col.append(Pin('D'+str(i), Pin.OUT))
# ドットマトリックスLEDのロウ端子を出力に設定
row = []
for i in range(5,13):
    row.append(Pin('D'+str(i), Pin.OUT))
rowix = 0

def dml_refresh(t):
    global col, row, rowix, matrix
    for r in range(0,8): # いったん全灯消灯
        row[r].on()
    col[0].value(rowix & 1)  # 表示対象行を変更
    col[1].value(rowix & 2)
    col[2].value(rowix & 4)
    for r in range(0,8): # 新たな行に対応した点灯データを設定
        row[r].value(not (matrix[7-rowix] & (1 << (7-r))))
    rowix += 1
    if rowix > 7:
        rowix = 0

# ここまでは前のプログラムと同じ

# フォントデータ
font = array.array('B',
                   [0b00010000, # A
                    0b00101000,
                    0b01000100,
                    0b01000100,
                    0b01111100,
                    0b01000100,
                    0b01000100,
                    0b00000000,
                    0b01111000, # B
                    0b01000100,
                    0b01000100,
                    0b01111000,
                    0b01000100,
                    0b01000100,
                    0b01111000,
                    0b00000000,
                    0b00111000, # C
                    0b01000100,
                    0b01000000,
                    0b01000000,
                    0b01000000,
                    0b01000100,
                    0b00111000,
                    0b00000000,
                    ])

timer = Timer()
timer.init(period=2, callback=dml_refresh)

# フォントデータを表示バッファに書き込む
def set_font(n):
    for i in range(0,8):
        matrix[i] = font[n*8+i]

fi = 0
while True:
    set_font(fi)
    fi += 1
    if fi > 2:
        fi = 0
    time.sleep_ms(1000)

関連製品

DML-STACK

RP2040-UNO

STM32-UNO

STM32-UNOには、MCUの異なるいくつかの開発ボードがあります。どの開発ボードも同様にDML-STACKのプログラミングを楽しむことができます。