M5StackGray モータ駆動デモプログラム TC78H653FTG

2021.6.11 Coskx Lab  

1 はじめに

M5StackGrayとモータドライバIC TC78H653FTGを使用し,モータ駆動デモプログラムを作成します。
TC78H653FTG 特徴
 2つのモータを駆動できる。
 1.8Vから7.5Vの低電圧電源でのモータ駆動ができる。
 入力制御信号は2Vから5.5Vの広い範囲が使える。3.3V系マイコンではありがたい
 通常は2つのモータを別々に駆動するためにHドライバを2回路別々に使用(Smallモデル)
 Smallモデル駆動(通常駆動)では最大電流は2.5Aまで
 大電流が必要な場合はHドライバ2つを結合して使用できる(Largeモデル)
 Largeモデル駆動(2回路接続駆動)では最大電流は5Aまで
 電流制限回路がついている(この回路が働くと機能が一次的に停止し,STBYをH→L→Hの操作をしないと復旧できない)

参考1 モータドライバ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

参考2 モータドライバIC TC78H653FTG 入出力ファンクション(Smallモデル)
   LARGE = MODE = L, STBY = H(論理レベル) で使用する
   モータは2つ接続できる。

   モータ1について
IN1IN2OUT1OUT2モード
LLOFF(Hi-Z)OFF(Hi-Z)ストップ
HLHL正転
LHLH逆転
HHLLブレーキ
   モータ2について
IN3IN4OUT3OUT4モード
LLOFF(Hi-Z)OFF(Hi-Z)ストップ
HLHL正転
LHLH逆転
HHLLブレーキ

参考3 モータドライバIC TC78H653FTG 入出力ファンクション(Largeモデル)
   LARGE = H, MODE = L, STBY = H(論理レベル) で使用する
IN1IN2OUT1(OUT2)OUT3(OUT4)モード
LLOFF(Hi-Z)OFF(Hi-Z)ストップ
HLHL正転
LHLH逆転
HHLLブレーキ

参考4 モータドライバIC TC78H653FTG 動作範囲(Smallモデル)
モータ出力電流は2つのモータそれぞれの値
項目最小標準最大
モータ電源電圧1.8V3.0V7.5V
モータ出力電流2A2.5A
ロジックHレベル2.0V(Vm=5.0のとき)5.5V
ロジックLレベル-0.3V0.5V
ロジック最大周波数500kHz

参考5 モータドライバIC TC78H653FTG 動作範囲(Largeモデル)
項目最小標準最大
モータ電源電圧1.8V3.0V7.5V
モータ出力電流4A5A
ロジックHレベル2.0V(Vm=5.0のとき)5.5V
ロジックLレベル-0.3V0.5V
ロジック最大周波数500kHz

参考6 モータドライバIC TC78H653FTG基板実装(秋月電子販売)
https://akizukidenshi.com/catalog/g/gK-14746/

回路図でわかるように,秋月電子の基板上で,論理系のGNDとモータ駆動系のGNDが接続されています。

2 使用環境

3 Smallモデルでの実験用配置と配線例

モータは1つだけ駆動します。配線は次のようになります。
M5Stackの正回転PWM信号の出力は「GPIO 2」です。 「GPIO 2」はM5Stackの裏側に 2 と書いてあるところです。これをTC78H653FTGのIN1に接続します。
M5Stackの逆回転PWM信号の出力は「GPIO 5」です。 「GPIO 5」はM5Stackの裏側に 5 と書いてあるところです。これをTC78H653FTGのIN2に接続します。
モータはTC78H653FTGのOUT1とOUT2に接続します。



実験の様子
実験ではモータを1つだけ使用しています。 基板上で,論理系のGNDとモータ駆動系のGNDが接続されているため,論理系のGNDとモータ駆動系のGNDを接続することはしていません。
TC78H653FTGのSTBYには3.3V,GNDは共通のGNDにします。



参考 M5Stackの裏側に書いてあるピンの名称

2,5を使用しています。
注意 ピンのいくつかは,他の用途に割り当てられている場合があるため,自由に変更できません。

4 Largeモデルでの実験用配置と配線例

配線は次のようになります。
M5Stackの正回転PWM信号の出力は「GPIO 2」です。 「GPIO 2」はM5Stackの裏側に 2 と書いてあるところです。これをTC78H653FTGのIN1に接続します。
M5Stackの逆回転PWM信号の出力は「GPIO 5」です。 「GPIO 5」はM5Stackの裏側に 5 と書いてあるところです。これをTC78H653FTGのIN2に接続します。
モータはTC78H653FTGのOUT1とOUT2に接続します。
ただし,OUT1とOUT2,OUT3とOUT4をそれぞれ接続します。



5 PWMの動作テスト用プログラム

Smallモデル配線でもLargeモデル配線でも,M5Stack側は「GPIO 2」と「GPIO 5」に出力するので,プログラムは同じものが使えます。
モータ駆動では,通電駆動状態とショートブレーキ状態を繰り返す駆動をしています。

