總網頁瀏覽量

2013年5月9日 星期四

循線自走車製作 = Motoduino(Arduino + L293D) + IR Tracker Sensor +


底下說明如何製作一台循線自走車,將沿著地上黑色膠帶往前行駛,Arduino程式撰寫非常簡單,此次利用市場最便宜的紅外線循跡感測元件(IR Tracker Sensor)來製作及Motoduino一塊板子即可以簡單做到,請參考一下做法


一.  使用材料 : (材料購買網站)
1.      Motoduino 或  Arduino + 馬達驅動板
2.      紅外線循跡感測器 (IR Tracker Sensor)
3.      9V電池一顆  電池釦線
4.      USB傳輸線 (下載程式用)
5.      小車體套件包




圖一

安裝過程 (step by step):

 Step 1
        圖一是所有組裝材料及工具首先可以先把車子底盤兩面的土黃色貼紙撕下,需要花點時間撕下因為黏膠很強,如圖二,或不撕保持貼紙在上面也可以。

圖二


Step 2:
       利用螺絲及馬達固定鐵片把馬達固定在車子底盤上如圖三及圖四



圖三


圖四

Step 3:
         測速馬盤可以不裝上馬達轉軸上面,如要安裝上去要特別注意不要推的太進去,容易卡到馬達固定鐵片邊緣,圖三的測速馬盤就推太進去且利用四條馬達電線(兩黑兩紅)直接接上馬達或用焊接方式也可以



Step 4:
        萬向輪的固定比較麻煩一點,利用銅柱螺絲鎖在底盤上,固定方式請參考圖五及圖六




圖五


圖六


Step 5:
        固定IR Tracker Sensor於自走車平台下方,且利用塑膠柱螺絲鎖在前方底盤上,固定方式請參考圖七。連接 6 PIN 排線於Sensor上



                                                                          圖七




Step 6:
        連接 6 PIN 排線於Sensor上,接法如圖八及圖九(實際上只接5 pin)
        Vcc --> 5V GND-->GND L -->D9 C-->D10 R-->D11
    如果是配合新版  Motoduino U1 則
       Vcc --> 5V GND-->GND L -->D9 C-->D8 R-->D7



                                                                           圖八


                                                                         圖九
    




Step 7:
        完成圖如圖十。有些細節組裝可以參考我其它文章
                                           

                                                                        圖十





Arduino 程式 (Sketch):
 程式說明:  
                              

 /////////////////////////////////////////////

///三路紅外線感測器與Motoduino的腳位對應
// 如果是用 Motoduino 第一版  使用如下
//const int SLeftLeft = 9;      //左感測器輸入腳
//const int SMiddle = 10;     //中間感測器輸入腳
//const int SRightRight = 11;     //右感測器輸入腳

// 如果是用 Motoduino U1 則使用如下  
const int SLeftLeft = 9;      //左感測器輸入腳
const int SMiddle = 8;     //中間感測器輸入腳

const int SRightRight = 7;     //右感測器輸入腳


// 馬達與motoduino的腳位對應
// 如果是用 Motoduino 第一版  
//const int Motor_E2 = 5; // 控制馬達2轉速 digital pin 5 of Arduino (PWM)    
//const int Motor_E1 = 6;  // 控制馬達1轉速 digital pin 6 of Arduino (PWM)  
//const int Motor_M1 = 7;     // 控制馬達1正反轉 digital pin 7 of Arduino
//const int Motor_M2 = 8;    // 控制馬達2正反轉 digital pin 8 of Arduino

// 如果是用 Motoduino U1 則   
const int Motor_E2 = 6; // 控制馬達2轉速 digital pin 6 of Arduino (PWM)    
const int Motor_E1 = 5;  // 控制馬達1轉速 digital pin 5 of Arduino (PWM)  
const int Motor_M1 = 10;     // 控制馬達1正反轉 digital pin 10 of Arduino


const int Motor_M2 = 11;    // 控制馬達2正反轉 digital pin 11 of Arduino
// 感測器狀態值
byte byteSensorStatus=0;

void setup() {
   //set up serial communications
   Serial.begin(57600);

  // 輸出入接腳初始設定
  pinMode(SLeftLeft, INPUT);
  pinMode(SMiddle, INPUT);
  pinMode(SRightRight, INPUT);
  
  pinMode(Motor_M1, OUTPUT);  // 設定 Motor_M1為輸出腳位
  pinMode(Motor_M2, OUTPUT);  // 設定 Motor_M2為輸出腳位
}

