本文旨在補充《超圖解Arduino互動設計入門》第十章小型直流馬達控制板單元。TB6612FNG是東芝生產的馬達驅動與控制IC,內部包含兩組H橋式電路,可驅動和控制兩個小型直流馬達,或者一個雙極性步進馬達。跟L298N比較,從外觀看來,TB6612FNG控制板明顯嬌小,而且沒有散熱片,這兩個馬達控制板的主要規格比較如下:
上表「效率」欄位的說明,請參閱下一篇文章。
用TB6612FNG直流馬達驅動板取代L298N模組
L298晶片也有比較小型的PowerSO20封裝型式(L298P型號),但如果你的微控制板採3.3V供電,例如:Arduino Pro Mini、執行JavaScript的Espruino、ESP8266系列控制板…等等,TB6612FNG模組是比較好的選擇,除非你採用的直流馬達工作電壓大於13V。
底下是一款常見的TB6612FNG直流馬達驅動模組的接腳說明:
上圖是最精簡的TB6612FNG控制板,某些板子配有直流電壓轉換器替馬達驅動IC供電,有的板子具有防止反接馬達電壓的電路,不過,這些TB6612FNG板的連接電路和操控方式都一樣。
和L298N對照,你可以發現TB6612FNG只多了一個STBY(standby,待機,相當於省電)模式接腳,控制馬達的接腳和接線,都跟L298N一樣。下表列舉控制「馬達A」的輸入和輸出關係,1代表高電位,0代表低電位:
下圖TB6612FNG與Arduino的接線示範是仿照書本「A型馬達控制板」的接線,程式碼也完全一樣(參閱10-34頁或者「L298N馬達控制板接線與控制程式補充」),重點是馬達驅動板的PWMA和PWMB要接在Arduino的PWM腳。
使用TB6612FNG程式庫控制兩個直流馬達
雖然控制TB6612FNG模組的程式不難,但還是有更簡單的方式。TB6612FNG有幾個程式庫可選,本文介紹美國Spark Fun電子材料供應商撰寫的SparkFun_TB6612FNG_Arduino程式庫,因為程式碼很簡單,底下直接採用程式庫附帶的範例來介紹相關指令。
這個程式庫有支援「待機模式」,因此請將TB6612FNG模組的STBY接在任何可用的數位或類比腳,本文把STBY接在數位11腳。
每個馬達都要透過程式庫的Motor()函式建立「馬達物件」,接下來的程式碼就能透過「馬達物件」執行驅動(drive)、前進(forward)、左轉(left)…等功能。底下是程式碼開頭的控制腳位宣告,以及建立兩個馬達物件的程式片段(請注意!底下程式的接線設定以上圖為主,跟原始範例不同):
直流馬達的正轉或反轉,跟擺設和人們的觀察視角有關。以下圖為例,馬達其實都是朝同一方向旋轉,但擺設方式不同,所以轉向也不一樣。
為此,這個程式庫安排了一個“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)
煞車。將兩個輸入都設成高電位來停止馬達。
請問程式可以輸入物件的名子嗎
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)
}
你可以用陣列或struct來存放多個伺服馬達物件,像這樣:
Servo servos[12];
再透過索引編號個別操控。
thanks,
jeffrey
老師您好
我看了您的書後依樣畫葫蘆組裝一台車並寫了一個測試程式
但不知為何馬達就是不轉,百思不得其解
希望老師閒暇時能幫我看看問題出在哪
接線圖片:
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);
}
}
問題應該是出在loop(),程式執行到底下這一行,馬達的才會通電:
analogWrite(ENA, POWER);
建議先採用動手做10-6的程式測試。
thanks,
jeffrey
老師請問為何我照上方教學
之後跑範例程式時
motor函式卻一直無法使用
moto函式無法使用…請問你有安裝程式庫嗎?
thanks,
jeffrey
要怎麼安裝程式庫呢???
我上網查都沒找到
這一篇貼文有介紹:
https://swf.com.tw/?p=897
那個您好,我又有問題了
我用這個指令原本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);
}
}