MicroPythonでDF-ROBOT micro:bit Driver Expansion Board(v2.0)を使う

DF-ROBOTのmicro:bit Driver Expansion Board(v2.0)は、安価な割に機能の多いモーター制御ボードである。

https://www.dfrobot.com/product-1738.html

micro:bit 上のGPIOへのアクセスに加えて、8個のサーボモータと4個のDCモータを独立して制御することができる。(全てを使った訳ではないが)

ただ、制御のためのプログラムを作成するには MakeCode なりのブロックプログラミング環境を必要としており、MicroPython で使えるコードを見つけることができなかった。

https://github.com/DFRobot/pxt-motor

このボードは PCA9685 という定番のサーボドライバを使っており、I2C接続で何とかなると思ったら、何とかなったので記事にした。

後述するプログラムリストは、上のMakeCodeブロック対応コードに、SG90へ対応するよう修正を加えた Javascript のプログラムを、micro:bit用の MicroPython に移植しただけの単純なものである。参考にしたのはこちら。

https://github.com/nekoma-seisakusho/pxt-motor

ポイントは、サーボモータもDCモータもPCA9685を使って制御するということである。当初、DCモータドライバもI2Cで別に接続されているかと思って調べていたのだが、PWM入力のDCモータドライバに、PCA9685のPWM出力をつなげたもののようだ。ちなみにDCモータドライバとして、HR8835 が2個使われている。

ということで、MicroPython のコードは以下の通り。

import microbit
import utime
initialized = False
def i2cWrite(addr, reg, value):
    buf = [0, 0]
    buf[0] = reg
    buf[1] = value
    microbit.i2c.write(addr, bytes(buf))
def i2cRead(addr, reg):
    microbit.i2c.write(addr, bytes([reg]))
    ret = microbit.i2c.read(addr, 1)
    return ret[0]
def initPCA9685():
    global initialized
    i2cWrite(64, 0, 0)
    oldmode = i2cRead(64, 0)
    newmode = (oldmode & 127) | 16
    i2cWrite(64, 0, newmode)
    i2cWrite(64, 254, 121)
    i2cWrite(64, 0, oldmode)
    utime.sleep_us(5000)
    i2cWrite(64, 0, oldmode | 161)
    initialized = True
def setPwm(channel, off):
    if channel < 0 or channel > 15:
        return
    print("setPWM",channel,off)
    buf = [0] * 5
    buf[0] = 6 + 4 * channel
    buf[1] = 0
    buf[2] = 0
    buf[3] = off & 255
    buf[4] = (off >> 8) & 255
    microbit.i2c.write(64, bytes(buf))
def Servo(index, degree):
    if not initialized:
        initPCA9685()
    value = (degree * 10 + 600) * 4095 // 20000
    setPwm(16 - index, value)
def MotorRun(index, speed):
    if index < 1 or index > 4:
        return
    if not initialized:
        initPCA9685()
    speed = speed * 16
    if speed >= 4096:
        speed = 4095
    if speed <= -4096:
        speed = -4095
    dp = speed
    dn = 0
    if speed < 0:
        dp = 0
        dn = -speed
    ch = (4 - index) * 2
    setPwm(ch + 1, dp)
    setPwm(ch, dn)

使い方は、Servo(チャネル番号, 角度) で、チャネル番号に1から8を、角度は数値を与えれば対応するサーボモータが動く。また、MotorRun(チャネル番号, 速度) で、チャネル番号に1から4を、速度に -255 から 255 の数値を与えればDCモータが動く。