//////////// 主程式 ////////
void loop(){
  int nIRStatus;  

  //清除感測器狀態值
  byteSensorStatus = 0;
  // 讀取左感測器狀態值
  nIRStatus = digitalRead(SLeftLeft);
  if(nIRStatus == 1)
     byteSensorStatus = (byteSensorStatus | (0x01 << 2));
     
  // 讀取中間感測器狀態值   
  nIRStatus = digitalRead(SMiddle);
  if(nIRStatus == 1)
     byteSensorStatus = (byteSensorStatus | (0x01 << 1));
     
    // 讀取右邊感測器狀態值   
  nIRStatus = digitalRead(SRightRight);
  if(nIRStatus == 1)
     byteSensorStatus = (byteSensorStatus | 0x01);

   drivemotor(byteSensorStatus);
}
///////////////////////////

void drivemotor(byte nStatus)
{
  switch(nStatus)
  { //   感測器 黑色:1   白色:0
    case 7: // SL:1 SM:1 SR:1  //黑黑黑
            motorstop(0, 0);
            break;
    case 6: // SL:1 SM:1 SR:0  //黑黑白
            left(0, 255);
            break;
    case 5: // SL:1 SM:0 SR:1  //黑白黑
            motorstop(0, 255);
            break;
    case 4: // SL:1 SM:0 SR:0  //黑白白
            left(0, 255);
            break;
    case 3: // SL:0 SM:1 SR:1 // 白黑黑
             right(0, 255);
             break;
    case 2: // SL:0 SM:1 SR:0  // 白黑白
             forward(0, 255);
             break;
    case 1: // SL:0 SM:0 SR:1  // 白白黑
             right(0, 255);
             break;
    case 0: // SL:0 SM:0 SR:0  //白白白
             forward(0, 255);
  }

}

void motorstop(byte flag, byte motorspeed)
{
  Serial.println("停止!");
  
  digitalWrite( Motor_E1, motorspeed);
  digitalWrite( Motor_E2, motorspeed);

}

void forward(byte flag, byte motorspeed)
{
  Serial.println("forward!");
    
  digitalWrite( Motor_M1, HIGH);
  digitalWrite( Motor_M2, HIGH);
  analogWrite( Motor_E1, motorspeed);
  analogWrite( Motor_E2, motorspeed);
}

void backward(byte flag, byte motorspeed)
{
  Serial.println("backward!");
  
  digitalWrite( Motor_M1, LOW);
  digitalWrite( Motor_M2, LOW);
  analogWrite( Motor_E1, motorspeed);
  analogWrite( Motor_E2, motorspeed);

}

void right(byte flag, byte motorspeed)
{
  Serial.println("right!");  
  
  digitalWrite( Motor_M1, HIGH);
  digitalWrite( Motor_M2, HIGH);
  analogWrite( Motor_E1, 0);
  analogWrite( Motor_E2, motorspeed);
}

void left(byte flag, byte motorspeed)
{
  Serial.println("left!");  
  
  digitalWrite( Motor_M1, HIGH);
  digitalWrite( Motor_M2, HIGH);
  analogWrite( Motor_E1, motorspeed);
  analogWrite( Motor_E2, 0);

}
////////////////////////////////////////////////////


影片觀賞: http://www.youtube.com/watch?v=sTala_3r8mA&list=UU6aKpj71jLKYABYLr3Wbpuw&index=13

參考資料網站:
     http://motoduino.com
     http://sinocgtchen.blogspot.com







