モータを制御したい場合、モータドライバICを使うと小型で簡単に実装可能です。
今回はL293Dを例に挙げてモータドライバICの使い方を学んでみます。

前回はこちらです
モータドライバICの概要
DCモータの駆動電流
DCモータを駆動するためには、LED点灯(約20 mA)とは桁違いの電流が必要です。例えば、FA-130RAモータの場合、適正負荷時には500 mAの電流が必要となります。また、回転数が低い状態(始動、ロック、高負荷)では、非常に大きな電流が流れます。FA-130RAモータでは、始動時やロック状態、高負荷時には最大で2200 mAの電流が流れます。
ロジックICやマイコンによる駆動の限界
ロジックICやマイコンの出力は、このような大きな電流を直接駆動するには不十分です。通常、ロジックICやマイコンは数十mA程度の電流しか供給できません。そのため、モータを駆動させるためには、トランジスタやFETを使用した回路が必要となります。
Hブリッジ回路
モータの回転を制御するためには、Hブリッジ回路が一般的に使われます。Hブリッジ回路は、トランジスタやFETを使用して、モータの両端にかかる電圧を制御し、モータの回転方向や速度を調整します。
詳しくは以下の記事で解説しています。
モータドライバIC
Hブリッジ回路を簡単に利用するために、FETを複数内蔵したHブリッジ回路を1個のIC内に組み込んだ「モータドライバIC」が使用されます。モータドライバICは、以下のような特徴があります:
- 簡単な制御:マイコンからの制御信号でモータの回転方向や速度を簡単に制御できます。
- 高電流対応:マイコンと比べて大きな駆動電流を供給する能力があります。
- 保護機能:過電流保護や過熱保護などの機能を持つものが多く、モータや回路の保護に役立ちます。
利点としては構成部品が少なくなり、簡単にモータ駆動回路を構成することが出来ます。
一方で大きな電流を扱えるものは少なく、大型のモータを駆動する事は難しいです。
L293D
今回の実験ではL293DというモータドライバICを使ってみます。
クワッド ハーフ H ドライバ L283D https://www.ti.com/jp/lit/gpn/l293d

L293D の仕様を以下の表にまとめました。
| 項目 | 仕様 |
|---|---|
| 動作電圧範囲 | 4.5 V ~ 36 V |
| 入力ロジック電源 | 分離(Separate Input-Logic Supply) |
| 内部ESD保護 | 有 |
| 高ノイズ耐性入力 | 有 |
| 出力電流(チャンネルあたり) | 1 A(L293Dの場合は600 mA) |
| ピーク出力電流(チャンネルあたり) | 2 A(L293Dの場合は1.2 A) |
| 誘導性過渡電圧抑制用クランプダイオード | 有(L293D) |

このモータドライバICは最大2個のモータを正転と逆転制御を行うことが出来ます。
16番ポートには中の制御ICを駆動するための電圧、5Vを印加します。
8番ポートにはモータを駆動させるための電圧を印加します。
下記の図の通り、3番ポートと6番ポートにモータをつなぎます。
ENポート(1番)にPWM信号を入力すると、モータの回転数を制御できます。
2番ポートと7番ポートの入力により回転方向を制御します。
2番がHIGH、7番がLOWの場合は正転、2番ポートがLOW、7番ポートがHIGHの場合は逆転です。

Arduinoに下記の通り接続します。
モータは回転を停止させる信号を送ると、しばらくは慣性の法則で回り続けます。
その際、モータから逆起電力により回路へ電流が逆流して流れます。
その電流から破壊されることを防ぐために、ダイオードをはさみ、逆起電流をGNDとショートさせることで回路を保護しています。
制御IC用の電源5VはArduinoから取り、モータ用の電源は安定化電源等外部電源で供給します。
その際、GNDは共通化させます。

