esp32とL293Dを用いてドローン用モータを回してみたので,まとめ記事を書きます.
ただ,最初に書いておきますが,この回路構成だとドローンが飛ぶレベルの出力は得られません.というのも,L293Dはバイポーラトランジスタを用いていて,消費電力のロスが大きいのです.ドローン用には,MOSFETを用いたモータドライバ等を使うのが一般的なようです.
ここらへんのことは,以下の記事でまとめているので,気になる方はご覧ください.
じゃあなんで記事にするんや?と思うかもしれません.以下がいちおう記事にしておく理由です.
- もう少し低出力でも大丈夫な車輪ロボット等であれば,この回路構成で大丈夫そう.
- もっと軽いモータや機体にすればこのモータドライバでももしかしたら飛ばせるかも.
- 4つのモータを1つのモータドライバで駆動できるというのは利便性が高い(回路の省スペース化ができる).
- ArduinoでL293Dを使っている記事は他にもあったが,4つモータを回している記事は見つからなかった.
- その他モータを回す際の注意点をまとめておきたい.
L293Dの仕様
データシートは以下のサイトから確認できます.
入出力の定格は以下のようになっています.
パラメータ | 定格 |
モータドライバ用電圧 Vcc1 | 推奨値:5 V |
モータ用電圧 Vcc2 | 推奨値:4.5 V 〜 7 V |
定常電流 | 最大値:600 mA |
ピーク電流 | 最大値:1.2 A |
ピン配置は以下のようになっています.
https://www.tij.co.jp/product/jp/L293D
回路構成
回路構成は以下のようにしています.

以下が,それぞれの配線の意味です.
モータ出力
- 1A, 2A, 3A, 4AにそれぞれPWM入力信号を印加する.esp32のD12, D13, D14, D15からPWM信号を出力する.
- モータの片方はL293Dの出力用信号1Y〜4Yにつなぎ,もう一方をGNDにつなぐ.
- モータドライバをACTIVEにするため,1,2ENと3,4ENにそれぞれ,esp32のD19,D18からHIGHの信号を送る.
電源周り
- esp32は3.3Vの出力しかない(5Vがない)ので,5V昇圧モジュールを使う.昇圧モジュールを使って得られた5V電圧をモータドライバ駆動用電源として,Vcc1に印加する.
- Vcc2にモータ用電源4.8 V(EVOLTA x 4)を印加する.
- バイパスコンデンサ(0.1 uF)を導入する.
- モータ用電源4.8Vは,esp32の駆動用電源と併用する.
私が使った5V出力昇圧DCDCコンバータは以下です.fritzingに適切な画像がなかったので,別のモジュールを使いました.
esp32のfritzing用データは以下のサイトで公開されていたので,ありがたく拝借させていただきました.

注意点1:バイパスコンデンサ(パスコン)を導入する
バイパスコンデンサ(パスコン)を入れることによって,「ICにノイズが流入する、ICからノイズが流出するのを防ぐ」ことができます.他にもパスコンにはいくつか役割があります.
パスコンのつなぎ方は以下のとおりです.
https://detail-infomation.com/bypass-capacitor/
パスコンを配線する位置に関しては,電源ピンの近傍にするというのが重要みたいです.
パスコンをICの電源ピン(VCC)の近傍に接続することによって、ICから電源側を見たときにおいて、電源ラインとグラウンドに対する交流的なインピーダンスを下げることができます。
パスコンは電源ピン(VCCピン)から最短で配線してください。電源ピン(VCCピン)から離れれば離れるほど効果が薄くなります。
https://detail-infomation.com/bypass-capacitor/
以下のサイトが,わかりやすくパスコンの役割をまとめています.

以下のパスコン選定の記事もおもしろかったので,一応読んでみました.コンデンサ容量によって軽減させたいノイズのターゲット周波数をしぼれるみたいですね.