○ 正転動作(例 デューティ比25%)のときは →
1周期の75%区間で,モータドライバのIN2,IN1ともにHighを与え,残りの25%区間で,モータドライバのIN2にLowを与えとIN1にHighを与えます。(IN1はずっとHigh)
すなわち次の2つの状態が交互に生じます。(ショートブレーキ区間75%,正転通電駆動区間が25%)
 

○ 逆転動作(例 デューティ比25%)のときは →
1周期の75%区間で,モータドライバのIN1,IN2ともにHighを与え,残りの25%区間で,モータドライバのIN1にLow,IN2にHighを与えます。(IN2はずっとHigh)
すなわち次の2つの状態が交互に生じます。(ショートブレーキ区間75%,逆転通電駆動区間が25%)
 

2つのPWMモジュール(PWMチャンネル)をそれぞれ別のGPIOピンに出力します。
モータへの指令値は離散的で,プログラム内での見かけ上は
{-1.0, -0.75, -0.5, -0.25, 0., 0.25, 0.5, 0.75, 1.0}
を使用しています。正の値は正転,負の値は逆転になるようにしています。
モータ駆動関数driveMotor(int drivevalue)では,指令値の正負によって,PWM発生の仕方を変えています。
M5Stackプログラムでは,ボタンAで指令値を増加,ボタンBで指令値を減少させます。

設定値は次の通りです。
 PWM生成に使用するビット数: 8bit
 PWM周波数:20000Hz
 使用するPWMモジュール(PWMチャンネル):2,3
  (利用可能性を調べてある2,3,4,5,8,9,10,11,12,13,14,15の中から4つを選んでいます)
 PWM出力に使用するGPIO PIN番号:2,5
  (利用可能性を調べてある2,5,16,17,23,19の中から4つを選んでいます)


  PWMの動作テスト用プログラム本体

モータ駆動メインプログラム MotorOOPTest01.ino

//MotorOOPTest01.ino//

#include <M5Stack.h>
#include "MotorDriver.h"

//DCブラシモータを1つ正転逆転駆動するテスト
//class MotorDriver 利用

//1つのモータを正逆駆動するためには,正転用と逆転用の2つのPWM信号が必要です。
//そのため,2つのPWMモジュール(PWMチャンネル)と2つのピンを割り当てます.
//正転(Forward) PWMチャンネル:2 GPIOピン:2
//逆転(Reverse) PWMチャンネル:3 GPIOピン:5

const uint8_t nBits_forPWM = 8; // PWMに使用するビット数 n=1~16[bit]
const double PWM_Frequency = 20000.0;   // PWM周波数 Maxfreq=80000000.0/2^n[Hz]

const uint8_t PWM_F_CH = 2;  // PWMチャンネル Forward
const uint8_t PWM_R_CH = 3;  // PWMチャンネル Reverse

const uint8_t PWM_F_PIN = 2; // PWM出力に使用するGPIO PIN番号 Forward
const uint8_t PWM_R_PIN = 5; // PWM出力に使用するGPIO PIN番号 Reverse

const double Motor_Drive_dutyRatios[] = {-1.0, -0.75, -0.5, -0.25, 0., 0.25, 0.5, 0.75, 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 value;

MotorDriver mMotorDriver; //class MotorDriver のインスタンス

void setup() {
  M5.begin();
  M5.Power.begin();
  M5.Lcd.setTextSize(4);
  M5.Lcd.print("Single Motor\n Drive Test");

  mMotorDriver.setPins(PWM_F_PIN, PWM_R_PIN, PWM_F_CH, PWM_R_CH);
  mMotorDriver.setPWM(nBits_forPWM, PWM_Frequency);

  M5.Lcd.setCursor(10, 80);
  M5.Lcd.printf("duty ratio =\n   %.4f   ",dutyRatio_Value);
  value = mMotorDriver.driveMotor(dutyRatio_Value);
  M5.Lcd.setCursor(10, 160);
  M5.Lcd.printf("value =\n   %5d   ",value);
}

void loop() {
  M5.update();

  if (M5.BtnA.wasPressed()) {
    dutyRatioIndex ++;
    if (nRatios <= dutyRatioIndex) dutyRatioIndex--;
    dutyRatio_Value = Motor_Drive_dutyRatios[dutyRatioIndex];
    M5.Speaker.tone(880, 200); //Peett
    M5.Lcd.setCursor(10, 80);
    M5.Lcd.printf("duty ratio =\n   %.4f   ",dutyRatio_Value);
    value = mMotorDriver.driveMotor(dutyRatio_Value);
    M5.Lcd.setCursor(10, 160);
    M5.Lcd.printf("value =\n   %5d   ",value);
  }
  if (M5.BtnB.wasPressed()) {
    dutyRatioIndex --;
    if (dutyRatioIndex < 0) dutyRatioIndex++;
    dutyRatio_Value = Motor_Drive_dutyRatios[dutyRatioIndex];
    M5.Speaker.tone(440, 200); //Peett
    M5.Lcd.setCursor(10, 80);
    M5.Lcd.printf("duty ratio =\n   %.4f   ",dutyRatio_Value);
    value = mMotorDriver.driveMotor(dutyRatio_Value);
    M5.Lcd.setCursor(10, 160);
    M5.Lcd.printf("value =\n   %5d   ",value);
  }
}

 モータドライブクラスヘッダファイル MotorDriver.h

//MotorDriver.h//

#ifndef MotorDriver_h
#define MotorDriver_h

class MotorDriver {
  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
  private:
    int fwdPin, rvsPin;
    int fwdChl, rvsChl;
    int pwmMaxValue;
};
#endif

 モータドライブクラス本体ファイル MotorDrive.cpp

//MotorDrive.cpp//

#include <Arduino.h>
#include "MotorDriver.h"

void MotorDriver::setPins(int forwardPin, int reversePin, int forwardChannel, int reverseChannel) {
  fwdPin = forwardPin;
  rvsPin = reversePin;
  fwdChl = forwardChannel;
  rvsChl = reverseChannel;
  pinMode(fwdPin, OUTPUT); //出力したいピンを出力用途に設定
  pinMode(rvsPin, OUTPUT); //出力したいピンを出力用途に設定
}

void MotorDriver::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);
}