PWMを100で正転、逆転、停止を1秒おきに繰り返すプログラムは以下の通りになります。
# ============================================
# L293DによるDCモータ制御
# PWM値100で 正転 → 停止 → 逆転 → 停止 を
# 1秒おきに繰り返すプログラム
# ============================================
from machine import Pin, PWM
from time import sleep
# --------------------------------------------
# ピンの設定
# --------------------------------------------
# ENピン(PWMで速度を制御する)
en = PWM(Pin(15))
en.freq(1000) # PWM周波数 1kHz
# 方向制御ピン(1Aと2A)
in1 = Pin(14, Pin.OUT)
in2 = Pin(13, Pin.OUT)
# --------------------------------------------
# PWM値の設定
# --------------------------------------------
# Arduinoは8bit(0〜255)でPWMを指定しますが、
# Raspberry Pi Picoは16bit(0〜65535)で指定します。
# 元記事のPWM=100に相当する値に変換します。
# 100 / 255 ≒ 0.392 → 65535 × 0.392 ≒ 25700
PWM_VALUE = 25700
# --------------------------------------------
# メインループ
# --------------------------------------------
try:
while True:
# 正転
print("正転")
in1.value(1)
in2.value(0)
en.duty_u16(PWM_VALUE)
sleep(1)
# 停止
print("停止")
in1.value(0)
in2.value(0)
en.duty_u16(0)
sleep(1)
# 逆転
print("逆転")
in1.value(0)
in2.value(1)
en.duty_u16(PWM_VALUE)
sleep(1)
# 停止
print("停止")
in1.value(0)
in2.value(0)
en.duty_u16(0)
sleep(1)
except KeyboardInterrupt:
# プログラム停止時にモータを止める
en.duty_u16(0)
print("プログラムを終了しました")回転数の計測
角度センサ
角度センサには主に以下の2種類があります:
- ポテンショメータ (Potentiometer)
- エンコーダ (Encoder)
ポテンショメータ
ポテンショメータは、抵抗値の変化を利用して回転角度を計測するセンサです。これは可変抵抗の一種で、回転角度の検出に抵抗値の変化を利用しています。
ポテンショメータの原理
巻線式のポテンショメータでは、抵抗板上にブラシが接触することで抵抗値が変化します。
- 構造:ポテンショメータには三つの端子があります。
- 供給電源端子 (VDD)
- 接地端子 (GND)
- 出力端子 (Vout)
- 動作:供給電源端子 (VDD) と接地端子 (GND) に電源を接続し、残りの一つの端子が出力端子 (Vout) となります。この出力端子から基準電位との電位差を計測します。軸が回転すると、可動ブラシの位置によって出力端子と基準電位との間の電位差が変化し、これによって回転角度を検出することができます。

https://akizukidenshi.com/catalog/g/g118292/
ポテンショメータの出力はアナログ信号となります。
ポテンショメータは抵抗値の変化を利用して回転角度を計測するセンサですが、構造上、回転数が限られてしまいます。一定の回転角度範囲内でのみ使用可能で、無限回転はできません。
ロータリーエンコーダ
エンコーダは、パルス信号の組み合わせを利用して回転角度を計測するセンサです。
ロータリエンコーダは無限回転の角度を取り扱うことができます。例えば、モータでロボットの関節角度を制御する場合、ギアなどで減速しているため、モータは何回転もすることが多いです。このため、モータの角度センサとしてはロータリエンコーダがよく使われます。
エンコーダの原理
エンコーダは、回転する部品に付けられたパターンを読み取り、そのパターンに基づいてパルス信号を生成します。これにより、回転角度や位置を精密に計測することができます。
エンコーダの出力はディジタル信号となります。
ロータリエンコーダの仕組み
ロータリエンコーダの動作原理を説明します:
- 発光ダイオードとフォトトランジスタの間にスリット円盤が回転します。
- スリット円盤の回転により、発光ダイオードの光がフォトトランジスタに届いたり遮断されたりします。
- この遮断と透過の繰り返しが、増幅されたパルス信号として出力されます。
パルス信号の位相ずれ
固定スリットによって、2組のパルス信号の位相がずれるようになっています。この2組のパルス信号はそれぞれA相、B相と呼ばれます。A相とB相のパルス信号の時系列波形は1/4ピッチずれた波形となります。
回転角度と回転方向の測定
- 回転角度:パルス信号をカウントすることで、回転角度を測定します。
- 回転方向:位相がずれながらHigh状態とLow状態を繰り返す二つのパルス信号(A相とB相)を比較することで、回転方向も検出できます。
回転方向の検出方法
- 時計回り:A相が先にHigh状態となり、B相がそれを追いかけるようにHigh状態になります。続いて、A相がLow状態になり、その後B相もLow状態になります。
- 反時計回り:B相が先にHigh状態となり、A相がそれを追いかけるようにHigh状態になります。続いて、B相がLow状態になり、その後A相もLow状態になります。
Z相の役割
Z相のついたロータリエンコーダでは、1回転するごとにZ相がHigh状態になります。これにより、正確な回転数の測定が可能です。

