Xiao ESP32S3 モータドライバTC78H653FTG駆動
2024.1.28 Coskx Lab
1 はじめに
Xiao ESP32S3で小型モータを制御します。
モータドライバIC TC78H653FTGを使用して,小型ブラシDCモータの130モータを駆動します。モータ駆動電圧は3Vです。
TC78H653FTGはDCモータを対象と考えた場合,2つのHブリッジ回路を持っていて,2つのモータを別々に駆動できるSMALLモードと2つのHブリッジ回路を並列にして1つのモータを駆動するLARGEモードがあります。
なお電流監視抵抗付加による電流制限機能は使いません。
参考 モータドライバIC TC78H653FTG(東芝デバイス&ストレージ)
データシート https://toshiba.semicon-storage.com/info/docget.jsp?did=63588&prodName=TC78H653FTG
アプリケーションノート https://toshiba.semicon-storage.com/info/docget.jsp?did=70283&prodName=TC78H653FTG
参考 モータドライバIC TC78H653FTG 入出力ファンクション
LARGE = H or L, MODE = L, STBY = H(論理レベル) で使用する
IN1 | IN2 | OUT1(OUT2) | OUT3(OUT4) | モード |
L | L | OFF(Hi-Z) | OFF(Hi-Z) | ストップ |
H | L | H | L | 正転 |
L | H | L | H | 逆転 |
H | H | L | L | ブレーキ |
参考 モータドライバIC TC78H653FTG 動作範囲
項目 | 最小 | 標準 | 最大 |
モータ電源電圧 | 1.8V | 3.0V | 7.5V |
モータ出力電流 small mode | ― | 2A | ― |
モータ出力電流 small mode Peak 10ms | ― | ― | 2.5A |
モータ出力電流 large mode | ― | 4A | ― |
モータ出力電流 large mode Peak 10ms | ― | ― | 5A |
ロジックHレベル | 2.0V(Vm=5.0のとき) | ― | 5.5V |
ロジックLレベル | -0.3V | ― | 0.5V |
ロジック最大周波数 | ― | ― | 500kHz |
参考 モータドライバIC TC78H653FTG基板実装(秋月電子販売)
https://akizukidenshi.com/catalog/g/gK-14746/
回路図でわかるように,秋月電子の基板上で,論理系のGNDとモータ駆動系のGNDが接続されています。
2 使用環境
- Windows 10 64-bit
- Arduino IDE 2.2.1
- Xiao ESP32S3
- モータドライバIC TC78H653FTG
3 実験用配線
2つのHブリッジ回路を持っていて,2つのモータを別々に駆動できるSMALLモードと2つのHブリッジ回路を並列にして1つのモータを駆動するLARGEモードがあります。
配線はSMALLモード・LARGEモードによって異なります。
1つのモータを駆動することを考え,SMALLモード・LARGEモードを試します。
モータドライバIC TC78H653FTG のIN1,IN2には,Xiao ESP32S3 のD0,D1を接続します。
万が一,電流保護回路が働いたときには,STBY信号も使うので,Xiao ESP32S3 のD3につないでおきます。
○SMALLモード
○LARGEモード
実際の配線(smallmode)は次のようになりました。
4 モータ駆動デモプログラム
モータ駆動では,通電状態と絶縁状態を繰り返す駆動をしています。
PWMモジュール(PWMチャンネル)は2つ,PWM出力用のGPIOピンは2つ必要になります。
設定値は次の通りです。
PWM生成に使用するビット数: 8bit
PWM周波数:1000Hz
使用するPWMモジュール(PWMチャンネル):1,2
PWM出力に使用するPIN番号:D0,D1
STBY信号:D3
SMALLモード・LARGEモードともに同じプログラムで動作します。
2秒間隔でPWMデューティ比を-100%から100%まで10%刻みで変化させます。(正のデューティ比は正転,負のデューティ比は逆転を表します。)
プログラムでは,モータ駆動クラスを利用しています。
PWMの動作テスト用プログラム本体
//** motordrivetest.ino **//
#include "MotorDriverESP32.h"
//DCブラシモータを1つ正転逆転駆動するテスト
//class MotorDriver 利用
//1つのモータを正逆駆動するためには,正転用と逆転用の2つのPWM信号が必要です。
//そのため,2つのPWMモジュール(PWMチャンネル)と2つのピンを割り当てます.
//ピン番号はGPIOピン番号ではなく,ESP32のピン番号で0ではなく1から始まります
//正転(Forward) PWMチャンネル:1 GPIOピン:1
//逆転(Reverse) PWMチャンネル:2 GPIOピン:2
const uint8_t nBits_forPWM = 8; // PWMに使用するビット数 n=1~16[bit]
const double PWM_Frequency = 1000.0; // PWM周波数 Maxfreq=80000000.0/2^n[Hz]
const uint8_t PWM_F_CH = 1; // PWMチャンネル Forward
const uint8_t PWM_R_CH = 2; // PWMチャンネル Reverse
const uint8_t PWM_F_PIN = D0; // PWM出力に使用するGPIO PIN番号 Forward
const uint8_t PWM_R_PIN = D1; // PWM出力に使用するGPIO PIN番号 Reverse
const uint8_t Standby_PIN = D3; //standbyに使用するGPIO PIN番号
int Led_PIN = LED_BUILTIN;
int LEV_Value = 1;
const double Motor_Drive_dutyRatios[] = {-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1,
0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
const int nRatios = sizeof(Motor_Drive_dutyRatios)/sizeof(double);
//Motor_Drive_dutyRatios[]はモータ指令デューティー比の候補(-1.0 <= dutyRatio <= 1.0)
//モータ指令値:正の時は正転側のデューティ比,負のときは逆転側のデューティ比を表す
int dutyRatioIndex = (nRatios>>1); //モータ指令値番号 初期値
double dutyRatio_Value = Motor_Drive_dutyRatios[dutyRatioIndex];
int naverage = 30;
int value;
int step = 1;
MotorDriverESP32 mMotorDriver; //class MotorDriver のインスタンス
void setup() {
Serial.begin(115200);
//while(!Serial);
Serial.println("\n\n\n*** Single Motor Drive Test ***");
mMotorDriver.setPins(PWM_F_PIN, PWM_R_PIN, PWM_F_CH, PWM_R_CH);
mMotorDriver.setPWM(nBits_forPWM, PWM_Frequency);
Serial.printf("duty ratio = %.4f\n",dutyRatio_Value);
value = mMotorDriver.driveMotor(dutyRatio_Value);
Serial.printf("value = %5d\n",value);
pinMode(Standby_PIN, OUTPUT);
digitalWrite(Standby_PIN, HIGH);
pinMode(Led_PIN, OUTPUT);
}
void loop() {
digitalWrite(Led_PIN, LEV_Value = 1 - LEV_Value);
dutyRatioIndex += step;
if (nRatios-1 <= dutyRatioIndex) step = -1;
if (dutyRatioIndex < 1) step = 1;
dutyRatio_Value = Motor_Drive_dutyRatios[dutyRatioIndex];
value = mMotorDriver.driveMotor(dutyRatio_Value);
Serial.printf("duty ratio = %.4f value = %d\n",dutyRatio_Value, value);
delay(2000);
}
モータ駆動クラスのヘッダーファイル
//** MotorDriverESP32.h **//
#ifndef MotorDriverESP32_h
#define MotorDriverESP32_h
class MotorDriverESP32 {
public:
void setPins(int forwardPin, int reversePin, int forwardChannel, int reverseChannel);
void setPWM(int nBits_forPWM, double PWM_Frequency);
int driveMotor(double dutyRatio); // -1.0 <= dutyRatio <= 1.0
void setHighImpedance();
private:
int fwdPin, rvsPin;
int fwdChl, rvsChl;
int pwmMaxValue;
};
#endif
モータ駆動クラスのCPPファイル
Arduino ESP32 coreのバージョンが2.Xから3.0になり,
ledcSetup(), ledcAttachPin() は廃止され,ledcAttachChannel()を使うことになりました。
https://github.com/espressif/arduino-esp32/blob/master/docs/en/migration_guides/2.x_to_3.0.rst#id4
//** MotorDriverESP32.cpp **//
#include <Arduino.h>
#include "MotorDriverESP32.h"
/*
XIAO ESP32S3 pin assignment
1 D0(A0)
2 D1(A1)
3 D2(A2)
4 D3(A3)
5 D4(A4)
6 D5(A5)
7 D8(A8)
8 D9(A9)
9 D10(A10)
*/
void MotorDriverESP32::setPins(int forwardPin, int reversePin, int forwardChannel, int reverseChannel) {
fwdPin = forwardPin; //GPIO PIN NUMBER
rvsPin = reversePin; //GPIO PIN NUMBER
fwdChl = forwardChannel;
rvsChl = reverseChannel;
pinMode(fwdPin, OUTPUT); //出力したいピンを出力用途に設定 ピン番号はA0,A1,... or D0,D1,...
pinMode(rvsPin, OUTPUT); //出力したいピンを出力用途に設定 ピン番号はA0,A1,... or D0,D1,...
}
void MotorDriverESP32::setPWM(int nBits_forPWM, double PWM_Frequency) {
pwmMaxValue = 1<<nBits_forPWM;
/*
// 指定PWMチャンネルにPWM周波数と使用ビット数を設定
ledcSetup(fwdChl, PWM_Frequency, nBits_forPWM);
ledcSetup(rvsChl, PWM_Frequency, nBits_forPWM);
// 出力したいピンにPWMチャンネル出力をつなげる設定
ledcAttachPin(fwdPin, fwdChl);
ledcAttachPin(rvsPin, rvsChl);
from versions 2.X (based on ESP-IDF 4.4) to version 3.0 (based on ESP-IDF 5.1) of the Arduino ESP32 core
への移行で次のように変更された
https://github.com/espressif/arduino-esp32/blob/master/docs/en/migration_guides/2.x_to_3.0.rst#id4
*/
ledcAttachChannel(fwdPin, PWM_Frequency, nBits_forPWM, fwdChl);
ledcAttachChannel(rvsPin, PWM_Frequency, nBits_forPWM, rvsChl);
}
//Slow decay mode での駆動
//モータ指令値が正のときはPWM_F_PINに デューティfullのPWMを出力,
// PWM_R_PINに full - デューティのPWMを出力
//モータ指令値が負のときはPWM_R_PINに デューティfullのPWMを出力,
// PWM_F_PINに full + デューティのPWMを出力
//デバッグのためにdrivevalueを返す
int MotorDriverESP32::driveMotor(double dutyratio) {
int drivevalue = (int)(pwmMaxValue * dutyratio);
if (drivevalue == 0) {
ledcWrite(fwdChl, pwmMaxValue);
ledcWrite(rvsChl, pwmMaxValue);
} else if (0<drivevalue) {
ledcWrite(fwdChl, pwmMaxValue);
ledcWrite(rvsChl, pwmMaxValue - drivevalue);
} else { //drivevalue<0
ledcWrite(fwdChl, pwmMaxValue + drivevalue);
ledcWrite(rvsChl, pwmMaxValue);
}
return drivevalue;
}
void MotorDriverESP32::setHighImpedance() {
ledcWrite(fwdChl, 0);
ledcWrite(rvsChl, 0);
}
5 駆動信号の様子
オシロスコープのCh1はIN1,Ch2はIN2の信号を表しています。
(1) 正転
デューティ比25%を与えて正転駆動時のIN1(D0),IN2(D1)の信号は次のようになっています。
IN1=HでIN2=Lの区間が正転駆動区間で,IN1=IN2=Hの区間はブレーキ区間になります。
(2) 逆転
デューティ比-25%を与えて逆転駆動時のIN1(D0),IN2(D1)の信号は次のようになっています。
IN1=LでIN2=Hの区間が逆転駆動区間で,IN1=IN2=Hの区間はブレーキ区間になります。
6 実行の様子
モータ駆動用の電源は定電圧電源装置を用い3.0Vを供給しました。
予定通り,2秒ごとに10%ずつのデューティ比変化で130モータを駆動することが出来ました。
動画では,Xiao ESP32S3のLEDが2秒ごとにON-OFFし,それに合わせてモータ駆動PWM信号のデューティ比が10%ずつ変化しています。10%のデューティ比でも動作していることがわかります。
7 まとめ
Xiao ESP32S3およびモータドライバTC78H653FTGのsmallモードによるブラシDCモータ駆動テストを行ないました。
ここではPWM周波数1000Hzで駆動しましたが,10000Hz,20000Hzでも同様の動作は確認できています。(1000Hzですと電磁音が耳障りです。)
なお,Largeモードでも同様の結果が得られています。
重要
「5 駆動信号の様子」を見てわかるように,使用したプログラムではPWMモータ駆動方式が「駆動 ー ブレーキ」の繰り返しを採用しています。
「駆動 ー ストップ」の繰り返しの方式でも駆動出来ますが,低いデューティ比での駆動が不安定になります。
使用する130モータにはコンデンサを付けて,ノイズに対策をする必要があります。これがないと,ノイズの影響で電流制限安全回路が働いてしまうことが多く,STBY信号にH→L→Hを与えるか電源ON→OFF→ONをしないと復旧しません。