//モータ指令値が正のときはモータは正転,負のときは逆転する
//モータ指令値の範囲は-1.0から1.0の間とする -1.0≦dutyratio≦1.0
//デバッグのためにdrivevalueを返す
int MotorDriver::driveMotor(double dutyratio) {
  int drivevalue = (int)(pwmMaxValue * dutyratio);
  if (drivevalue == 0) {
    ledcWrite(PWM_M1_F_CH, 0);
    ledcWrite(PWM_M1_R_CH, 0);
  } else if (0<drivevalue) {
    ledcWrite(PWM_M1_F_CH, pwmMaxValue);
    ledcWrite(PWM_M1_R_CH, pwmMaxValue - drivevalue);
  } else { //drivevalue<0
    ledcWrite(PWM_M1_F_CH, pwmMaxValue + drivevalue);
    ledcWrite(PWM_M1_R_CH, pwmMaxValue);
  }
  return drivevalue;
}

5 実行時の信号観察

PWM周波数を1000Hzにして実行時の GPIO 2 と GPIO 5 の信号をオシロスコープで観察しました。
Ch1(緑)が GPIO 2 ,Ch2(黄)が GPIO 5 です。PWM指令値が正のとき,GPIO 5 にPWM波形が見え, GPIO 2 はHighが保たれています。PWM指令値が負のとき,GPIO 5 はHighが保たれ, GPIO 2 にPWM波形が見えています。

(1)PWM指令値 0.25 のとき,GPIO 2がHighでGPIO 5がLowになる区間が正転駆動区間です。デューティ比:25%が出力されています。


(2)PWM指令値 -0.25 のとき,GPIO 5がHighでGPIO 2がLowになる区間が逆転駆動区間です。デューティ比:25%が出力されています。



6 まとめ

M5StackGrayおよびモータドライバTC78H653FTGによるブラシDCモータ駆動テストを行ないました。

割り当て可能であるとわかっているGPIOピン2,5を使い,PWMチャンネルは2,3をそれぞれ割り当てました。


重要な問題
モータ用電源があらかじめ入っていると,M5Stackの電源が入り,起動してプログラムが起動するまでの間に,モータが回ってしまいます。
M5Stackの電源が入り,プログラムが起動するまでの間は,GPIOピンの状態は設定出来ず,GPIO 2はL,GPIO 5はHになっていることが原因です。
M5Stackの電源を先に入れて,起動してからモータ側の電源を入れるのが良いでしょう。他にも工夫があるかもしれません。


補足1 M5Stack Gray 出力ピン割り当てとPWMチャンネル選定テストの結果

1)M5Stack Grayで用途が制限されているGPIOピン
  ・回路図から読み取った,すでに使用されているGPIOピン
   GPIO 1 3 ............. USB UART0 (RXD0,TXD0)で使用
   GPIO 4 23 18 19 ...... SD SPIと共有
   GPIO 33 27 23 18 14 .. LCDで使用
   GPIO 21 22 ........... I2C,電源管理,モーションセンサ,磁気センサで使われている
   GPIO 25 .............. Audioで使用
  ・ESP32仕様
   GPIO 34~39は読み取り専用

2)M5Stack Grayで使えることを確認したGPIOピン
  GPIO 2, GPIO 5 他とは共用していないので自由に使える
  GPIO 16, GPIO 17 UART2 (TXD2・RXD2)を使わなければ OK
  GPIO 26 DAを使わなければ OK
  GPIO 19 SDを使わなければ OK
  GPIO 35, GPIO 36 ADを使わなければ,入力のみOK

3)M5Stack Grayで使ってはいけない PWMチャンネル
  0 音源として使われている (動作させるとビープ音がなる)
  1 用途は不明だが,干渉され周期もデューティ比も指定とは異なる動作をする
  6 LCDの輝度調整に使われている (動作させるとLCDの文字の明るさが変化する)
    使用bit数が12以上のとき,この現象が現れる
  7 LCDの輝度調整に使われている (動作させるとLCDの文字の明るさが変化する)

4)M5Stack Grayで使用確認できたPWMチャンネル
  2,3,4,5,8,9,10,11,12,13,14,15