インクリメンタル方式
インクリメンタル方式のロータリエンコーダは、初期状態からの相対的な回転角度の情報を扱います。そのため、電源を入れた際には原点を合わせる必要があります。
実験に使用するモータ
今回はギアドモータとロータリエンコーダが一体となったエンコーダ付きギアドモータ(DG01D-E)を使用します。

| 動作電圧 | 3V~9V |
| ギア比 | 1:45 |
| 回転数 | 90RPM (4.5V) |
| トルク | 0.8 kg*cm (0.078 Nm) |
| 分解能 | モータ1回転当たり3パルス |
課題11
Raspberry Pi Pico、L293D、エンコーダ付きギアドモータを使用して、モータの駆動制御を行なう装置を構成せよ。
スイッチなどを押すと,正転,逆転,停止とモータの回転が変化する。
それぞれのコマンドを送った際のエンコーダの波形を読取り、レポートで報告してください。
解答例はこちら
| 部品 | Picoのピン |
|---|---|
| L293D:ENピン(1番) | GP15(PWM) |
| L293D:1A(2番) | GP14 |
| L293D:2A(7番) | GP13 |
| L293D:Vcc1(16番) | VBUS(5V) |
| L293D:Vcc2(8番) | 外部電源(+) |
| L293D:GND(4,5番) | GND |
| プッシュスイッチ:片側 | GP12 |
| プッシュスイッチ:もう片側 | GND |
# ============================================
# プッシュスイッチでDCモータの状態を切り替える
# スイッチを押すたびに
# 正転 → 逆転 → 停止 → 正転 → ...
# と切り替わるプログラム
# ============================================
from machine import Pin, PWM
from time import sleep
# --------------------------------------------
# ピンの設定
# --------------------------------------------
# ENピン(PWMで速度を制御する)
en = PWM(Pin(15))
en.freq(1000) # PWM周波数 1kHz
# 方向制御ピン(1Aと2A)
in1 = Pin(14, Pin.OUT)
in2 = Pin(13, Pin.OUT)
# プッシュスイッチ(GP12)
# Pin.PULL_UP は内部プルアップ抵抗を有効にする設定です
# → 押していないとき:1(HIGH)
# → 押したとき :0(LOW)
sw = Pin(12, Pin.IN, Pin.PULL_UP)
# --------------------------------------------
# PWM値の設定
# --------------------------------------------
# 元記事のPWM=100に相当する値(16bit換算)
PWM_VALUE = 25700
# --------------------------------------------
# モータ制御関数
# --------------------------------------------
def forward():
"""正転"""
in1.value(1)
in2.value(0)
en.duty_u16(PWM_VALUE)
print("正転")
def reverse():
"""逆転"""
in1.value(0)
in2.value(1)
en.duty_u16(PWM_VALUE)
print("逆転")
def stop():
"""停止"""
in1.value(0)
in2.value(0)
en.duty_u16(0)
print("停止")
# --------------------------------------------
# 状態管理用の変数
# --------------------------------------------
# 現在のモータの状態を覚えておく変数
# 0: 正転 / 1: 逆転 / 2: 停止
state = 2 # 最初は停止状態からスタート
# 最初は停止状態にしておく
stop()
# --------------------------------------------
# メインループ
# --------------------------------------------
try:
while True:
# スイッチが押されたかチェック
# value() == 0 のとき = 押されている状態
if sw.value() == 0:
# 状態を1つ進める
# 0 → 1 → 2 → 0 → ... と循環させるため
# 「+1して3で割った余り」を使う
state = (state + 1) % 3
# 状態に応じてモータを制御
if state == 0:
forward()
elif state == 1:
reverse()
else:
stop()
# スイッチを離すまで待つ(連続切り替え防止)
while sw.value() == 0:
sleep(0.01)
# チャタリング対策で少し待機
sleep(0.05)
# CPU負荷軽減のため少し待機
sleep(0.01)
except KeyboardInterrupt:
# プログラム停止時にモータを止める
stop()
print("プログラムを終了しました")次回はこちら


