底下說明如何製作一台循線自走車,將沿著地上黑色膠帶往前行駛,Arduino程式撰寫非常簡單,此次利用市場最便宜的紅外線循跡感測元件(IR Tracker Sensor)來製作及Motoduino一塊板子即可以簡單做到,請參考一下做法。
一. 使用材料 : (材料購買網站)
1. Motoduino 或 Arduino + 馬達驅動板
2. 紅外線循跡感測器 (IR Tracker Sensor)
3. 9V電池一顆 及 電池釦線
4. USB傳輸線 (下載程式用)
圖一
安裝過程 (step by step):
Step 1:
圖一是所有組裝材料及工具,首先可以先把車子底盤兩面的土黃色貼紙撕下,需要花點時間撕下因為黏膠很強,如圖二,或不撕保持貼紙在上面也可以。
圖二
Step 2:
利用螺絲及馬達固定鐵片把馬達固定在車子底盤上,如圖三及圖四。
圖三
圖四
Step 3:
測速馬盤可以不裝上馬達轉軸上面,如要安裝上去要特別注意不要推的太進去,容易卡到馬達固定鐵片邊緣,圖三的測速馬盤就推太進去且利用四條馬達電線(兩黑兩紅)直接接上馬達或用焊接方式也可以。
Step 4:
萬向輪的固定比較麻煩一點,利用銅柱螺絲鎖在底盤上,固定方式請參考圖五及圖六。
圖五
圖六
Step 5:
固定IR Tracker Sensor於自走車平台下方,且利用塑膠柱螺絲鎖在前方底盤上,固定方式請參考圖七。連接 6 PIN 排線於Sensor上
圖七
圖八
圖九
Arduino 程式 (Sketch):
程式說明:
/////////////////////////////////////////////
影片觀賞: http://www.youtube.com/watch?v=sTala_3r8mA&list=UU6aKpj71jLKYABYLr3Wbpuw&index=13
參考資料網站:
http://motoduino.com
http://sinocgtchen.blogspot.com
圖七
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
Vcc --> 5V, GND-->GND, L -->D9, C-->D10, R-->D11。
如果是配合新版 Motoduino U1 則
Vcc --> 5V, GND-->GND, L -->D9, C-->D8, R-->D7
圖八
圖九
Arduino 程式 (Sketch):
程式說明:
/////////////////////////////////////////////
///三路紅外線感測器與Motoduino的腳位對應
// 如果是用 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 第一版
// 如果是用 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
大大我想請問一下 這行是什麼意思啊?
回覆刪除nIRStatus = digitalRead(SRightRight);
if(nIRStatus == 1)
byteSensorStatus = (byteSensorStatus | 0x01);
drivemotor(byteSensorStatus);
最後一張圖有八個狀態,就是我要把三個sensor感測到的值轉換成0到7的數字,然後再來控制兩顆馬達要如何轉動.
刪除噢噢謝謝大大
回覆刪除可是她是怎麼計算的啊?
我想應該是這行在做運算
byteSensorStatus = (byteSensorStatus | 0x01);
可是想不出是為什麼阿 麻煩大大了~
你可能需去翻一下C語言的書, 了解 bitwise operation.
刪除大大我想再問你一個問題 因為我有結合藍芽
回覆刪除那如執行 紅外線自走的時候 去無法中斷跳出
不知大大可不可以教學一下^^
不太懂你的意思,可以再說清楚一點嗎?
刪除這是我結合了 藍芽遙控 跟 紅外線自走
回覆刪除剛開始自走都沒有問題 但是只要按下自走的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. 把while改成 if()方式.
刪除2. 試想想當你按下按鈕, sw的值變化已被執行過多少次?
記得多利用 Serial.println() 印出訊息來debug,這樣你才知道問題所在.
謝謝大大提醒
回覆刪除我又多加了個判斷式就OK了 ^^
大大你好
刪除請教一下,你的判斷式是怎麼寫的??
大大請問一下 如果我不要讓車子跑那麼快
回覆刪除是不是只要改255這個值就好啦?
forward(0, 255);
您好
回覆刪除我上周訂購了您的自走車套件組
組裝後遇到了一些問題
1.軌道的寬度沒辦法像您網站中影片呈現的一樣細
需要跟軌道感應器寬度一樣才能夠走
大約是影片中的軌道寬度三倍
2.請問軌道的R角有特別的數字嗎?
有時候R角會無法順暢行走
3.senser左右邊感應不太平均
有時候很順暢
有時候會有一邊感應不到
麻煩您了
謝謝
可以用email來信詢問較方便?
刪除可以拍張照給我看看?
回答您的問題:
1. 軌道寬3倍!如果寬度大於感測器第一顆到最後一顆寬度就無法辨識軌道!
2. R角沒有特別數字! 建議把車子速度放慢試試!
3. 請問軌道是黑色? 什麼材質? 電池是不是快沒電?
尋軌不能正常尋軌是什麼情形??
回覆刪除尋軌不能正常尋軌是什麼情形??
回覆刪除您好 請問此程式可以用在arduino嗎?
回覆刪除還是只能用在 Motoduino
感謝
L293D模組 馬達要給致能腳嗎
回覆刪除應該說L293D的IC 有 enable pin.
刪除所以L293D馬達模組不用給enable pin
刪除就只給馬達輸出腳位?
L293D IC本身需要enable pin, 如果是模組各廠家設計不一樣,要看規格! 建議你可以查 一下規格或線路圖最清楚!
刪除請問:
回覆刪除我從D2讀進來的值會0->1->0->1不斷循環。正常應該是碰到黑線為0,讀到非黑是1?
我是用下列程式測的
http://www.motoduino.com/component/content/article/?layout=edit&id=83
Ted Lee
這樣說明很難判定問題, 沒看到硬體線路!
刪除感謝回覆
刪除硬体是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
我剛試是正常的! 手靠近ST188 IO board上的LED會亮起, 手移開就滅掉! 你有接其他東西? 麻煩用email聯繫比較快! sinocgtchen@gmail.com
刪除結語:
刪除剛換了RJ11線並重燒程式後已測試成功
有再測另一顆ST188,調了一下可變電阻後也OK了
感謝Dennis Chen and Sam Lin
Ted Lee
有辦法單寫成是讓機器人走嗎
回覆刪除直流馬達送電就會走了
刪除但重奌是您想要怎麼走
Ted Lee
不是很明白您的意思! 要單寫成讓機器人走?
回覆刪除請問如果他再循線,要讓他尋找黑色的線
回覆刪除// 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);
}
程式是要這樣改嗎?
要利用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