L298N馬達控制板接線與控制程式補充

本文旨在補充《超圖解Arduino互動設計入門》第十章。第10-31頁列舉兩種採用L298N的控制板,並採用第二種說明控制程式寫法,本文介紹第一種控制板的接線與程式範例。

10-31頁的第一種馬達控制板的控制接線比較多,但也是最原始的L298N電路的接線方式,因為這個板子的電路類似10-30頁的電路圖。如果您打算DIY或者在麵包板上組裝一個L298M控制板,請參考本文的控制程式。

基本的馬達控制電路接線如下:

L298N馬達控制板+Arduino+FA-130馬達

註1:馬達控制板的「致能A」和「致能B」腳,接Arduino的PWM腳位。

註2:為了避免接線圖凌亂,本文並未如10-30頁般,銜接Arduino的數位2和3腳。

註3:此控制板的IN1和IN2,等同10-30頁的「輸入1A」和「輸入2A」;IN3和IN4等同「輸入1B」和「輸入2B」。

從序列埠控制馬達轉向

實驗目標:讓Arduino接收來自「序列埠監控視窗」的w, a, s, d, x等字元,進而控制兩個馬達的轉向。

筆者採用的FA-130型馬達,其建議工作電壓為1.5V~3V。由於筆者的馬達電源輸入是5V,透過底下的算式可得知,PWM輸出值為153時,約等同輸出3V電壓給馬達(反之,從Arduino控制板的PWM輸出訊號值,請不要超過153):

PWM輸出電壓

實驗程式碼如下:


// 接收序列埠值的變數
char cmd;
// 設定啟動或停止馬達的參數
// 一開始先設定成「停止」
boolean run = false;

// 左馬達控制設定
const byte LEFT1 = 10;
const byte LEFT2 = 9;
const byte LEFT_PWM = 5;

// 右馬達控制設定
const byte RIGHT1 = 8;
const byte RIGHT2 = 7;
const byte RIGHT_PWM = 6;

// 設定PWM輸出值(註:FA-130馬達供電不要超過3v)
byte motorSpeed = 100;

void forward() {	// 馬達轉向:前進
 digitalWrite(LEFT1, HIGH);
 digitalWrite(LEFT2, LOW);
 digitalWrite(RIGHT1, HIGH);
 digitalWrite(RIGHT2, LOW);
}

void backward() {	// 馬達轉向:後退
 digitalWrite(LEFT1, LOW);
 digitalWrite(LEFT2, HIGH);
 digitalWrite(RIGHT1, LOW);
 digitalWrite(RIGHT2, HIGH);
}

void turnLeft() {	// 馬達轉向:左轉
 digitalWrite(LEFT1, LOW);
 digitalWrite(LEFT2, HIGH);
 digitalWrite(RIGHT1, HIGH);
 digitalWrite(RIGHT2, LOW);
}

void turnRight() {	// 馬達轉向:右轉
 digitalWrite(LEFT1, HIGH);
 digitalWrite(LEFT2, LOW);
 digitalWrite(RIGHT1, LOW);
 digitalWrite(RIGHT2, HIGH);
}

void setup() {
  Serial.begin(9600);
  pinMode(LEFT1, OUTPUT);
  pinMode(LEFT2, OUTPUT);
  pinMode(LEFT_PWM, OUTPUT);
  pinMode(RIGHT1, OUTPUT);
  pinMode(RIGHT2, OUTPUT);
  pinMode(RIGHT_PWM, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    cmd = Serial.read();
    
    switch (cmd) {
      case 'w':		// 接收到'w',前進。
        forward();
        run = true;	// 啟動馬達
        break;
      case 'x':		// 接收到'x',後退。
        backward();
        run = true;	// 啟動馬達
        break;
      case 'a':		// 接收到'a',左轉。
        turnLeft();
        run = true;	// 啟動馬達
        break;
      case 'd':		// 接收到'd',右轉。
        turnRight();
        run = true;	// 啟動馬達
        break;
      case 's':
        run = false;	// 停止馬達
        break;
    }
  }
  
  if (run) {	
    // 如果要啟動馬達…
    // 向馬達輸出指定的類比電壓值
    analogWrite(LEFT_PWM, motorSpeed);
    analogWrite(RIGHT_PWM, motorSpeed);
  } else {
    // 否則…
    // 將馬達的電壓值設定成0
    analogWrite(LEFT_PWM, 0);
    analogWrite(RIGHT_PWM, 0);
  }
}
  
