Arduino智能避障小車避障程序匯編
《Arduino智能避障小車避障程序匯編》由會員分享,可在線閱讀,更多相關《Arduino智能避障小車避障程序匯編(13頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、首先建立一個名為modulecai.ino的主程序。
// modulecar.iiio,玩轉智能小車主程序
*include
2、const mt trigger = 9 ; 〃定義超聲波傳感器發(fā)射腳為D9 const int echo = 10 ; //定義傳感器接收腳為D10 const int max」ead = 300; 〃設定傳感器最大探測距離。 int no_good = 35; //* 設定 35cm 警戒距離。 int read_aliead; 〃實際距離讀數(shù)。 Seivo sensoiStation; 〃設定傳感器平臺。 NewPmg sensor(tngger, echo, max」ead); 〃設定傳感器弓|腳和最大讀數(shù) 〃系統(tǒng)初始化 void setupQ ( Senal.beg
3、in(9600); 〃啟用串行監(jiān)視器可以給調(diào)試帶來極大便利 sensorStation.attach(l 1); //IE Dll 分配給舵機 pmMode(ENA, OUTPUT); 〃依次設定各 I O 屬性 puiMode(INl, OUTPUT); puiMode(IN2, OUTPUT); pmMode(ENB, OUTPUT); puiMode(IN3, OUTPUT); puiMode(IN4, OUTPUT); puiMode(Uigger, OUTPUT); puiMode(echo, INPUT); sensorStation.wnte(90); 〃舵機
4、更位至 90 1 delay(6000); 〃上電等待6s后進入主循環(huán) } 〃主程序 void loopQ ( read_aliead = readDistanceO; 〃調(diào)用 readDistance。函數(shù)讀出前方距離 Serial.printlii(H AHEAD:"); Senal.pnntln(read_ahead); 〃串行監(jiān)視器顯示機器人前方距離 if (read_aliead < no_good) //如果前方距離小于警戒值 ( fastStopO; 〃就令機器人緊急剎車 waTchO; 〃然后左右查看,分析得出最佳路線 goFofwaidO;"*此處調(diào)
5、用看似多余,但可以確保機器人高速運轉下動作的連貫性 } else goFoiwa】d0; 〃否則就一直向前行駛 } 主程序用到了兩個庫,Sezo庫是IDE自帶的,NwePing庫是第三方庫,需要下載安裝。 接下來建立一個名為move. mo的標簽。 //move.iiio,機動模塊。 〃剎車 void fastStopQ ( SeriaLprintln(“STOP");〃串行監(jiān)視器顯示機器人狀態(tài)為STOP (停止) 〃左電機急停(注:L298N和L293D均帶有剎車功能,在使能成立的條件下,同時向兩 相寫入高電平可令電機急停,詳見芯片手冊) digitalWrite(E
6、NA, HIGH); digitalWnte(INh HIGH); digitalWnte(IN2, HIGH); 〃右電機急停 digitalWrite(ENB, HIGH); digitalWnte(IN3, HIGH); digitalWnte(IN4, HIGH); } 〃前進 void goFoiwaidQ ( Senal.pnntlnCTORWARD) 〃串行監(jiān)視器顯示機器人狀態(tài)為FORWARD (前進) 〃左電機逆時針旋轉 analogWnte(ENA,106); 〃左電機PWM,可微調(diào)這個數(shù)值使小車左右兩側車輪轉速相等,右 電機同理 digitalW
7、nte(INl, LOW); digitalWnte(IN2, HIGH); 〃右電機順時針旋轉 analog Write(ENBJ 18); digitalWnte(IN3, HIGH); digitalWnte(IN4, LOW); } 〃原地左轉 void mniLeftQ ( Senal.pimtln(“LEFT"); 〃串行監(jiān)視器顯示機器人狀態(tài)為LEFT (向左轉) 〃左電機正轉 analogWrite(ENA, 106); digitalWnte(INh HIGH); digitalWnte(IN2, LOW); 〃右電機正轉 analogWnte(
8、ENB,59);〃*微調(diào)這個數(shù)值,使轉彎時內(nèi)側車輪起主導作用。相當于讓小車向后 打一把輪再拐彎。右轉同理 digitalWrite(IN3, HIGH); digitalWnte(IN4, LOW); delay(205);〃*延遲,數(shù)值以亳秒為單位,調(diào)節(jié)此值可使機器人動作連貫 } 〃原地右轉 void tuniRight() ( Senal.pnntln("RIGHT) 〃串行監(jiān)視器顯示機器人狀態(tài)為RIGHT (向右轉) 〃左電機反轉 analogWrite(ENA,53); digitalWnte(INh LOW); digitalWnte(IN2, HIGH); 〃右
9、電機反轉 analog Write(ENB J18); digitalWnte(IN3, LOW); digitalWnte(IN4, HIGH); delay (205); 〃*調(diào)節(jié)此值可使機器人動作連貫 } 〃原地掉頭(暫時用不到) void tuniAioundQ ( Senal.pnnthi(HTURN 180) 〃串行監(jiān)視器顯示機器人狀態(tài)為TURN 180 (原地順時針旋轉 1800 ) 〃左電機反轉 analogWrite(ENA, 106); digitalWnte(INh LOW); digitalWnte(IN2, HIGH); 〃右電機反轉 ana
10、log Write(ENB J18); digitalWnte(IN3, LOW); digitalWnte(IN4, HIGH); delay (500); //* ) //pmg.ino,測距模塊 mt readDistanceQ delay(30);〃聲波發(fā)送間隔30ms,大約每秒探測33次。受系統(tǒng)所限,此值不可小于29ms int cm = sensoi.ping0 / US_ROUNDTRIP_CM; 〃把 Ping 值(Us)轉換為 cm retuin(cm); 〃1eadDistance()返回的數(shù)值是 cm } 最后是驅(qū)動云臺掃描并分析左右兩側距離的watch.
11、ino模塊。 // watch.ino,查看模塊 void waTch() ( 〃測量右前方距離。 //*注意舵機旋轉方向,SG5010為逆時針旋轉 sensoiStation.write(20);〃*舵機右轉至20。調(diào)節(jié)此值會影響傳感器掃描區(qū)域,夾角越小, 機器人轉彎越謹慎 delay(1200); 〃延遲1.2s待舵機穩(wěn)定 mt read_right = ieadDistance(); 〃調(diào)用】eadDistance()函數(shù)讀出右前方距離 Senal.pnnt(”RIGHT「); Senal.piintlii(reacl_nglit); 〃sensorStation.
12、write(90); 〃*舵機更位至90度。廉價舵機大角度旋轉會產(chǎn)生抖動,要加上這 兩行以求讀數(shù)準確。 //delay (500); 〃延遲 0.5s 〃測量左前方距離 sensoiStation.wiite(160); //舵機左轉至 1601 delay(1200); //延遲L2s待舵機穩(wěn)定。 mt read」eft = leadDistanceO; 〃調(diào)用函數(shù)讀出距離左前方距離。 Senal.pnnt("LEFT: Senal.piintlii(read_left); sensorStation.wnte(90); 〃這一行確保只要小車處于行駛狀態(tài),傳感器就面向正前方
13、
delay (500); //延遲 0.5s。
//分析得出最佳行進路線。
if (read_right > read」eft) 〃如果右前方距離比較大
(
nmiRight(); 〃就向右轉,
}
else tinnLeftO; 〃否則就向左轉
〃此處也可以加入另一層邏輯:如果左右兩側讀數(shù)相等就調(diào)用mniAroundO原地掉頭。但 實際上觸發(fā)的幾率不大。
}
// FC 液晶測試程序,Aiduiiio 版本 L5.6-r2, LiquidCiystal_I2C 庫版本 2.0
#mclude
14、" 〃導入 I2C 液晶庫 LiquidCrystal_DC lcd(0x27,16,2); 〃設定 I2C 地址及液晶屏參數(shù) void setupQ Icd.uutQ; //始化液晶屏 Icd.backlightQ; lcd.piint("HeUo, world!1); 〃開始打印信息 lcd.setCursor(3,l);〃設定顯示位置,第3列,第1行 lcd.pnnt(nZANG.HAIBOH); } void loop() ( ) 〃前進 void goForwaid。 { Serial.pnndn("FORWARD) 〃串行監(jiān)視器顯示機器人狀態(tài)為FORWAR
15、D (前進) 〃左電機逆時針旋轉 mt vail = analogRead(AO); 〃手動調(diào)整左電機轉速。電位器兩端分別接至+5V和GND, 中心抽頭接至A0 mt leftSpeed = map(vallQ1023,0,255); //把讀數(shù)映射為 PWM analogWrite(ENA,left Spued); 〃寫入速度。卜.面的右電機同理 digitalWnte(INl, LOW); digitalWnte(IN2, HIGH); //右電機順時針旋轉 mt val2 = analogRead(Al); mt rightSpeed = map(val2.0,1023.0,
16、255); analogWnte(ENB4ightSpeed); digitalWnte(IN3, HIGH); digitalWnte(IN4, LOW); } //ping.mo,紅外測距模塊 〃山gge「腳沿用D9, echo腳換成A3 int readDistanceQ { digitalWHte(tngger,HIGH); 〃點亮紅外發(fā)射管 dulayMiciosecondsQOO); 〃給接收管留出200 u s響應時間 IRvalue=analogRead(echo); 〃讀取自然光和紅外線下反射值的總和 digitalWrite(trigger,LOW);
17、 〃關閉紅外發(fā)射管以讀取自然光下的反射值 dulayMiciosecondsQOO);〃留出 200 us 響應時間 IRvalue=IRvalue-aiialogRead(echo); //刨除自然光得出實際值(紅外發(fā)射管產(chǎn)生的部 分) return niap(IRvalue, 120.930,30.0); //ffl map()函數(shù)把讀數(shù)轉換為距離 ) 超聲波模塊SR04與Arduino連接: TRIG接Digital 5口,觸發(fā)測距;ECHO接Digital 4口,接收距離信號。 程序代碼: intinputPin=4;"定義超聲波信號接收接口 ECHO接4口 int ou
18、tputPin=5; //定義超聲波信號發(fā)出接口 TRIG接5口 void setup() ( Serial.begin(9600); pinMode(inputPin. INPUT); pinMode(outputPin. OUTPUT); ) void loop() ( u f digitalWrite(outputPin, LOW);//便發(fā)出發(fā)命超聲波信號接口低電平2ps , I<*. delayMicroseconds(2); digitalWrite(outputPin. HIGH); 〃使發(fā)出發(fā)出超聲波信號接口高電平1叩s,這里是至少 delayMicroseco
19、nds(10); digitalWrite(outputPin, LOW); //保持發(fā)出超聲波信號接口低電平 int distance = pulseln(inputPin. HIGH); 〃讀出脈沖時間 distance= distance/58; //將脈沖時間轉化為距離(單位:厘米) Serial .println(dlstance); /隔出距離值 delay(50); } 代碼1: HC-SR04超聲波傳感器典型代碼 digitalWrite(TrigPin, LOW); delayMicroseconds(2); digitalWnte(TngPin. HIGH);〃
20、發(fā)送10 ms的高電平觸發(fā)信號 delayMicroseconds( 10); digitalWrite(TrigPin, LOW); distance - pukeIn(EchoPin, HIGH廣340/60/2; 〃檢測脈沖寬度即為超聲波往返時間 代碼2:簡易超聲波測距代碼 const int TrigPin - 2; const int EchoPni - 3; 〃設定 SR04 連接的 Arduino 引腳 float distance; void setupQ { 〃初始化串口通信及連接SR04的引腳 Serial.begin(9600); pmMode(Tng
21、Pin, OUTPUT); //要檢測引腳上輸入的脈沖寬度,需要先設置為輸入狀態(tài) pinMode(EchoPm. INPUT); Senal.prmtln(uUltrasomc sensor:**); } void loop() { 〃產(chǎn)生一個10 us的高脈沖去觸發(fā)TngPm digitalWrite(TrigPin, LOW); delayMicroseconds(2); digitalWrite(TrigPin, HIGH); delayMicroseconds( 10); digitalWrite(TrigPin, LOW); //檢測脈沖寬度,并計算出距離 d
22、istance - pulseIn(EchoPin. HIGH) /58.00;
Serial.prmt(distance);
Serial.prmt(Mcm,r);
Senal.printlnO; delay(1000);
}
代碼3:具有溫度補償?shù)某暡y距代碼
ffinclude
23、lue: ffdefine ONE_WIRE_BUS 4 OneWire oneWire(ONE_WIRE_BUS); DallasTempeiature sensors(&oneWue); void setupQ { 〃初始化串口通信及連接SR04的引腳 Serial.begin(9600); pmMode(TngPin, OUTPUT); 〃要檢測引腳上輸入的脈沖寬度,需要先設置為輸入狀態(tài) pinMode(EchoPm. INPUT); sensors.beginQ; } void loop() { 〃產(chǎn)生一個10 us的高脈沖去觸發(fā)TngPm sensors.ieq
24、uestTeinpeiatures(); teinperature_value - sensois.getTeixipCByliidex(O); Seiial.prmt(Mtemperauue -"); Sei ial.priiit(temperatui e_value); Serial.print(HC ”); digital\Vrite(TiigPin, LOW); delayMicioseconds(2); digital\Vrite(TiigPin, HIGH); delayMici oseconds( 10); digital\Vrite(TiigPin, LOW)
25、; 〃檢測脈沖寬度,并計算出距離 distance - pulseIn(EchoPm. HIGH) *(331.4+0.6*temperatuie_value)/2; Serial.print(Mdistance - ); Seiial.priiit(distance); Seiial.pnnt(”cm"); Seiial.prmtlnQ; delay(lOOO); 代碼4:基于GP2D12的紅外測距系統(tǒng)代碼 int i; float val; void setup(){ Serial.begin(9600); } void loop(){ i=analogRea
26、d(A0); val=2547.8/((float)i*0.49-10.41)-0.42; Serial.println(val/2); } 〃藍牙遙控小車 //Arduino源程序 〃定稿口期:2016-3-16 〃程序功能簡介: 〃程序采用軟件PWM方式,控制兩支直流電機的運行行為,實現(xiàn)直行、后退、左轉和右轉 動作。 〃操作者使用Android 機的藍牙功能發(fā)出指令,操控小車動作。 〃操作者還通過藍牙對小車的動作參數(shù)進行調(diào)試。 〃使用自定義串口收發(fā)數(shù)據(jù) 〃使用軟件PWM,輸出引腳可任意制定 〃使用Atmega48芯片 //Arduio 版本 1.0.5
27、
#include
28、 = 0; unsigned int RP = 0; unsigned int LD = 0; unsigned int RD = 0; unsigned int PWM[6]; 〃存放當前PWM參數(shù)的整數(shù)型數(shù)組,全局變量 unsigned char inputString[8]; //存輸入數(shù)據(jù)字符串變量 boolean stringComplete = false; // 數(shù)據(jù)串結束標志 〃定時器2初始化函數(shù) void timer2Jnit() ( cli(); TCCR2B = 0x00; // TCNT2 = 0xF6; // TCCR2A = 0x00;
29、TCCR2B = 0x02; // TIMSK2 = 0x01; 〃定時器2中斷允許 sei(); ) 〃定時器2中斷服務函數(shù) //PWM波形產(chǎn)生器 ISR(TIMER2_OVF_vect) TCNT2 = 0xF6; // counter++; if(counter == Ox3ff) { if (rDirect == 1) bitSet(P0RTDz5); else bitSet(P0RTD,4); if (IDirect == 1) bitSet(P0RTD,7); else bitSet(P0RTD,6); counter = 0; } if(c
30、ounter == pwm_RH) { bitClearfPORTD^); bitClearfPORTD^); } if(counter == pwm_LH) { bitClearfPORTD^); bitClearfPORTDJ); } ) 〃電機運行函數(shù) void Move(unsigned int LS,unsigned charLD,unsigned int RS,unsigned char RD) ( asm("BCLR7"); 〃關中斷 pwm_LH = LS; pwm_RH = RS; IDirect = LD; rDirect = RD; a
31、sm(”BSET7”); 〃開中斷 ) 〃獲取EEPROM數(shù)據(jù)函數(shù) 〃功能:從EEPROM里順序讀出六個PWM參數(shù),存入PWM數(shù)組 void GetData() ( unsigned char bytes[2]; 〃暫時存放PWM參數(shù)的字節(jié)數(shù)組,全局變量 unsigned char i; unsigned char j; unsigned char k; for(i = 0;i < 6;i++) //for 循環(huán),讀六個參數(shù) for (j = 0;j < 2;j++) 〃內(nèi)循環(huán),每次讀兩個字節(jié) { k = i*2 + l-j; 〃地址計算 bytes。] = EEPRO
32、M.read(k); //EEPROM 讀操作 } PWM = word(bytes[0], bytes[l]); 〃將讀出的兩個字節(jié)合成一個PWM整數(shù)數(shù)據(jù) } ) 〃數(shù)據(jù)發(fā)送函數(shù) 〃功能:將一個整數(shù)拆分成四個ASCH代碼,通過藍牙串口發(fā)出的函數(shù)。 〃例如:整數(shù)784,將拆分成;二7,8:星四個字符 void Numberfint val) ( inttmp; 〃中間變量 unsigned char i; //循環(huán)計數(shù)變量 unsigned char buf[4]; 〃存字符數(shù)組 tmp= val/1000; buf[O] = tmp + 0x30; 〃獲得千位
33、val= val % 1000; tmp= val/100; buf[l] = tmp + 0x30; 〃獲得百位 val= val % 100; tmp= val/10; buf[2] = tmp + 0x30; 〃獲得十位 val= val % 10; buf[3] = val + 0x30; 〃獲得個位 for(i = 0;i < 4;i++) { if (buf == 0x30) 〃從高位整理,如果是3則轉換成空格。 buf =0x20; else break; } Usart_Transmit(buf[O]); 〃通過藍牙串11連續(xù)發(fā)出四個字符。 Usa
34、rt_ Transmit(buf[ 1]); Usart_ Transmit(buf[2]); Usart_Transmit(buf[3]); } void setupf) { timer2_init(); UsartJnit(9600); sei(); PORTD = 0x00; DDRD = OxFO; GetDataf); 〃初始化PWM參數(shù) ) void loop() { unsigned char buf[6]; 〃存連續(xù)字符的數(shù)組 unsigned char index = 0; 〃存索引值變量 unsigned char i; unsigned char
35、 k; unsigned int para; 〃存 PWM 數(shù)據(jù)變量 delay(500); iffstringComplete == true) 〃分解手機傳過來的參數(shù) ( 〃格式是:#n%dddd k= 0; 〃其中:n為索引(地址);dddd為數(shù)據(jù) index = 0; for (i = 0;i <= wCnt ;i++) { if (inputString == %) ( index = inputstring卜 1] - 0x30; 〃獲得索引 k = 0; } else buf[k] = inputstring - 0x30; 〃獲得數(shù)據(jù) k++; par
36、a = 0; for(i = 0;i < k-l;i++) para = para * 10 + buf; PWM[index] = para; 〃將得到的整數(shù)參數(shù)立即存入對應的PWM數(shù)組單元,修改當前運 行參數(shù) buf[l] = lowByte(para); 〃將整數(shù)轉換成兩個字節(jié)。 buf[O] = highByte(para); index = index * 2; 〃計算 EE PROM 地址 EEPROM.writefindex, buf[l]); 〃寫入 EEPROM 低位在前 index++; EEPROM.writefindex, buf[O]); 〃高位在后
37、 stringComplete = false; wCnt = 0; } ) ISR(USART_RX_vect) wCnt = 0; break; case d: 〃接收到d,右轉 LP = PWM[4]; RP = PWM[5]; LD = 1; RD = O; wCnt = 0; break; case s: 〃接收到后,停止電機 LP = 0; RP = O; LD = 1; RD = 1; wCnt = 0; break; default: LP = 0; RP = O; LD = 1; RD = 1; } Move(LRLD,RERD); }
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。