LoginSignup
1
1

More than 1 year has passed since last update.

CircuitPythonでステッピングモーター(28BYJ-48)を動かすライブラリを書いてみた

Posted at

28BYJ-48って何?

これのことです。

Ren He 5V ステッピングモータ+ 28BYJ-48 ULN2003ドライバーボード セット Arduino用 3個セット
https://www.amazon.co.jp/Ren-He-%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF-28BYJ-48-ULN2003%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89/dp/B07LBRNZB6

667D2290-DE9A-48BA-B989-61895D9BC088.jpeg

28BYJ-48というステッピングモーターと、ULN2003なるトランジスタアレイとやらが搭載されたドライバーボードです。Arduino言語やMicroPythonにてこれを用いている作例はweb上でいくつか見つかるのですが、CircuitPythonでは見つかりませんでした。

そこで今回、これをCircuitPythonでどうにか動かすためのライブラリを書いてみましたので、備忘録も兼ねてこちらに置いておこうと思います。

コード

その手作りライブラリがこちら。

lib/CPython_28BYJ48_ULN2003.py
import digitalio, time

"""
このステッピングモーターの場合、
1ステップは`5.625° /64`なようなので、
64ステップで`5.625°`、
512ステップで`45°`、
4096ステップで`360°`、即ち1周分となります。
"""
deg45 = 512
deg90 = 1024
deg180 = 2048
deg360 = 4096

class stepper:
    def __init__(self, IN1, IN2, IN3, IN4):
        self.DIG_OUT = [
            digitalio.DigitalInOut(pin) for pin in [IN1, IN2, IN3, IN4]
        ]
        for p in self.DIG_OUT:
            p.direction = digitalio.Direction.OUTPUT
        self.SEQ_CLOCK = [
            [1, 0, 0, 1],
            [1, 0, 0, 0],
            [1, 1, 0, 0],
            [0, 1, 0, 0],
            [0, 1, 1, 0],
            [0, 0, 1, 0],
            [0, 0, 1, 1],
            [0, 0, 0, 1]
        ]
        self.POSITION = 0
        self.STEP_COUNT = len(self.SEQ_CLOCK)
        self.STEP_DIR = 1
        self.STEP_COUNTER = 0

    def rotate(self, clockwise=True, LIMIT=deg180):
        COUNT = 0
        SEQ = self.SEQ_CLOCK if clockwise else self.SEQ_CLOCK[::-1]
        while COUNT < LIMIT:
            COUNT += 1
            for i in range(0, 4):
                pin = self.DIG_OUT[i]
                pin.value = SEQ[self.STEP_COUNTER][i] != 0
            self.STEP_COUNTER += self.STEP_DIR
            if self.STEP_COUNTER >= self.STEP_COUNT:
                self.STEP_COUNTER = 0
            if self.STEP_COUNTER < 0:
                self.STEP_COUNTER = self.STEP_COUNT + self.STEP_DIR
            # sleepを挟まないと、モーターが不穏な音をたてながらビクンビクン震えます。絶対に抜かないように。
            time.sleep(0.0005)
        self.POSITION += LIMIT if clockwise else (-1 * LIMIT)

    def reset(self):
        if self.POSITION < 0:
            self.rotate(True, (-1 * self.POSITION) % deg360)
        else:
            self.rotate(False, self.POSITION % deg360)

これをこう!

code.py
import board, digitalio
# 先程のライブラリをインポート
from CPython_28BYJ48_ULN2003 import *

# タクトスイッチ
switch = digitalio.DigitalInOut(board.GP18)
switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

motor = stepper(
    board.GP14, # IN1に繋いでいるピン
    board.GP15, # IN2
    board.GP16, # IN3
    board.GP17  # IN4
)

while True:
    # タクトスイッチを押したとき
    if not switch.value:
        # (時計回りかどうか, ステップ数)
        motor.rotate(False, deg45)
        # 初期化時の位置に戻る
        motor.reset()

サンプルコードの通りに動かすと、モーターは車のワイパーのような動きをします。

ドライバーにはIN1, IN2, IN3, IN4, VCC (+), GND (-)がありますので、前者4つをデジタル出力が可能なピンに、後者2つを5Vの電源供給に繋げて下さい。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1