Posts created 467

43 thoughts on “L298N馬達控制板接線與控制程式補充

  1. 英傑先生,
    我今天針對「超圖解Arduino互動設計入門」,在給您的email中提了2個問題。
    其中第2個問題是:「在14-18頁的圖中,L298N的GND直接接到Arduino板的GND上,那電池的負極接哪裡?」。

    您的回答是:「GND接地,就是一般電源的「負極」」,這並沒有切中我的問題。
    我的意思是:電池的正極是接到L298N的5V或12V)上,而負極本來是要接到 GND去的,但現在L298N的GND卻已經被用來跟arduino的GND連接了,那電池的負極要接哪裡?

    1. hi frank:

      電路中的接地都是相接在一起的,所以電池的負極可以接在Arduino控制板的任何一個GND接孔(註:UNO板子上面有3個GND插孔)。

      thanks,
      jeffrey

  2. jeffrey,

    「超圖解Arduino互動設計入門」ch14中:
    1、我把電池線接到L298N的5V腳,紅色LED亮,遙控馬達,卻不動。
    我把L298N的ENA及ENB的jumper都拆掉,再分別接到D6及D5,IN1接到D7,IN3接到D4,IN2及
    IN4 空接,這樣對嗎?若馬達線接錯,應該只是轉動方向問題,應不至於不會動吧?
    2、手機顯示<、>、x等方向符號,而switch case是用’w’、’x’、’a’、’d’、’s’,不會有問題吧?

    Thanks
    Frank

    1. hi frank:

      假設你的馬達控制板和上文相同,它的輸入∕輸出關係表,請參閱10-30頁上方的表10-5。馬達控制板的IN1, IN2控制馬達A的轉向;IN3和IN4則控制馬達B的轉向。

      所以依照上文的程式:
      ENA接D5,IN1, IN2接D9和D10。
      ENB接D6,IN3, IN4接D7和D8。

      至於手機顯示<、>、x等方向符號,只是操作介面的外觀;使用者按下這些按鈕時,實際送出的值就是’w’、’x’、’a’、’d’、’s’。相關說明請參閱附錄E,或者「Windows版App Inventor 2.0離線版軟體(Ai2LiveComplete)安裝說明與基礎操作」文末的「App Inventor 2.0版附錄E與範例檔下載」單元。

      thanks,
      jeffrey

  3. jeffrey,

    我的L298N模組與書本不一樣,但已經參照元智大學網路文章的安裝方式,成功。另外,我買的藍牙模組之PIN腳功能也與書本所標示的不一樣,但也已經安裝成功。而程式stop部分得要多加2行,才能正常運作,見下面備註「Added by me」那2行。
    void stop() { // 馬達停止
    analogWrite(EA, 0); // 馬達 A 的 PWM 輸出
    digitalWrite(IA, LOW); // Added by me 
    analogWrite(EB, 0); // 馬達 B 的 PWM 輸出
    digitalWrite(IB, LOW); // Added by me
    }

    Thanks
    Frank

  4. 我供電的地方我用電表量是13V,在還沒接馬達前兩側馬達輸出電壓為3V,但是一街上馬達之後輸出電壓剩0.6V 左右 導致馬達轉不動, 我一直找不出原因可以幫我解答嗎?

    1. hi michael:

      L298N的技術文件第3頁有記載此IC在驅動馬達時,會有1.8V/1A~4.9V/2A的電壓降(total drop),所以驅動3V的小型馬達,控制板的馬達電源接5V就夠了。你電源接13V,再接上負載之後電壓降到0.6V…我覺得應該是控制板的IC或二極體故障了。

      thanks,
      jeffrey

  5. 老師您好
    我是本書的門外漢讀者 我按照此網頁的接法 並將l298n接9V電池 另將l298n的5v接到arduino的5v 小車能走 但常發出嗶嗶聲 而且馬達好像不太順 容易卡住 請教是甚麼原因? 這是l298n發出的聲音嗎? 需要給arduino另外接電源嗎?
    謝謝

    1. hi tammy:

      一般小車的馬達應該是採用3V小馬達,我覺得問題是出在馬達的電流不足,請改接5V測試——我現在大都改用手機的行動電源,方便實用。

      thanks,
      jeffrey

  6. 老師我想請問一下,我最近買了兩個L298N驅動模組(對岸出場的),他有四個上拉電阻選擇腳跟兩個AB項致能控制還有2個CSA/B通道電流檢測腳。
    我想問如果要控制馬達轉速是要從致能控制腳輸入PWM訊號嗎?
    還有上拉電阻的功用到底為何?我查了好多資料都沒說明清楚。
    CSA/B檢測腳要怎麼使用?

    感謝老師抽空幫忙。

    1. hi oakmilk:

      是的,可從EN腳輸入PWM訊號控制轉速。
      如同10-29頁說明,L298N的1和15腳用於偵測馬達的堵轉電流。多數的L298N馬達控制模組都沒有使用這項功能,ST晶片廠商的L298系列技術文件,第7頁也有說明,若需要偵測堵轉電流,可在這兩個腳位連接低歐姆數的電阻,第8頁的示範電路連接的是0.5Ω的電阻。

      技術文件第3頁的電子特性表(ELECTRICAL CHARACTERISTICS)有提到這兩個接腳的Vsense電壓,最大值為2V。假設它們輸出2V,依照歐姆定律,流經0.5Ω的電流將高達4A!也就是這兩個電阻各自要承受8W的熱量!

      如果真要連接這兩個電阻,你可以從預設的堵轉電流反推,假設堵轉電流是2A,電阻值設定為0.5Ω,消耗熱量就是2W,建議至少採用3W, 0.5Ω電阻。

      thanks,
      jeffrey

  7. 老師您好:本人依照此書上的教學學習自製避障自走車,按照範例上的線路接法與程式碼上傳,供應電源後馬達卻沒有反應(馬達是用外接電源12v Arduino板用9v) 有試過直接給馬達供電可正常運轉,題,但是接上去L298N馬達控制模組後可看到馬達控制面板上接角的LED發光但馬達卻不會動,請老師幫個忙~ 謝謝!

    1. hi hank:

      請先單獨測試L298N控制板和馬達,參閱10-30頁的表10-5,先把輸入1A(in1)、輸入1B(in2)分別接5V和接地,致能A(EN A)接5V,再接上馬達、馬達電源和控制板的5V電源,馬達應該會轉動。如果馬達不轉,代表L298N控制板可能故障了。

      thanks,
      jeffrey

  8. 你好,我用以下程式去控制小車的直流減速馬達
    在前進時有時候兩顆同時跑不動(會發出很像蜂鳴的聲音)、有時候兩顆有點像同時跑但是很卡且時間點對不上
    不知道是哪裡出了問題,如有空煩請解答謝謝。

    // 右輪馬達-A
    const byte IN1 = 5; // 馬達A 的正反轉接腳編號
    const byte IN2 = 6;
    const byte ENA = 3; // 馬達A 的 PWM 轉速控制

    // 左輪馬達-B
    const byte IN3 = 9; // 馬達B 的正反轉接腳編號
    const byte IN4 = 10;
    const byte ENB = 11; // 馬達B 的 PWM 轉速控制

    int speed; // 定義速度變數,PWM 輸出範圍為 0~255

    void setup() {
    pinMode(IN1, OUTPUT);
    pinMode(IN2, OUTPUT);
    pinMode(ENA, OUTPUT);

    pinMode(IN3, OUTPUT);
    pinMode(IN4, OUTPUT);
    pinMode(ENB, OUTPUT);

    speed = 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, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    }

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

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

    void loop() {
    analogWrite(ENA, speed); //輸出 PWM 脈衝到 ENA
    analogWrite(ENB, speed); //輸出 PWM 脈衝到 ENB

    forward(); // 前進
    delay(1000); // 延時5秒
    backward(); // 後退
    delay(1000); // 延時5秒
    turnLeft(); // 左轉
    delay(1000); // 延時5秒
    turnRight(); // 右轉
    delay(1000); // 延時5秒

    stop();
    delay(600); // 延時6秒

    speed += 40; // 加速
    if (speed >= 240) { // 速度超過 240 則回到預設值(100)
    speed = 100;
    }
    }

  9. 我把ENA和ENB的跳線帽拆除,分別會露出兩個pin腳,請問我是用ENA其中一個pin腳跟ENB其中一個pin腳來連接PWM的pin腳即可嗎?

    1. EN腳用跳線帽連接的另一腳是5V,你可以觀察印刷電路板上的銅箔走線,ENA和ENB的跳線相鄰腳之間,應該有銅箔相連,或者,你可以用三用電錶的電阻檔位檢測,跳線帽連接的其中一腳與5V相連。

      通常有印字的那一腳就是ENA或ENB接腳,另一腳是5V,不要連錯了。

      thanks,
      jeffrey

  10. 老師您好:
    想要詢問老師您
    如果想要透過一個按鍵更改 馬達的轉速
    應該怎麼做呢?
    例如
    手機按下A鍵 馬達轉速就會提高
    手機按下B鍵 馬達轉速就會降低

    感謝
    謝謝

    1. hi hackerC:

      首先,你要知道如何控制馬達的轉速;
      然後,要知道如何開發手機APP,
      光是開發APP的工具和程式語言就有好多種。
      你先解決第一個問題,再處理下個問題。

      thanks,
      jeffrey

  11. 關於馬達並聯電容的用意

    請問是因為步進馬達內部線圈之電感在迴路中產生感抗(+90度相位)

    使用電容之容抗(-90度相位)藉此抵銷虛功率

    也就是LC電路互相充放? 否則線圈會在L298N的PIN腳上輸入突波

    這樣講對嗎?

    1. 我不確定你說得對不對,不過,並聯在直流馬達上的電容和IC電源腳的旁路電容一樣,都是用來吸收電源或訊號之外的突波雜訊,就這樣。

      thanks,
      jeffrey

  12. 你好~
    我用陀螺儀控制傾斜到一定角度時馬達起動正常,輸出電壓也與輸入電壓相同,但再加上超音波感測器偵測距離使馬達停止,使用電表量測L298 OUT輸出,輸出電壓小於輸入給馬達的12V指有1V左右(PWM已設定225),這是什麼原因?

    1. 超音波感測器並不是直接與L298N相連,所以這兩者沒有關聯,問題應該是出在程式邏輯。

      thanks,
      jeffrey

  13. 程式碼是這樣,也試過不同寫法的超音波感測器,使用電表量測馬達輸出都有電壓,指是都在1V以內而已,會使有接腳衝突嗎(使用UNO版)?

    #include
    #include
    #include
    #define Echo 13
    #define Trig 12
    long duracion, distancia;

    MPU6050 mpu;
    int16_t ax, ay, az;
    int16_t gx, gy, gz;

    void setup()
    {
    Wire.begin();
    Serial.begin(9600);
    Serial.println(“Initialize MPU”);
    mpu.initialize();
    Serial.println(mpu.testConnection() ? “Connected” : “Connection failed”);
    pinMode(Echo, INPUT);
    pinMode(Trig, OUTPUT);
    pinMode(7,OUTPUT); //IN3
    pinMode(8,OUTPUT); //IN4
    pinMode(9,OUTPUT); //ENB
    pinMode(4,OUTPUT); //IN1
    pinMode(5,OUTPUT); //IN2
    pinMode(6,OUTPUT); //ENA

    }
    void loop()
    {
    mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    ax = map(ax, -17000, 17000, -125, 125);
    digitalWrite(Trig, LOW);
    delayMicroseconds(2);
    digitalWrite(Trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(Trig, LOW);
    duracion = pulseIn(Echo, HIGH);
    distancia = (duracion/2) / 29;

    if(ax > 0 &&distancia >= 100 && distancia >= 1){
    Serial.println(ax);
    if(ax>80){
    Serial.println(ax);
    // 馬達轉向:前進(兩個馬達都正轉)
    digitalWrite(8,HIGH);
    digitalWrite(7,LOW);
    analogWrite(9,255);
    digitalWrite(5,HIGH);
    digitalWrite(4,LOW);
    analogWrite(6,255);

    if (distancia = 1){

    analogWrite(9,0);
    Serial.println(“Danger……”) ;}

    else{
    Serial.println(ax);
    analogWrite(6,0);
    analogWrite(9,0);
    }
    }
    }
    }

    1. 看來是條件運算式有誤:

      (ax > 0 && distancia >= 100 && distancia >= 1)

      改成:

      (ax > 0 && distancia <= 100 && distancia >= 1)

      thanks,
      jeffrey

  14. 你好!我用的是L298N控制9V的直流馬達,但是馬達沒有轉動
    const int motorIn1=5;
    const int motorIn2=6;

    void setup()
    {
    pinMode(motorIn1, OUTPUT);
    pinMode(motorIn2, OUTPUT);
    }

    void loop()
    {
    for(int i=150; i<256; i+=10)
    {
    analogWrite(motorIn1, i);\\正轉加速
    analogWrite(motorIn2, 0);
    delay(150);
    }
    analogWrite(motorIn1, 0);
    analogWrite(motorIn2, 0);
    delay(2000);
    }

    1. 請先用簡單的程式確定是否能轉動,改自你的程式碼:

      const int motorIn1=5;
      const int motorIn2=6;
      
      void setup() {
        pinMode(motorIn1, OUTPUT);
        pinMode(motorIn2, OUTPUT);
      
        analogWrite(motorIn1, 128);
      }
      
      void loop(){
      }
      

      你還要確認控制板的形式,照理說你應該還要接上1A, 1B之類的腳位(請參閱10-29頁的表格)。

      thanks,
      jeffrey

  15. 不好意思老師,我想我找到問題了,程式的部分我相信大致上沒有問題,問題出在馬達輸出的電壓,用電表量了一下,當供電為9V時(這是馬達需求電壓),量出的電壓不足1V,後來我換成12V,馬達就轉動了,所以我想請問這是正常的現象嗎嗎?!會不會是IC本身的問題??

  16. 老師你好
    最近遇到一個問題 當L298N接6V輸入的時候馬達輸出有3V,但輸入電壓6V改成12V時,會沒有輸出
    請問這是甚麼問題?

    還有就是L298N能提高馬達輸出電壓,或是不要讓輸出壓降這麼高
    有甚麼辦法可以解決?

    1. 1. 我覺得是馬達的電源端子接錯了,L298N IC本體的電源和馬達的電源是分開的,如10-28頁所示。
      2. L298N無法提高馬達的電壓輸出,假設馬達的電源是12V,它最高就只能供給12V,但是你可以透過PWM調控馬達的電力,讓它介於0V~馬達電壓(如:12V)之間,如10-34頁程式裡的speed變數。

      thanks,
      jeffrey

  17. 赵老师您好
    我有个问题向您请教,我用了您的例子代码通过串口监视器,进行控制电机运转正常,没有问题。可是随后,用我的蓝牙HC-06模块,已设置成从机模式(把串口的设置都改成了蓝牙接收的设置)和我的安卓手机(锤子手机 Android 5.1.1版本),利用App inventor 2进行交互界面控制却完全没有反应(以排除以下问题的可能1、手机蓝牙已经搜索到,配对成功。2、l298n的电机输出口,用万用表测量没有电压)下面是程序,请你指教!感谢!:)
    #include // 引用「軟體序列埠」程式庫
    SoftwareSerial BT(3, 2); // 設定軟體序列埠(接收腳, 傳送腳)
    char command;

    // 接收序列埠值的變數

    //char cmd;
    // 設定啟動或停止馬達的參數
    // 一開始先設定成「停止」
    boolean run = false;

    // 左馬達控制設定
    const byte LEFT1 = 10;
    const byte LEFT2 = 9;
    const byte LEFT_PWM = 5;

    // 右馬達控制設定
    const byte RIGHT1 = 8;
    const byte RIGHT2 = 7;
    const byte RIGHT_PWM = 6;

    // 設定PWM輸出值(註:FA-130馬達供電不要超過3v)
    byte motorSpeed = 255;

    void forward() { // 馬達轉向:前進
    digitalWrite(LEFT1, HIGH);
    digitalWrite(LEFT2, LOW);
    digitalWrite(RIGHT1, HIGH);
    digitalWrite(RIGHT2, LOW);
    }

    void backward() { // 馬達轉向:後退
    digitalWrite(LEFT1, LOW);
    digitalWrite(LEFT2, HIGH);
    digitalWrite(RIGHT1, LOW);
    digitalWrite(RIGHT2, HIGH);
    }

    void turnLeft() { // 馬達轉向:左轉
    digitalWrite(LEFT1, LOW);
    digitalWrite(LEFT2, HIGH);
    digitalWrite(RIGHT1, HIGH);
    digitalWrite(RIGHT2, LOW);
    }

    void turnRight() { // 馬達轉向:右轉
    digitalWrite(LEFT1, HIGH);
    digitalWrite(LEFT2, LOW);
    digitalWrite(RIGHT1, LOW);
    digitalWrite(RIGHT2, HIGH);
    }

    void setup() {
    //Serial.begin(9600);
    BT.begin(9600); // 啟動軟體序列埠
    pinMode(LEFT1, OUTPUT);
    pinMode(LEFT2, OUTPUT);
    pinMode(LEFT_PWM, OUTPUT);
    pinMode(RIGHT1, OUTPUT);
    pinMode(RIGHT2, OUTPUT);
    pinMode(RIGHT_PWM, OUTPUT);
    }

    void loop() {
    // if (Serial.available() > 0) {
    // cmd = Serial.read();
    if (BT.available() > 0) {
    command = BT.read();
    // switch (cmd) {
    switch (command) {
    case ‘w’: // 接收到’w’,前進。
    forward();
    run = true; // 啟動馬達
    break;
    case ‘x’: // 接收到’x’,後退。
    backward();
    run = true; // 啟動馬達
    break;
    case ‘a’: // 接收到’a’,左轉。
    turnLeft();
    run = true; // 啟動馬達
    break;
    case ‘d’: // 接收到’d’,右轉。
    turnRight();
    run = true; // 啟動馬達
    break;
    case ‘s’:
    run = false; // 停止馬達
    break;
    }
    }

    if (run) {
    // 如果要啟動馬達…
    // 向馬達輸出指定的類比電壓值
    analogWrite(LEFT_PWM, motorSpeed);
    analogWrite(RIGHT_PWM, motorSpeed);
    } else {
    // 否則…
    // 將馬達的電壓值設定成0
    analogWrite(LEFT_PWM, 0);
    analogWrite(RIGHT_PWM, 0);
    }
    }

    1. 「代码通过串口监视器,进行控制电机运转正常。」也就代表Arduino的代码没有问题,请在Android手机安装 “Bluetooth Serial” 软件,通过它发送字符测试看看。

      thanks,
      jeffrey

  18. 感谢您的回复,我下面试一下。另外还有个问题:您第三版光盘里的离线的《app inventor offline》应该如何安装呢?求指教谢谢:)

  19. 你好 我的馬達並不會轉 只會一直發出聲音 一直找不出問題點

    const int motorIn1=11; //左輪馬達前進
    const int motorIn2=10; //左輪馬達後退
    const int motorIn3=5; //右輪馬達前進
    const int motorIn4=6; //右輪馬達後退

    const int SLeftLeft = 7; //中間 左感測器輸入腳
    const int SRightRight = 8; //中間 右感測器輸入腳
    const int SL = 9; //外側 左感測器輸入腳
    const int SR = 3; //外側 右感測器輸入腳
    const int LS = 12; //光感測器

    int LL,RR,LA,RA,LON;
    int spdL,spdR,spd_low,spd_bk,spd_tn;
    int RUN=1,DONE=0,CNT=0;;

    void setup() {

    pinMode(motorIn1,OUTPUT);
    pinMode(motorIn2,OUTPUT);
    pinMode(motorIn3,OUTPUT);
    pinMode(motorIn4,OUTPUT);

    pinMode( SLeftLeft,INPUT);
    pinMode( SL,INPUT);
    pinMode( SRightRight,INPUT);
    pinMode( SR,INPUT);
    pinMode( LS,INPUT);
    spdL=70;
    spdR=80;
    spd_low=40;
    spd_bk=50;
    spd_tn=80;
    }

    void CarStop()
    {
    analogWrite(motorIn1,0);
    analogWrite(motorIn3,0);
    analogWrite(motorIn2,0);
    analogWrite(motorIn4,0);
    }

    void CarCTRL()
    {
    if ((LA == 0) && (LL == 1) && (RR == 1) && (RA == 0))
    {
    analogWrite(motorIn1,spdL);
    analogWrite(motorIn3,spdR);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    if ((LA == 0) && (LL == 1) && (RR == 0) && (RA == 0))
    {
    analogWrite(motorIn1,spd_low);
    analogWrite(motorIn3,spdR);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 0) && (LL == 0) && (RR == 1) && (RA == 1))
    {
    analogWrite(motorIn1,spdL);
    analogWrite(motorIn3,spd_low);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 0) && (LL == 0) && (RR == 0) && (RA == 1))
    {
    analogWrite(motorIn1,spd_tn-30);
    analogWrite(motorIn3,0);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 1) && (LL == 1) && (RR == 0) && (RA == 0))
    {
    analogWrite(motorIn1,spd_low);
    analogWrite(motorIn3,spdR);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 1) && (LL == 0) && (RR == 0) && (RA == 0))
    {
    analogWrite(motorIn1,0);
    analogWrite(motorIn3,spd_tn);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 0) && (LL == 0) && (RR == 1) && (RA == 0))
    {
    analogWrite(motorIn1,spdL);
    analogWrite(motorIn3,spd_low);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    else if ((LA == 0) && (LL == 0) && (RR == 0) && (RA == 0))
    {
    analogWrite(motorIn2,spd_bk);
    analogWrite(motorIn4,spd_bk+10);
    analogWrite(motorIn1,LOW);
    analogWrite(motorIn3,LOW);
    }
    else
    {
    analogWrite(motorIn1,spd_low);
    analogWrite(motorIn3,spd_low);
    analogWrite(motorIn2,LOW);
    analogWrite(motorIn4,LOW);
    }
    // 計算停止後之行駛時間
    if (DONE == 1)
    {
    CNT++;
    if (CNT > 30000)
    {
    DONE=0;
    CNT=0;
    }
    }
    }

    void loop()
    {

    LL=digitalRead(SLeftLeft);
    RR=digitalRead(SRightRight);
    LA=digitalRead(SL);
    RA=digitalRead(SR);
    LON=digitalRead(LS);

    if ((LON == 0) && (DONE == 0))
    {
    CarStop();
    delay(1000);
    DONE=1;
    }
    else CarCTRL();

    }

    1. 建議先用簡單的轉動程式測試,也許是馬達供應電流不足所導致。

      thanks,
      jeffrey

  20. 老師您好!
    有個問題想請教您。如何讓馬達電壓與PWM值成正比例關係?
    我想用的Arduino精確控制馬達輸出電壓的大小,採用12.6V的鋰電池給L298N供電,在PWM輸出255,127,63(即佔空比為100%,50%,25%)的情況下,OUT1, OUT2之間(不接馬達)的電壓分別為12.6V,6.2V,3.1V,完全符合PWM值與輸出電壓成正比例的關係。
    然而,一旦OUT1,OUT2之間接上馬達,馬達電壓與PWM值呈現非線性關係:在PWM = 255時,電壓為10.32(低於理論值2V); PWM = 127時,電壓為7.6 V(這次卻高於理論值1.5V); PWM = 63時,電壓為3.7V。
    第二次實驗,我用另一組8V的鋰電池,新購的L298N,不同型號的馬達做了同樣的實驗,得出一樣的結果。一旦OUT1,OUT2之間接上馬達,電壓發生變化,與PWM值呈現非線性關係。
    第三次實驗,我用兩種鋰電池直接連接馬達,實測馬達電壓和電源電壓一致。
    第四次實驗,L298N接4歐姆(和馬達的內阻相同)的電阻,奇怪的是接上電阻後,電壓竟然也與pwm值呈現非線性關係。

    結論,經過四次實驗發現,無法用PWM值控制想要的電壓。雖然L298N的空載輸出電壓與PWM值成正比例;但是一旦接上負載,不管是馬達還是電阻,電壓與PWM值呈現誇張的非線性關係。

    請問,如何用PWM值控制馬達電壓的大小?

    1. 因為輸出電路在沒有連接負載的情況下,不會受到其他元件的影響,所以輸出訊號和預期相同(線性變化)。

      馬達內部包含線圈,接上馬達時,控制器的輸出端相當於連接一個由電阻和電感構成的濾波器,進而影響輸出訊號(電感類似電容,會儲存電能);馬達透過線圈通電所產生的磁場來驅動轉子旋轉,一開始會消耗較多的電流才能驅動。

      每一種馬達的物理特性都不同,再加上馬達驅動的裝置也不一樣(如:不同重量的自走車,或不同樣式的扇葉),我們很難從輸出的PWM訊號來預測轉速,唯一的方法是加裝「轉速計」,像遮光型光電開關或霍爾感測器,再從轉速感應器的回傳(回授)訊號來調整PWM輸出。

      thanks,
      jeffrey

    1. 額…正好是Arduino新書的其中一個單元內容,需要搭配編碼器取得馬達轉速,才能用程式協調讓兩輪的速度趨近一致。

發佈留言

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

Related Posts

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

Back To Top