注意点2:モータ用電源を最初からつないでおかない
モータ用電源を最初からつないでおくと,モータがいきなり高速回転します.なので,モータ用電源はesp32の起動処理が終わってからつなぐようにしています.
起動処理が完了するまでは,端子から出る電流値は不定であることが原因かと思っています.
マイコンに電源が投入されても直ぐに動作が可能にはなりません。(中略)一般に、F/Fを含む論理回路は初期化されるまではその状態が不定となります(中略)。この状態では端子の状態は不定となり、端子に異常な信号が出ることがあります。
https://ja-support.renesas.com/knowledgeBase/17793981
上の回路図で言うと,Vcc2につながっている導線は,esp32起動処理が終わったのを確認してからつなぐようにしているということです.setup()関数の中で,ビルトインLEDを点滅するようにしているので,ビルトインLEDを見れば起動処理が終了したことがわかります.
#define BUILTIN_LED 2
setup() {
pinMode(BUILTIN_LED, OUTPUT);
char blink_times = 3;
for (int i = 0; i < blink_times; i++) {
digitalWrite(BUILTIN_LED, HIGH);
delay(50);
digitalWrite(BUILTIN_LED, LOW);
delay(50);
}
}
注意点3:モータに並列にダイオードをつなぐ(L293D使用時は不要)
本来なら,スイッチオフ時にモータに生じる逆起電力からトランジスタを守るため,モータと並列にダイオードをつなぐ必要があります.このようなダイオードをフリーホイーリングダイオードと呼ぶそうです.L293Dでは,ダイオードが素子の内部に入っているため,フリーホイーリングダイオードは付け加える必要がないみたいです.
On the L293, external high-speed output clamp diodes should be used for inductive transient suppression. On the L293D, these diodes are integrated to reduce system complexity and overall system size.
https://www.tij.co.jp/product/jp/L293D
補足ですが,フリーホイーリングダイオードは以下のように取り付けます.スイッチを切っても矢印の方向に電流を流し続けることができ,急激な逆起電力の発生を防ぐことができるようです.
http://pelab.nagaokaut.ac.jp/~nagayosi/robocon/motordrive/motordrive.html
ソースコード
モータを回した際のソースコードを紹介します.
PINの定義
以下のように配線します.
ソースコード | esp32 | モータドライバ L293D |
MOTOR_PWM1 | D12 | 1A |
MOTOR_PWM2 | D13 | 2A |
MOTOR_PWM3 | D14 | 3A |
MOTOR_PWM4 | D15 | 4A |
MOTOR_DIR1 | D18 | 3,4EN |
MOTOR_DIR2 | D19 | 1,2EN |
#define MOTOR_PWM1 12
#define MOTOR_PWM2 13
#define MOTOR_PWM3 14
#define MOTOR_PWM4 15
#define MOTOR_DIR1 18
#define MOTOR_DIR2 19
setup()関数の中身
MOTOR_DIR1とMOTOR_DIR2で,L293Dの3,4ENと1,2ENをHIGHにしてモータドライバをACTIVEにしています.また,MOTOR_PWM1〜MOTOR_PWM4を使って,L293Dの1A〜4AにPWM信号を印加しています.
pinMode(MOTOR_DIR1, OUTPUT);
pinMode(MOTOR_DIR2, OUTPUT);
digitalWrite(MOTOR_DIR1, HIGH);
digitalWrite(MOTOR_DIR2, HIGH);
pinMode(MOTOR_PWM1, OUTPUT);
pinMode(MOTOR_PWM2, OUTPUT);
pinMode(MOTOR_PWM3, OUTPUT);
pinMode(MOTOR_PWM4, OUTPUT);
ledcSetup(0, 12800, 8);
ledcAttachPin(MOTOR_PWM1, 0);
ledcSetup(1, 12800, 8);
ledcAttachPin(MOTOR_PWM2, 1);
ledcSetup(2, 12800, 8);
ledcAttachPin(MOTOR_PWM3, 2);
ledcSetup(3, 12800, 8);
ledcAttachPin(MOTOR_PWM4, 3);
for (int i = 0; i < 4; i++) {
ledcWrite(i, 0);
}
esp32ではanalogWrite()はないけど,ledcWrite()が代わりにあるんでしたね.
loop()関数の中身
ここで,motor_valを255にして,すべてのモータを最大出力で回すようにしています.
int test_motor_val = 255;
ledcWrite(0, test_motor_val);
ledcWrite(1, test_motor_val);
ledcWrite(2, test_motor_val);
ledcWrite(3, test_motor_val);
動画
4つのモータがちゃんと回っているのがわかると思います.ただ,冒頭で述べたとおり,私の感想としてはドローン用としての出力は足りなそうだなという感じです.
動画では,スイッチを押したらモータが動くようにプログラムしています.
参考サイト

コメント