TB6612FNG直流馬達驅動∕控制板(一):簡介、程式庫與取代L298N模組

本文旨在補充《超圖解Arduino互動設計入門》第十章小型直流馬達控制板單元。TB6612FNG是東芝生產的馬達驅動與控制IC,內部包含兩組H橋式電路,可驅動和控制兩個小型直流馬達,或者一個雙極性步進馬達。跟L298N比較,從外觀看來,TB6612FNG控制板明顯嬌小,而且沒有散熱片,這兩個馬達控制板的主要規格比較如下:

比較TB6612FNG直流馬達驅動板與L298N模組

上表「效率」欄位的說明,請參閱下一篇文章

用TB6612FNG直流馬達驅動板取代L298N模組

L298晶片也有比較小型的PowerSO20封裝型式(L298P型號),但如果你的微控制板採3.3V供電,例如:Arduino Pro Mini、執行JavaScript的Espruino、ESP8266系列控制板…等等,TB6612FNG模組是比較好的選擇,除非你採用的直流馬達工作電壓大於13V。

底下是一款常見的TB6612FNG直流馬達驅動模組的接腳說明

TB6612FNG直流馬達驅動模組接腳

上圖是最精簡的TB6612FNG控制板,某些板子配有直流電壓轉換器替馬達驅動IC供電,有的板子具有防止反接馬達電壓的電路,不過,這些TB6612FNG板的連接電路和操控方式都一樣。

和L298N對照,你可以發現TB6612FNG只多了一個STBY(standby,待機,相當於省電)模式接腳,控制馬達的接腳和接線,都跟L298N一樣。下表列舉控制「馬達A」的輸入和輸出關係,1代表高電位,0代表低電位:

TB6612FNG的輸入與輸出關係表

下圖TB6612FNG與Arduino的接線示範是仿照書本「A型馬達控制板」的接線,程式碼也完全一樣(參閱10-34頁或者「L298N馬達控制板接線與控制程式補充」),重點是馬達驅動板的PWMA和PWMB要接在Arduino的PWM腳。

TB6612FNG與Arduino的接線示範

使用TB6612FNG程式庫控制兩個直流馬達

雖然控制TB6612FNG模組的程式不難,但還是有更簡單的方式。TB6612FNG有幾個程式庫可選,本文介紹美國Spark Fun電子材料供應商撰寫的SparkFun_TB6612FNG_Arduino程式庫,因為程式碼很簡單,底下直接採用程式庫附帶的範例來介紹相關指令。

這個程式庫有支援「待機模式」,因此請將TB6612FNG模組的STBY接在任何可用的數位或類比腳,本文把STBY接在數位11腳。

每個馬達都要透過程式庫的Motor()函式建立「馬達物件」,接下來的程式碼就能透過「馬達物件」執行驅動(drive)、前進(forward)、左轉(left)…等功能。底下是程式碼開頭的控制腳位宣告,以及建立兩個馬達物件的程式片段(請注意!底下程式的接線設定以上圖為主,跟原始範例不同):

TB6612FNG程式庫的初始化程式碼

直流馬達的正轉或反轉,跟擺設和人們的觀察視角有關。以下圖為例,馬達其實都是朝同一方向旋轉,但擺設方式不同,所以轉向也不一樣。

馬達的擺設方式影響轉向

為此,這個程式庫安排了一個“offset”變數(「抵消」之意),透過設定1或-1來決定馬達的初始轉向。

底下是TB6612FNG程式庫的完整範例程式碼,馬達物件的控制方法指令,請參閱下文說明。

#include <SparkFun_TB6612.h>

#define AIN1 8   // 控制輸入A1
#define AIN2 7   // 控制輸入A2
#define BIN1 10  // 控制輸入B1
#define BIN2 9   // 控制輸入B2
#define PWMA 6
#define PWMB 5
#define STBY 11  // 「待機」控制接Arduino的11腳

const int offsetA = 1;  // 正反轉設定A,可能值為1或-1。
const int offsetB = 1;  // 正反轉設定B,可能值為1或-1。

Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);

void setup() {
 // 這裡沒有程式碼
}

void loop() {
   motor1.drive(255,1000);   // 驅動馬達1全速正轉1秒
   motor1.drive(-255,1000);  // 驅動馬達1全速反轉1秒
   motor1.brake();           // 停止馬達1
   delay(1000);
   
   motor2.drive(255,1000);   // 驅動馬達2全速正轉1秒
   motor2.drive(-255,1000);  // 驅動馬達2全速反轉1秒
   motor2.brake();           // 停止馬達2
   delay(1000);
   
   forward(motor1, motor2, 150);  // 驅動雙馬達半速前進
   delay(1000);				       // 持續1秒
   
   back(motor1, motor2, -150);  // 驅動雙馬達半速前進
   delay(1000);
   
   brake(motor1, motor2);     // 停止兩個馬達
   delay(1000);
   
   left(motor1, motor2, 100);   // 左轉
   delay(1000);
   right(motor1, motor2, 100);  // 右轉
   delay(1000);
   
   brake(motor1, motor2);     // 停止兩個馬達
   delay(1000);   
}

SparkFun_TB6612FNG程式庫馬達物件的方法