30 則留言:

  1. 大大我想請問一下 這行是什麼意思啊?

    nIRStatus = digitalRead(SRightRight);
    if(nIRStatus == 1)
    byteSensorStatus = (byteSensorStatus | 0x01);

    drivemotor(byteSensorStatus);

    回覆刪除
    回覆
    1. 最後一張圖有八個狀態,就是我要把三個sensor感測到的值轉換成0到7的數字,然後再來控制兩顆馬達要如何轉動.

      刪除
  2. 噢噢謝謝大大
    可是她是怎麼計算的啊?
    我想應該是這行在做運算
    byteSensorStatus = (byteSensorStatus | 0x01);
    可是想不出是為什麼阿 麻煩大大了~

    回覆刪除
    回覆
    1. 你可能需去翻一下C語言的書, 了解 bitwise operation.

      刪除
  3. 大大我想再問你一個問題 因為我有結合藍芽
    那如執行 紅外線自走的時候 去無法中斷跳出
    不知大大可不可以教學一下^^

    回覆刪除
    回覆
    1. 不太懂你的意思,可以再說清楚一點嗎?

      刪除
  4. 這是我結合了 藍芽遙控 跟 紅外線自走
    剛開始自走都沒有問題 但是只要按下自走的Button時 他就會陷入無限自走
    而無法跳回手動遙控

    const int Motor_E2 = 5; // 控制馬達2轉速 digital pin 5 of Arduino (PWM)
    const int Motor_E1 = 6; // 控制馬達1轉速digital pin 6 of Arduino (PWM)
    const int Motor_M2 = 7; // 控制馬達1正反轉digital pin 7 of Arduino
    const int Motor_M1 = 8; // 控制馬達2正反轉digital pin 8 of Arduino
    const int SRightRight = 3; //右感測器輸入腳
    const int SLeftLeft = 4; //左感測器輸入腳
    byte sw=1;
    byte byteSensorStatus=0; // 感測器狀態值

    char val; // variable to receive data from the serial port(bluetooth)

    void setup()
    {
    Serial.begin(57600); // Start serial communication at 57600
    // 輸出入接腳初始設定
    pinMode(SLeftLeft, INPUT); //左感測器
    pinMode(SRightRight, INPUT); //右感測器
    pinMode(Motor_M1, OUTPUT); // 設定 Motor_M1為輸出腳位
    pinMode(Motor_M2, OUTPUT); // 設定 Motor_M2為輸出腳位
    }



    void loop()
    {
    while(sw==0)
    {

    int nIRStatus;

    byteSensorStatus = 0; //清除感測器狀態值


    // 讀取左感測器狀態值
    nIRStatus = digitalRead(SLeftLeft);
    if(nIRStatus == 1)
    byteSensorStatus = (byteSensorStatus | (0x01 << 1));

    // 讀取右邊感測器狀態值
    nIRStatus = digitalRead(SRightRight);
    if(nIRStatus == 1)
    byteSensorStatus = (byteSensorStatus | 0x01);

    drivemotor(byteSensorStatus);

    }


    if (Serial.available())
    {
    val = Serial.read();
    switch(val)
    {
    case 'b': // car forward
    forward(0, 255);
    break;
    case 'f': // car backward
    backward(0, 255);
    break;
    case 'l': // car turn left
    left(0, 255);
    break;
    case 'r': // car turn right
    right(0, 255);
    break;
    case 's': // car stop
    motorstop(0, 0);
    break;
    case 'x':
    { // car IRStatu
    if(sw==0)
    {sw=1;
    }

    if(sw==1)
    {sw=0;
    }

    }




    }
    }
    }








    void drivemotor(byte nStatus)
    {
    switch(nStatus)
    {
    //   感測器 黑色:1  白色:0
    case 3: // SL:1 SR:1 //黑黑
    motorstop(0, 0);
    break;
    case 2: // SL:1 SR:0 //黑白
    right(0, 255);
    break;

    case 1: // SL:0 SR:1 // 白黑
    left(0, 255);
    break;
    case 0: // SL:0 SR:0 // 白白
    backward(0, 255);
    break;
    }
    }




    void motorstop(byte flag, byte motorspeed)
    {
    Serial.print("Stop!");
    digitalWrite( Motor_E1, motorspeed);
    digitalWrite( Motor_E2, motorspeed);

    }

    void forward(byte flag, byte motorspeed)
    {
    Serial.print("Forward!");

    digitalWrite( Motor_M1, LOW);
    digitalWrite( Motor_M2, LOW);
    analogWrite( Motor_E1, motorspeed);
    analogWrite( Motor_E2, motorspeed);

    }

    void backward(byte flag, byte motorspeed)
    {
    Serial.print("Backward!");

    digitalWrite( Motor_M1, HIGH);
    digitalWrite( Motor_M2, HIGH);
    analogWrite( Motor_E1, motorspeed);
    analogWrite( Motor_E2, motorspeed);

    }

    void right(byte flag, byte motorspeed)
    {
    Serial.print("Turn Right! ");

    digitalWrite( Motor_M1, HIGH);
    digitalWrite( Motor_M2, HIGH);
    analogWrite( Motor_E1, 0);
    analogWrite( Motor_E2, motorspeed);

    }

    void left(byte flag, byte motorspeed)
    {
    Serial.println("Turn Left!");

    digitalWrite( Motor_M1, HIGH);
    digitalWrite( Motor_M2, HIGH);
    analogWrite( Motor_E1, motorspeed);
    analogWrite( Motor_E2, 0);

    }

    回覆刪除
    回覆
    1. 1. 把while改成 if()方式.
      2. 試想想當你按下按鈕, sw的值變化已被執行過多少次?

      記得多利用 Serial.println() 印出訊息來debug,這樣你才知道問題所在.

      刪除
  5. 謝謝大大提醒
    我又多加了個判斷式就OK了 ^^

    回覆刪除
    回覆
    1. 大大你好
      請教一下,你的判斷式是怎麼寫的??

      刪除
  6. 大大請問一下 如果我不要讓車子跑那麼快
    是不是只要改255這個值就好啦?
    forward(0, 255);

    回覆刪除
  7. 您好
    我上周訂購了您的自走車套件組

    組裝後遇到了一些問題

    1.軌道的寬度沒辦法像您網站中影片呈現的一樣細
    需要跟軌道感應器寬度一樣才能夠走
    大約是影片中的軌道寬度三倍

    2.請問軌道的R角有特別的數字嗎?
    有時候R角會無法順暢行走

    3.senser左右邊感應不太平均
    有時候很順暢
    有時候會有一邊感應不到

    麻煩您了
    謝謝

    回覆刪除
    回覆
    1. 可以用email來信詢問較方便?
      可以拍張照給我看看?

      回答您的問題:
      1. 軌道寬3倍!如果寬度大於感測器第一顆到最後一顆寬度就無法辨識軌道!
      2. R角沒有特別數字! 建議把車子速度放慢試試!
      3. 請問軌道是黑色? 什麼材質? 電池是不是快沒電?

      刪除
  8. 尋軌不能正常尋軌是什麼情形??

    回覆刪除
  9. 尋軌不能正常尋軌是什麼情形??

    回覆刪除
  10. 您好 請問此程式可以用在arduino嗎?
    還是只能用在 Motoduino
    感謝

    回覆刪除
  11. L293D模組 馬達要給致能腳嗎

    回覆刪除
    回覆
    1. 應該說L293D的IC 有 enable pin.

      刪除
    2. 所以L293D馬達模組不用給enable pin
      就只給馬達輸出腳位?

      刪除
    3. L293D IC本身需要enable pin, 如果是模組各廠家設計不一樣,要看規格! 建議你可以查 一下規格或線路圖最清楚!

      刪除
  12. 請問:
    我從D2讀進來的值會0->1->0->1不斷循環。正常應該是碰到黑線為0,讀到非黑是1?

    我是用下列程式測的
    http://www.motoduino.com/component/content/article/?layout=edit&id=83

    Ted Lee

    回覆刪除
    回覆
    1. 這樣說明很難判定問題, 沒看到硬體線路!

      刪除
    2. 感謝回覆
      硬体是Motoduino U1+I/O board
      一入的ST188模組接在D2D3的RJ11接孔
      用http://www.motoduino.com/component/content/article/?layout=edit&id=83
      這隻程式誏ST188由D2讀到的值顯示到serial monitor上會0->1一直跳(有沒碰到黑線都一樣)

      用三入的模組也一樣

      Ted Lee

      刪除
    3. 我剛試是正常的! 手靠近ST188 IO board上的LED會亮起, 手移開就滅掉! 你有接其他東西? 麻煩用email聯繫比較快! sinocgtchen@gmail.com

      刪除
    4. 結語:

      剛換了RJ11線並重燒程式後已測試成功
      有再測另一顆ST188,調了一下可變電阻後也OK了
      感謝Dennis Chen and Sam Lin

      Ted Lee

      刪除
  13. 有辦法單寫成是讓機器人走嗎

    回覆刪除
    回覆
    1. 直流馬達送電就會走了
      但重奌是您想要怎麼走

      Ted Lee

      刪除
  14. 不是很明白您的意思! 要單寫成讓機器人走?

    回覆刪除
  15. 請問如果他再循線,要讓他尋找黑色的線

    // Sensor sequence: SLeftLeft SMiddle SRightRight

    const int SLeftLeft = 10; //左感測器輸入腳

    const int SMiddle = 10; //中間感測器輸入腳

    const int SRightRight = 10; //右感測器輸入腳



    // variables will change:

    int SLL; //左感測器狀態

    int SM; //中感測器狀態

    int SRR; //右感測器狀態

    const int Motor_M1 = 7;

    const int Motor_M2 = 8;

    const int Motor_E1 = 5;

    const int Motor_E2 = 6;

    byte byteSensorStatus=0;

    #define SENSOR_L 4;

    #define SENSOR_M 2;

    #define SENSOR_R 1;



    void setup() {

    //set up serial communications

    Serial.begin(9600);

    // 輸出入接腳初始設定

    pinMode(SLeftLeft, INPUT);

    pinMode(SMiddle, INPUT);

    pinMode(SRightRight, INPUT);

    pinMode(Motor_M1, OUTPUT);

    pinMode(Motor_M2, OUTPUT);

    }



    void loop(){

    byteSensorStatus = 0;

    // 讀取感測器狀態值

    SLL = digitalRead(SLeftLeft);

    if(SLL == 1)

    byteSensorStatus = (byteSensorStatus | (0x01 << 2));

    SM = digitalRead(SMiddle);

    if(SM == 1)

    byteSensorStatus = (byteSensorStatus | (0x01 << 1));

    SRR = digitalRead(SRightRight);

    if(SRR == 1)

    byteSensorStatus = (byteSensorStatus | 0x01);

    // Serial.println(byteSensorStatus, HEX);

    switch(byteSensorStatus)

    { //   感測器黑色:0  白色:1

    case 0: // SL:0 SM:0 SR:0

    motorstop(0, 255);

    break;

    case 1: // SL:0 SM:0 SR:1 //no used

    left(0, 255);

    break;

    case 2: // SL:0 SM:1 SR:0 //no used

    motorstop(0, 255);

    break;

    case 3: // SL:0 SM:1 SR:1

    left(0, 255);

    break;

    case 4: // SL:1 SM:0 SR:0 // no used

    right(0, 255);

    break;

    case 5: // SL:1 SM:0 SR:1

    forward(0, 255);

    break;

    case 6: // SL:1 SM:1 SR:0

    right(0, 255);

    break;

    case 7: // SL:1 SM:1 SR:1

    forward(0, 255);

    }

    }

    void looptest(){

    forward(0,255);

    delay(1000);

    back(0,255);

    delay(1000);

    right(0,255);

    delay(1000);

    left(0,255);

    delay(1000);

    motorstop(0,0);

    delay(3000);

    }

    void motorstop(byte flag, byte numOfValues)

    {

    digitalWrite( Motor_E1, 0);

    digitalWrite( Motor_E2, 0);

    // Serial.println("stop : ");

    }

    void forward(byte flag, byte numOfValues)

    {

    digitalWrite( Motor_M1, LOW);

    digitalWrite( Motor_M2, LOW);

    analogWrite( Motor_E1, numOfValues);

    analogWrite( Motor_E2, numOfValues);

    }

    void back(byte flag, byte numOfValues)

    {

    digitalWrite( Motor_M1, HIGH);

    digitalWrite( Motor_M2, HIGH);

    analogWrite( Motor_E1, numOfValues);

    analogWrite( Motor_E2, numOfValues);

    }

    void right(byte flag, byte numOfValues)

    {

    digitalWrite( Motor_M1, LOW);

    digitalWrite( Motor_M2, LOW);

    analogWrite( Motor_E1, numOfValues);

    analogWrite( Motor_E2, 0);

    }

    void left(byte flag, byte numOfValues)

    {

    digitalWrite( Motor_M1, LOW);

    digitalWrite( Motor_M2, LOW);

    analogWrite( Motor_E1, 0);

    analogWrite( Motor_E2, numOfValues);

    }
    程式是要這樣改嗎?

    回覆刪除
  16. 要利用Auduino 2560自走車集一身以下功能:
    1. 紅外線循軌跡行走
    2. 透過RS485與循軌跡功能行走
    3. 超音波避障偵測
    4. RFID控制偵測送出高或低電位
    5. 接收高或低電位訊號即停車
    6. 手按啟動行走
    7. 手按停止行走
    要找人承包寫程式. 有人願意可報價討論承接...謝謝.....
    李宗達Lee Tsung Da (志勲)手機:0933001611
    郵編:115地址Address:台北市南港區忠孝東路七段512號5樓
    TEL:886-2-27831159
    個人email:sfh92.king@msa.hinet.net

    回覆刪除