今までRaspberry Pi入門キットに付属のL293D ICチップを使ってDCモーターを回してきました。同梱品は不良品だったため、再購入してやっと回すことができました。さらに使いこなそうと試みましたがあっけなくICチップがお亡くなりになりました。(T T)
L293Dの仕様である最大電流600mA(ピーク1.2A)を超えてしまっていることに気づかず、チンチンにICが熱くなっていて指で触って確認した際に軽いやけどを負いました。破裂しなくて幸いでした。
L298Nブレークアウトモジュールの購入
そこでL293Dに代わるものをネットで探したところ、L298Nがあることがわかりました。こちらは最大電流2A、最大電圧35Vの高出力ドライバです。さらにヒートシンク、端子台、5Vレギュレータなど装備されたブレークアウトモジュール(基板)(※)として販売されていました。
※ブレークアウトモジュール(またはブレークアウトボード)は、集積回路(IC)やセンサーなどの部品を扱いやすくするための基板で、ICやセンサーのピン幅をブレッドボードなどのピン幅に変換して簡単にアクセスできるようにした基板です。
こちらが購入したL298Nブレークアウトモジュールです。中央後方の黒い塊がヒートシンクで前面にビスで固定されているのがL298N ICチップです。
ネット通販で2個、ケーブル付きで999円でした。
L298Nブレークアウトモジュールの使い方
- IN1, IN2: モーターAの入力ピン。モーターAの回転方向を制御するために使用します
- IN3, IN4: モーターBの入力ピン。モーターBの回転方向を制御するために使用します
- ENA: モーターAのPWM信号を入力することで、速度制御に使用します。購入時はジャンパキャップを使って5Vに接続されています。
- ENB: モーターBのPWM信号を入力することで、速度制御に使用します。購入時はジャンパキャップを使って5Vに接続されています。
- OUT1, OUT2: モーターAへの出力ピン
- OUT3, OUT4: モーターBへの出力ピン
- Vcc: DC電源からの7V(5V)~35Vの入力ピン
- +5V: L298N IC内部のスイッチングロジック回路の電源供給ピン
- GND: グランドピン
このブレークアウトモジュールには、注意しないといけない事項があります。
出荷時の状態では、Vcc、GND、+5Vの端子台の後ろにあるピンにジャンパーキャップがつけられています。これは、VccとGNDに7V~12Vまでの電源を入力している場合、+5VとGNDには、モジュールから5Vの電源として出力されることになります。出力端子になっていることに注意が必要です。これは Arduino(「アルデュイーノ」または「アルディーノ」と読みます)などへの電源として利用できます。
逆にジャンパーキャップを外した場合、このブレークアウトモジュールには、L298N ICへのロジック回路に対して+5VとGNDに5V電源を入力する必要があります。
このようにジャンパー有無によって出力と入力が切り替わるという、便利というか悩ましい仕様があります。
あともう少し注意が必要なのは、VccとGNDには最大35Vまで入力可能ですが、ジャンパーキャップを付けた際はVccとGNDに12Vまでで使用する必要があります。12Vを超える電圧をかけるとブレークアウトモジュール内のレギュレータICの耐電圧を超えるため壊れます。
L298Nブレークアウトモジュールを使った配線図
L298Nブレークアウトモジュールを使用した配線図です。L293D ICチップへの配線に比べて専用ピンや端子台があるので簡単です。モーター2個を使っていますがすっきりしています。
GPIOのピン番号とL298Nモジュールの制御ピン番号の対応表は以下の通りです。
ケーブルカラー | PIN No. | ドライバ PIN | 信号レベル | 動作 |
緑 | GPIO26 | ENA | PWM0~255 | モーターA速度制御 |
青 | GPIO19 | IN1 | H(L) | モーターA 正転(逆転) |
紫 | GPIO13 | IN2 | L(H) | |
灰 | GPIO22 | IN3 | H(L) | モーターB 正転(逆転) |
白 | GPIO27 | IN4 | L(H) | |
黒 | GPIO17 | ENB | PWM0~255 | モーターB速度制御 |
実際の配線
実際の配線図です。L298Nブレークアウトモジュールに同梱されていたジャンパーケーブルが大活躍すぐに使えるようになっています。赤と黒のワニ口クリップはDC安定化電源につながっています。黒い箱はRaspberry Piです。
DCモーター単体では、固定できないし回転しているのがわかりづらいので、タミヤのギヤボックスを購入しました。
タミヤの楽しい工作シリーズ NO.97 ツインモーターギヤーボックスです。モーター2個も付いています。
2セット購入しました。
中はこんな感じで自分で組み立てます。パーツは多そうですが図面通りに組み立てればできます。大事なのはグリスを丁寧にギヤーに塗り付けることです。そうすると静かに回ります。
合わせてタミヤの楽しい工作シリーズのスリムタイヤセット(36・55mm径)を3セット購入しました。これでモーターが回っていることが確認できます。
DCモーターを回すプログラム
ハードウェアが揃いましたので、モーターを回すためのプログラムを作成します。今までのプログラムを少し改造すればよさそうです。
# RPiGPIO制御用ライブラリの取り込み
import RPi.GPIO as GPIO
# GPIOPIN番号とL298NモジュールのPIN対応付け定義
ENA = 26
IN1 = 19
IN2 = 13
IN3 = 22
IN4 = 27
ENB = 17
#周波数とデューティ比の初期値定義
frequency = 1000
duty = 100
#モーターの回転方向の定義
CW = True
CCW = False
# ロータリーエンコーダーのPIN番号の定義
clkPin = 25 # CLK Pin
dtPin = 24 # DT Pin
swPin = 23 # Button Pin
globalCounter = 0
flag = 0
Last_dt_Status = 0
Current_dt_Status = 0
# モーターA用のGPIO、PWMの初期化
def setup_gpioAxisA():
GPIO.setup(IN1, GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(IN2, GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(ENA, GPIO.OUT, initial=GPIO.LOW)
return GPIO.PWM(ENA, frequency)
# モーターB用のGPIO、PWMの初期化
def setup_gpioAxisB():
GPIO.setup(IN3, GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(IN4, GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(ENB, GPIO.OUT, initial=GPIO.LOW)
return GPIO.PWM(ENB, frequency)
# モーターAのデューティ比と回転方向の設定用関数
def AxisA(duty,direction):
enA.ChangeDutyCycle(duty)
if direction == CW :
GPIO.output(IN1, GPIO.HIGH)
GPIO.output(IN2, GPIO.LOW)
else:
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN2, GPIO.HIGH)
# モーターBのデューティ比と回転方向の設定用関数
def AxisB(duty,direction):
enB.ChangeDutyCycle(duty)
if direction == CW:
GPIO.output(IN3, GPIO.HIGH)
GPIO.output(IN4, GPIO.LOW)
else:
GPIO.output(IN3, GPIO.LOW)
GPIO.output(IN4, GPIO.HIGH)
# ロータリーエンコーダーのGPIO初期化
def setup():
GPIO.setup(clkPin, GPIO.IN) # input mode
GPIO.setup(dtPin, GPIO.IN)
GPIO.setup(swPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# ロータリーエンコーダー信号の変換
def rotaryDeal():
global flag
global Last_dt_Status
global Current_dt_Status
global globalCounter
Last_dt_Status = GPIO.input(dtPin)
while(not GPIO.input(clkPin)):
Current_dt_Status = GPIO.input(dtPin)
flag = 1
if flag == 1:
flag = 0
if (Last_dt_Status == 0) and (Current_dt_Status == 1):
globalCounter = globalCounter - 1
if (Last_dt_Status == 1) and (Current_dt_Status == 0):
globalCounter = globalCounter + 1
# メインとなるループ処理(ロータリーエンコーダーによるPWM制御)
def loop():
global globalCounter
tmp = 0 # Rotary Temperary
while True:
rotaryDeal()
if tmp != globalCounter:
print ('globalCounter = %d' % globalCounter)
tmp = globalCounter
# CW(正転) Motor
if globalCounter >= 0 and globalCounter <= 20:
duty = globalCounter * 5
AxisA(duty,CW)
AxisB(duty,CW)
# CCW(逆転) Motor
if globalCounter < 0 and globalCounter >= -20:
duty = globalCounter * -5
AxisA(duty,CCW)
AxisB(duty,CCW)
#メイン処理
if __name__ == '__main__': # Program start from here
#各種初期化処理
GPIO.setmode(GPIO.BCM) # Numbers GPIOs by physical location
setup()
enA = setup_gpioAxisA()
enB = setup_gpioAxisB()
enA.start(0)
enB.start(0)
#モーター動作処理
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program will be executed.
pass
#終了時の後処理
finally:
enA.stop()
enB.stop()
GPIO.cleanup()
このプログラムでは、2個のモーターは正転/逆転と速度制御は同じ動作になります。例えばロータリーエンコーダーを2つ用意することで2個のモーターを独立して制御することが可能になります。
# GPIOPIN番号とL298NモジュールのPIN対応付け定義
ENA = 26
IN1 = 19
IN2 = 13
IN3 = 22
IN4 = 27
ENB = 17
この部分のプログラムは、以下の表の部分と対応付いています。もし、このプログラムを利用される場合にGPIOのピン番号が違うときは、対応付けを変更するだけで使えると思います。
PIN No. | ドライバ PIN |
GPIO26 | ENA |
GPIO19 | IN1 |
GPIO13 | IN2 |
GPIO22 | IN3 |
GPIO27 | IN4 |
GPIO17 | ENB |
結果
最後に動作確認です。動作は動画で紹介します。
今までのL293Dでの四苦八苦が嘘みたいにスムーズに回りました。デューティ比10%程度からスムーズに回りだします。もう少し電圧を上げると5%からでも回りました。ヒートシンクもついており安心して回せます。
まとめ
L293DドライバICに代わってL298Nドライバモジュールを使ってDCモーター制御に再トライです。結果は、呆気ないくらいスムーズに回りました。応答もよく、デューティ比5%程度から100%までほぼフルレンジで回すことができました。入門キットにはL298Nドライバを付けてもらったほうが初心者にはよいかも。やっと次の段階に進めそうです。
コメント