底下是這個程式庫馬達物件提供的方法指令:

  • drive(速度, 持續時間)
    驅動一個馬達。「速度」是介於-255~255的整數值,數字越大,轉速越高,負值代表反轉。「持續時間」是選擇性參數,用於指定轉動時間。

  • standby()
    將晶片設定成待機模式。執行任何驅動馬達的指令(drive, forward, back, left和right),將停止待機模式。

  • forward(馬達物件1, 馬達物件2, 速度)
    驅使兩個馬達前進。若執行此指令的結果是「後退」,請修改offset值;速度值介於-255~255整數,若「速度」值為負,馬達也會反轉:若忽略「速度」值,代表採用程式庫預設的DEFAULTSPEED值(255)。

  • back(馬達物件1, 馬達物件2, 速度)
    驅使兩個馬達後退。若執行此指令的結果是「前進」,請修改offset值。

  • left(馬達物件1, 馬達物件2, 速度)
    驅使左、右馬達分別反轉和正轉,達成左轉效果。

  • right(馬達物件1, 馬達物件2, 速度)
    驅使左、右馬達分別正轉和反轉,達成右轉效果。

  • brake(馬達物件1, 馬達物件2)
    煞車。將兩個輸入都設成高電位來停止馬達。
Posts created 468

9 thoughts on “TB6612FNG直流馬達驅動∕控制板(一):簡介、程式庫與取代L298N模組

  1. 請問程式可以輸入物件的名子嗎
    servo 1_1,1_2,1_3,2_1,2_2~~~,4_3;
    void Mod1(char aa,char bb){ //伺服馬達控制角度副程式,可選擇12個中其中兩個
    aa.write(115);
    bb.write(85);}
    void setup(){
    }
    void loop(){
    Mod1(1_2,1_3)
    }

    1. 你可以用陣列或struct來存放多個伺服馬達物件,像這樣:

      Servo servos[12];

      再透過索引編號個別操控。

      thanks,
      jeffrey

  2. 老師您好
    我看了您的書後依樣畫葫蘆組裝一台車並寫了一個測試程式
    但不知為何馬達就是不轉,百思不得其解
    希望老師閒暇時能幫我看看問題出在哪
    接線圖片:
    https://drive.google.com/file/d/1A6VLhAWpFvZnh1p4W3WhD9CnkhCw5et8/view?usp=sharing

    boolean run = false;

    const byte IN1 = 10;
    const byte IN2 = 9;
    const byte ENA = 5;

    const byte IN3 = 8;
    const byte IN4 = 7;
    const byte ENB = 6;

    byte POWER = 100;

    void forward() {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
    }

    void backward() {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
    }

    void turnLeft() {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
    }

    void turnRight() {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
    }

    void setup() {
    pinMode(IN1, OUTPUT);
    pinMode(IN2, OUTPUT);
    pinMode(ENA, OUTPUT);
    pinMode(IN3, OUTPUT);
    pinMode(IN4, OUTPUT);
    pinMode(ENB, OUTPUT);
    }

    void loop(){
    forward();
    run = true;
    delay(1000);

    backward();
    run = true;
    delay(1000);

    turnLeft();
    run = true;
    delay(1000);

    turnRight();
    run = true;
    delay(1000);
    run = false;

    if (run) {

    analogWrite(ENA, POWER);
    analogWrite(ENB, POWER);
    } else {

    analogWrite(ENA, 0);
    analogWrite(ENB, 0);
    }

    }

    1. 問題應該是出在loop(),程式執行到底下這一行,馬達的才會通電:

      analogWrite(ENA, POWER);

      建議先採用動手做10-6的程式測試。

      thanks,
      jeffrey

  3. 那個您好,我又有問題了
    我用這個指令原本tp6612能操控馬達
    但後面卻沒辦法了,有甚麼原因嗎
    #include

    int trigPin =7; //Trig Pin
    int echoPin =6; //Echo Pin
    long duration, cm ;
    #define AIN1 32 // 控制輸入A1
    #define AIN2 34 // 控制輸入A2
    #define BIN1 36 // 控制輸入B1
    #define BIN2 38 // 控制輸入B2
    #define PWMA 5
    #define PWMB 4
    #define STBY 11 // 「待機」控制接Arduino的11腳
    const int offsetA = 1; // 正反轉設定A,可能值為1或-1。
    const int offsetB = 1; // 正反轉設定B,可能值為1或-1。

    Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
    Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);

    void setup() {
    Serial.begin (9600); // Serial Port begin
    pinMode(trigPin, OUTPUT); // 定義輸入及輸出
    pinMode(echoPin, INPUT);
    }

    void loop()
    {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(5);
    digitalWrite(trigPin, HIGH); // 給 Trig 高電位,持續 10微秒
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    pinMode(echoPin, INPUT); // 讀取 echo 的電位
    duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間
    cm = (duration/2) / 29.1; // 將時間換算成距離 cm 或 inch
    Serial.print(“Distance : “);
    Serial.print(cm);
    Serial.print(“cm”);
    Serial.println();
    delay(10);
    if (cm>5){
    forward(motor1, motor2, 200); // 驅動雙馬達半速前進
    delay(100);
    }
    else
    {
    brake(motor1, motor2); // 停止兩個馬達
    delay(100);
    back(motor1, motor2, 200); // 驅動雙馬達後退
    delay(500);
    motor2.drive(255,1000); // 驅動馬達 2 全速正轉 1 秒
    brake(motor1, motor2); // 停止兩個馬達
    delay(100);
    }
    }

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top