Arduino小程式——超聲波避障遙控小車
之前偶然間瞭解到Arduino,腦子一熱果斷入手一套簡單的小車開發套件,後來由於忙些其他的東西,就把它丟在角落裡吃灰了……上個月正好表妹過生日,決定弄一弄也算準備一個誠意滿滿的小禮物了;這也是第一次接觸硬體程式設計,也算是個小挑戰。
由於只是入門級別的套件,像超聲波,舵機,直流電機等配件的程式碼都是現成的,只需要配置開發環境,寫自己的小車執行邏輯就行了,忍不住吐槽一下黑心商家的配件,各種問題搞得開發過程中莫名其妙的被坑……
安裝好開發軟體,把開發板接入電腦就可以寫程式碼了,開發板接入電腦後先看看埠號:
然後開發軟體中記得選擇對應的埠,不然無法燒錄程式。
新建一個專案,發現自動生成2個函式:
void setup()函式是初始化函式,裡面的語句只會執行一次,一般用來設定硬體的引腳;void loop()函式是程式執行函式,裡面的語句會重複執行(有點類似createjs的Ticker類),下面貼一個簡單LED燈閃爍程式碼。
void setup(){
pinMode(11, OUTPUT); //將11號引腳上拉輸出
}
void loop(){
digitalWrite(11,HIGH); //設定11號引腳位高電平
delay(1000);
digitalWrite(11,LOW); //設定11號引腳為低電平
delay(1000); // 閃爍時間間隔為1S
}
寫完程式碼需要先編譯再燒錄到開發板裡才能看到效果,有些複雜的配件需要監控返回值,比如超聲波要看返回檢測到障礙物的距離,紅外遙控要看返回按鍵的鍵值,這就要用到串列埠監視器了;寫好程式碼,每次按下紅外遙控器,串列埠監視器會返回鍵值:
Serial.print(results.value);//返回當前按鍵值
注意串列埠監視器下面的波特率要和我們設定的一致。
Serial.begin(9600);
使用自帶的開發介面寫程式碼很不習慣,可以在首選項裡設定使用外部編輯器,這樣軟體會把開發頁面鎖死,只能通過其他編輯器寫程式碼了,這裡我用sublime text(語言選擇C++程式碼才會高亮顯示)。
下面貼個全部原始碼,留個備份:
#include <Servo.h> #include <IRremote.h> long control; boolean car_automatic_move = false; boolean car_trajectory = false; //紅外避障模組 // long SL; //紅外接收模組 int RECV_PIN = 11;//管腳 //舵機 int servopin = 10; IRrecv irrecv(RECV_PIN); decode_results results; long unsigned int return_decode() { if (irrecv.decode(&results)) { irrecv.resume(); Serial.print(results.value);//返回當前按鍵值 return results.value; } else { return 0; irrecv.resume(); } } void setup() { Serial.begin(9600); pinMode(2, INPUT); pinMode(4, INPUT); pinMode(7, INPUT); pinMode(8, INPUT); pinMode(A0, INPUT); pinMode(3, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); digitalWrite(7, LOW); digitalWrite(8, LOW); irrecv.enableIRIn();//初始化紅外遙控 } void loop() { // SL = digitalRead(A0);//左避障管腳 // if (car_automatic_move && SL == 0) {//左避障觸發 // car_forward(); // } control = return_decode(); if (control == 16712445) {//前進 car_forward(); delay(500); car_stop(); } else if (control == 16720605) {//後退 car_back(); delay(500); car_stop(); } else if (control == 16769055) {// - car_left(); delay(150); car_stop(); } else if (control == 16754775) {// + car_right(); delay(150); car_stop(); } else if (control == 16761405) {//暫停 car_stop(); car_automatic_move = false; } else if (control == 16748655) {//EQ car_automatic_move = true; } else if (control == 16750695) {//100+ } else if (control == 16756815) {//200+ } else if (control == 16738455) {//0 原地打轉 car_left(); } else if (control == 16753245) {//CH- servopulse(servopin, 180); } else if (control == 16769565) {//CH+ servopulse(servopin, 0); } else if (control == 16736925) {//CH servopulse(servopin, 65); } // car_line(); car_automatic(); } void car_forward() {//前進 analogWrite(3, 0); analogWrite(5, 255); analogWrite(6, 255); analogWrite(9, 0); } void car_back() {//後退 analogWrite(3, 255); analogWrite(5, 0); analogWrite(6, 0); analogWrite(9, 255); } void car_stop() {//停車 analogWrite(3, 0); analogWrite(5, 0); analogWrite(6, 0); analogWrite(9, 0); } void car_left() {//左轉 analogWrite(3, 255); analogWrite(5, 0); analogWrite(6, 255); analogWrite(9, 0); } void car_right() {//右轉 analogWrite(3, 0); analogWrite(5, 255); analogWrite(6, 0); analogWrite(9, 255); } void car_line() {//紅外循跡 if (car_trajectory) { if (digitalRead(4)) {//左探頭 Serial.print("left"); } if (digitalRead(2)) {//右探頭 Serial.print("right"); } } } long speedF; long speedL; long speedR; // 超聲波檢測距離 int ardublockUltrasonicSensorCodeAutoGeneratedReturnCM(int trigPin, int echoPin) { long duration; pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(20); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); duration = duration / 59; return duration; } //定義一個脈衝函式 void servopulse(int servopin, int myangle) { int pulsewidth, count; for (count = 0; count < 25; count++) { pulsewidth = (myangle * 11) + 500; //將角度轉化為500-2480的脈寬值 digitalWrite(servopin, HIGH); //將舵機介面電平至高 delayMicroseconds(pulsewidth);//延時脈寬值的微秒數 digitalWrite(servopin, LOW); //將舵機介面電平至低 delay(20 - pulsewidth / 1000); } } // 測量前方距離 int range_F() { speedF = ardublockUltrasonicSensorCodeAutoGeneratedReturnCM(7, 8) ; Serial.print("speedF:"); Serial.println(speedF); return speedF; } // 自動行駛 void car_automatic() { if (car_automatic_move) { car_forward(); if (range_F() <= 18) { car_stop(); car_automatic_move = false; delay(300); servopulse(servopin, 20); if (range_F() > 18) { //檢測右方距離 servopulse(servopin, 65); car_right(); delay(120); car_automatic_move = true; } else if (range_F() <= 18) { //檢測右方距離 delay(300); servopulse(servopin, 110); if (range_F() > 18) { //檢測左方距離 servopulse(servopin, 65); car_left(); delay(120); car_automatic_move = true; } else if (range_F() <= 18) { //檢測左方距離 car_back(); servopulse(servopin, 65); delay(120); car_right(); delay(120); car_automatic_move = true; } } } } }
本來要寫紅外避障模組的,可惜有一個紅外避障配件是壞的,而且紅外感應器“怕太陽光”,即使沒有直接被陽光直射到,白天在室內也可能被太陽熱輻射影響到紅外訊號,避障變成“智障”……一個直流電機也有問題,只有設定電流引數255才會工作,所以無法調整小車的行駛速度,再次吐槽一下黑心商家……