(1)智能小車自動運行(先後走,左右轉)html
(2)藍牙控制、遙控器控制、無線手柄控制python
(3)循跡、避障git
(4)視覺編程
(5)裝飾:音樂播放器json
材料 |
數量 |
Arduino主控板 | 1 |
車輪 | 2 |
直流電機 | 2 |
L298N | 1 |
紅外循跡模塊 | 1 |
超聲波模塊 | 1 |
紅外接收器 | 1 |
紅外遙控器 | 1 |
無線手柄及接收器 | 1 |
麪包板 | 1 |
杜邦線 | 若干 |
電池盒 | 1 |
充電鋰電池3.7v | 2 |
開關 | 2 |
萬向輪 | 1 |
銅柱 | 4 |
鏈接螺絲螺母 | 若干 |
電工工具(電烙鐵、剝線鉗、電工膠帶) | 1 |
機械工具(錐、鉗、卡尺、熱熔槍) | 1 |
藍牙模塊 | 1 |
蜂鳴器 | 1 |
OpenMV | 1 |
(1)Arduino控制板引腳、連線及編程ide
(2)電機驅動板L298N連線及編程函數
(3)傳感器模塊的連線及使用,包括紅外避障、紅外循跡、超聲波避障、數碼管速度顯示、OPENMV視覺捕捉、語音識別模塊、音樂播放、工具
(4)無線通訊及遙控:藍牙模塊、WiFi模塊、紅外遙控、無線手柄、GPS定位。oop
小車實物圖如圖1所示,按照圖示鏈接安裝post
圖1 實物鏈接圖
圖2 L298N電路板圖
圖中,通道A和通道B分別鏈接電機的兩端(兩端無方向性,關乎電機正反轉);電源正負極分別接到圖示主電源正負極(≤5V接到5V輸入,≥5V接到12V);A、B相使能端靠外接線端接入三、五、六、九、十、11等任意兩個接線端帶~的接線端,此處接到D10 D11,靠內一側的兩個引腳懸空或接5V連線端;1,2,3,4輸入端分別接入數字端口D4 D5 D6 D7。
電池盒放入兩節2×3.4V的可充電鋰電池,將正極線(紅色)鏈接到開關一端,另外一端連入麪包板正極列,正極列連入圖2電源正極端(12V或5V)和Arduino的VIN端;GND接到麪包板負極,電源負極端連入麪包板負極的同一列。
圖3 電源鏈接線
(1)超聲波接線端
圖4 超聲波實物圖
VCC接5V,GND接GND,TRIG接2 ECHO接3
(2)藍牙模塊連線
VCC接5V,GND接GND,TX接RX,RX接TX
-接GND,+接5V,S接信號端,此處接D8
四路循跡分別接到循跡主控板上,VCC接主控板5V,GND接主控板GND,OUT1~OUT4分別接到A0-A3
調節方式:將循跡模塊置於軌跡上,令四路模塊依次檢測軌跡與非軌跡部分,並經過調節所在位置的電位器,使得指示燈在檢測到軌跡時滅,未檢測到軌跡時亮便可,而後經過串口通訊端讀取值,替換到程序中。
(5)舵機雲臺
棕色接GND,紅色接5V,橙色接信號線,此處接D9
(6)OPENMV
P4接A4,P5接A5,VCC接5V,GND接GND
(7)蜂鳴器
VCC接5V,GND接GND,I/O接D12
按住藍牙模塊黑色按鈕,而後再接通電源,藍牙以一秒間隔閃滅
將下面程序串燒到Arduino中,打開串口監視器,觀察串口輸出,顯示OK即爲成功設置
斷電,再次上電,當藍牙不斷閃爍時,開始正常工做
void setup() { // put your setup code here, to run once: Serial.begin(38400); } void sendcmd() { Serial.println("AT"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } // Get response: OK delay(1000); // wait for printing Serial.println("AT+NAME=Sonny"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); Serial.println("AT+ADDR?"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); Serial.println("AT+PSWD=2113"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); /*Serial.println("AT+PSWD?"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000);*/ } void loop() { sendcmd(); }
int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA=10; int ENB=11;int i; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 4 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 5 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 6 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 7 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); }
void Run() // 前進 { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW);
digitalWrite(ENA,HIGH);
digitalWrite(ENB,HIGH);
} void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); } void left() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); } void right() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void back() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); }
void loop(
Run(); }
3.紅外遙控程序
#include <IRremote.h> int RECV_PIN = 8; IRrecv irrecv(RECV_PIN); decode_results results;//結構聲明 //============================== int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA=10; int ENB=11; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 9 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 10 (PWM) pinMode(ENA, OUTPUT);////端口模式,輸出 pinMode(ENB, OUTPUT);////端口模式,輸出 Serial.begin(9600); //波特率9600 irrecv.enableIRIn(); // Start the receiver } void back() // 前進 { digitalWrite(Right_motor_go,LOW); // 右電機前進 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); digitalWrite(ENA,HIGH); digitalWrite(ENB,HIGH); } void brake() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_back,LOW); } void right() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); } void left() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void run() //後退 { digitalWrite(Right_motor_go,HIGH); //右輪後退 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); } void read_key() { if(irrecv.decode(&results)){ //若是接收到信息 Serial.print("code:"); Serial.println(results.value,HEX);//results.value爲16進制,unsigned long Serial.print("bits:"); Serial.println(results.bits);//輸出元位數 irrecv.resume(); } } void loop() { read_key(); if(irrecv.decode(&results)){ //若是接收到信息 switch(results.value){ case 0xFF18E7: //前,對應2 run(); break; case 0xFF4AB5: //後,對應8 back(); break; case 0xFF10EF: //左,對應4 left(); break; case 0xFF5AA5: //右,對應6 right(); break; case 0xFF38C7: //中止,對應5 brake(); break; default: break; } irrecv.resume(); } }
#include <IRremote.h>//紅外遙控庫函數 #define BAUD_RATE 9600 int RECV_PIN = 8;//紅外接收端口 IRrecv irrecv(RECV_PIN); decode_results results;//結構聲明 char mode = 'I'; //設置小車運行模式,默認紅外模式 int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA = 10; //PWM輸入A int ENB = 11; //PWM輸入B int speed_default = 100; //0-255之間,小車最低速度爲70,最佳速度爲100 char ch; bool inverse_left=false; bool inverse_right=false; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 7 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 8 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); Serial.begin(BAUD_RATE); //波特率9600 irrecv.enableIRIn(); // Start the receiver delay(1000); // 給OpenMV一個啓動的時間 } void read_key() { if(irrecv.decode(&results)){ //若是接收到信息 Serial.print("code:"); Serial.println(results.value,HEX);//results.value爲16進制,unsigned long Serial.print("bits:"); Serial.println(results.bits);//輸出元位數 irrecv.resume(); } } void back() // 前進 { digitalWrite(Right_motor_go,LOW); // 右電機前進 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void right() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void left() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Run() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void loop() { if(Serial.available()>0){ char ch = Serial.read(); Serial.println(ch); if(ch == '1'){ //前進 Run(); Serial.print("forward"); }else if(ch == '2'){ //後退 back(); Serial.print("backward"); }else if(ch == '3'){ //左轉 left(); Serial.print("turnLeft"); }else if(ch == '4'){ //右轉 right(); Serial.print("turnRight"); }else if(ch=='0'){ //停車 Break(); Serial.print("stop"); } } }
5.藍牙與紅外遙控的切換
#include <IRremote.h>//紅外遙控庫函數 #define BAUD_RATE 9600 int RECV_PIN = 8;//紅外接收端口 IRrecv irrecv(RECV_PIN); decode_results results;//結構聲明 char mode = 'I'; //設置小車運行模式,默認紅外模式 int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA = 10; //PWM輸入A int ENB = 11; //PWM輸入B int speed_default = 100; //0-255之間,小車最低速度爲70,最佳速度爲100 char ch; bool inverse_left=false; bool inverse_right=false; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 7 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 8 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); Serial.begin(BAUD_RATE); //波特率9600 irrecv.enableIRIn(); // Start the receiver delay(1000); // 給OpenMV一個啓動的時間 } void read_key() { if(irrecv.decode(&results)){ //若是接收到信息 Serial.print("code:"); Serial.println(results.value,HEX);//results.value爲16進制,unsigned long Serial.print("bits:"); Serial.println(results.bits);//輸出元位數 irrecv.resume(); } } void back() // 前進 { digitalWrite(Right_motor_go,LOW); // 右電機前進 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void right() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void left() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Run() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void loop() { if(Serial.available()>0){ ch = Serial.read(); Serial.println(ch); if(ch == 'I'){ //紅外模式 mode = 'I'; } if(ch == 'B'){ //藍牙模式 mode = 'B'; } } if(mode == 'I'){ //紅外模式控制代碼 Serial.println("IRremote Mode"); read_key(); if(irrecv.decode(&results)){ //若是接收到信息 Serial.println(results.value); switch(results.value){ case 0xFF18E7: //前,對應2 Run(); break; case 0xFF4AB5: //後,對應8 back(); break; case 0xFF10EF: //左,對應4 left(); break; case 0xFF5AA5: //右,對應6 right(); break; case 0xFF38C7: //中止,對應5 Break(); break; default: break; } irrecv.resume(); } } if(mode == 'B'){ //藍牙模式控制代碼 Serial.println("Blue Mode"); char ch1 = '0'; if(ch == '1'){ //前進 Run(); Serial.print("forward"); }else if(ch == '2'){ //後退 back(); Serial.print("backward"); }else if(ch == '3'){ //左轉 left(); Serial.print("turnLeft"); }else if(ch == '4'){ //右轉 right(); Serial.print("turnRight"); }else if(ch=='0'){ //停車 Break(); Serial.print("stop"); }
}
#define L1 A0 #define L2 A1 #define L3 A2 #define L4 A3 int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA = 10; //PWM輸入A int ENB = 11; //PWM輸入B int speed_default = 100; //0-255之間,小車最低速度爲70,最佳速度爲100 char ch; bool inverse_left=false; bool inverse_right=false; int a; int b; int c; int d; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 7 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 8 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); pinMode(L1,OUTPUT); pinMode(L2,OUTPUT); pinMode(L3,OUTPUT); pinMode(L4,OUTPUT); Serial.begin(9600); //波特率9600 delay(1000); // 給OpenMV一個啓動的時間 } void back() // 前進 { digitalWrite(Right_motor_go,LOW); // 右電機前進 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void right() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void left() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Run() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void loop() { Serial.print("one"); Serial.println(analogRead(L1)); Serial.print("two"); Serial.println(analogRead(L2)); Serial.print("three"); Serial.println(analogRead(L3)); Serial.print("four"); Serial.println(analogRead(L4)); a=analogRead(L1); b=analogRead(L2); c=analogRead(L3); d=analogRead(L4); if(a==1000&&b==1000&&c==1000&&d==1000) { Run(); } if(a==0&&b==0&&c==0&&d==0) { Break(); } if(a<1000&&b<1000&&c>1000&&d>1000) { left(); } if(a>1000&&b>1000&&c<1000&&d<1000) { right(); } }
7.超聲波避障
#include <Servo.h> int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA=10; int ENB=11; Servo myServo; //舵機 int inputPin=3; // 定義超聲波信號接收接口 int outputPin=2; // 定義超聲波信號發出接口 void setup() { // put your setup code here, to run once: //串口初始化 Serial.begin(9600); //舵機引腳初始化 myServo.attach(9); //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 4 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 5 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 6 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 7 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); //超聲波控制引腳初始化 pinMode(inputPin, INPUT); pinMode(outputPin, OUTPUT); } int getDistance() { digitalWrite(outputPin, LOW); // 使發出發出超聲波信號接口低電平2μs delayMicroseconds(2); digitalWrite(outputPin, HIGH); // 使發出發出超聲波信號接口高電平10μs,這裏是至少10μs delayMicroseconds(10); digitalWrite(outputPin, LOW); // 保持發出超聲波信號接口低電平 int distance = pulseIn(inputPin, HIGH); // 讀出脈衝時間 distance= distance/58; // 將脈衝時間轉化爲距離(單位:釐米) Serial.println(distance); //輸出距離值 if (distance >=50) { //若是距離小於50釐米返回數據 return 50; }//若是距離小於50釐米小燈熄滅 else return distance; } void Run() // 前進 { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); } void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_go,LOW); } void left() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); } void right() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } void back() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); } void loop() { // put your main code here, to run repeatedly: avoidance(); } void avoidance() { int pos; int dis[3];//距離 Run(); myServo.write(90); dis[1]=getDistance(); //中間 digitalWrite(ENA,HIGH); digitalWrite(ENB,HIGH); if(dis[1]<30) { Break(); for (pos = 90; pos <= 150; pos += 1) { myServo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position } dis[2]=getDistance(); //左邊 for (pos = 150; pos >= 30; pos -= 1) { myServo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position if(pos==90) dis[1]=getDistance(); //中間 } dis[0]=getDistance(); //右邊 for (pos = 30; pos <= 90; pos += 1) { myServo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position } if(dis[0]<dis[2]) //右邊距離障礙的距離比左邊近 { //左轉 left(); delay(500); } else //右邊距離障礙的距離比左邊遠 { //右轉 right(); delay(500); } } }
#car.py # Arduino 做爲I2C主設備, OpenMV做爲I2C從設備。 # # 請把OpenMV和Arduino按照下面連線: # # OpenMV Cam Master I2C Data (P5) - Arduino Uno Data (A4) # OpenMV Cam Master I2C Clock (P4) - Arduino Uno Clock (A5) # OpenMV Cam Ground - Arduino Ground import pyb, ustruct import ujson from pyb import Pin, Timer text = "Hello World!\n" data = ustruct.pack("<%ds" % len(text), text) # 使用 "ustruct" 來生成須要發送的數據包 # "<" 把數據以小端序放進struct中 # "%ds" 把字符串放進數據流,好比:"13s" 對應的 "Hello World!\n" (13 chars). # 詳見 https://docs.python.org/3/library/struct.html # READ ME!!! # # 請理解,當您的OpenMV攝像頭不是I2C主設備,因此不論是使用中斷回調, # 仍是下方的輪循,均可能會錯過響應發送數據給主機。當這種狀況發生時, # Arduino會得到NAK,而且不得不從OpenMV再次讀數據。請注意, # OpenMV和Arduino都不擅長解決I2C的錯誤。在OpenMV和Arduino中, # 你能夠經過釋放I2C外設,再從新初始化外設,來恢復功能。 # OpenMV上的硬件I2C總線都是2 bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12) bus.deinit() # 徹底關閉設備 bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12) print("Waiting for Arduino...") # 請注意,爲了正常同步工做,OpenMV Cam必須 在Arduino輪詢數據以前運行此腳本。 # 不然,I2C字節幀會變得亂七八糟。因此,保持Arduino在reset狀態, # 直到OpenMV顯示「Waiting for Arduino...」。 def run(left_speed, right_speed): data = str(left_speed)+" "+str(right_speed)+" " try: #print(data) bus.send(ustruct.pack("<h", len(data)), timeout=10000) # 首先發送長度 (16-bits). try: bus.send(data, timeout=10000) # 而後發送數據 print("Sent Data!") # 沒有遇到錯誤時,會顯示 except OSError as err: pass # 不用擔憂遇到錯誤,會跳過 # 請注意,有3個可能的錯誤。 超時錯誤(timeout error), # 通用錯誤(general purpose error)或繁忙錯誤 #(busy error)。 「err.arg[0]」的錯誤代碼分別 # 爲116,5,16。 except OSError as err: pass # 不用擔憂遇到錯誤,會跳過 # 請注意,有3個可能的錯誤。 超時錯誤(timeout error), # 通用錯誤(general purpose error)或繁忙錯誤 #(busy error)。 「err.arg[0]」的錯誤代碼分別 # 爲116,5,16。
#pid.py from pyb import millis from math import pi, isnan class PID: _kp = _ki = _kd = _integrator = _imax = 0 _last_error = _last_derivative = _last_t = 0 _RC = 1/(2 * pi * 20) def __init__(self, p=0, i=0, d=0, imax=0): self._kp = float(p) self._ki = float(i) self._kd = float(d) self._imax = abs(imax) self._last_derivative = float('nan') def get_pid(self, error, scaler): tnow = millis() dt = tnow - self._last_t output = 0 if self._last_t == 0 or dt > 1000: dt = 0 self.reset_I() self._last_t = tnow delta_time = float(dt) / float(1000) output += error * self._kp if abs(self._kd) > 0 and dt > 0: if isnan(self._last_derivative): derivative = 0 self._last_derivative = 0 else: derivative = (error - self._last_error) / delta_time derivative = self._last_derivative + \ ((delta_time / (self._RC + delta_time)) * \ (derivative - self._last_derivative)) self._last_error = error self._last_derivative = derivative output += self._kd * derivative output *= scaler if abs(self._ki) > 0 and dt > 0: self._integrator += (error * self._ki) * scaler * delta_time if self._integrator < -self._imax: self._integrator = -self._imax elif self._integrator > self._imax: self._integrator = self._imax output += self._integrator return output def reset_I(self): self._integrator = 0 self._last_derivative = float('nan')
#main.py # Blob Detection Example # # This example shows off how to use the find_blobs function to find color # blobs in the image. This example in particular looks for dark green objects. import sensor, image, time import car from pid import PID # You may need to tweak the above settings for tracking green things... # Select an area in the Framebuffer to copy the color settings. sensor.reset() # Initialize the camera sensor. sensor.set_pixformat(sensor.RGB565) # use RGB565. sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed. sensor.skip_frames(10) # Let new settings take affect. sensor.set_auto_whitebal(False) # turn this off. clock = time.clock() # Tracks FPS. # For color tracking to work really well you should ideally be in a very, very, # very, controlled enviroment where the lighting is constant... green_threshold = (42, 80, 28, 127, -22, 55) # 顏色閾值,不一樣物體須要修改 size_threshold = 2000 #小球距離 x_pid = PID(p=0.1, i=0.2, imax=30) # 方向參數p h_pid = PID(p=0.01, i=0.1, imax=100) # 速度參數p def find_max(blobs): #找到視野中最大的色塊,即最大的小球 max_size=0 for blob in blobs: if blob[2]*blob[3] > max_size: max_blob=blob max_size = blob[2]*blob[3] return max_blob while(True): clock.tick() # Track elapsed milliseconds between snapshots(). img = sensor.snapshot() # Take a picture and return the image. blobs = img.find_blobs([green_threshold]) if blobs: max_blob = find_max(blobs) x_error = max_blob[5]-img.width()/2 #色塊的外框的中心x座標blob[5] h_error = max_blob[2]*max_blob[3]-size_threshold #色塊的外框的寬度blob[2],色塊的外框的高度blob[3] print("x error: ", x_error) #打印 x 軸偏差 用於轉彎 print("h error: ", h_error) #打印 距離偏差 用於速度 ''' for b in blobs: # Draw a rect around the blob. img.draw_rectangle(b[0:4]) # rect img.draw_cross(b[5], b[6]) # cx, cy ''' img.draw_rectangle(max_blob[0:4]) # rect img.draw_cross(max_blob[5], max_blob[6]) # cx, cy x_output=x_pid.get_pid(x_error,1) h_output=h_pid.get_pid(h_error,1) #h_error調整後的值 print("x_output",x_output) print("h_output",h_output) car.run(-h_output-x_output,-h_output+x_output) print(-h_output-x_output,-h_output+x_output) else: car.run(0,0)
#include <IRremote.h> #include <Wire.h> #define BAUD_RATE 9600 #define CHAR_BUF 128 float left_speed = 1.1; float right_speed = 1.1; char buff[CHAR_BUF] = {0}; int RECV_PIN = 8;//紅外接收端口 IRrecv irrecv(RECV_PIN); decode_results results;//結構聲明 char mode = 'I'; //設置小車運行模式,默認紅外模式 int Left_motor_back=4; //左電機後退(IN1) int Left_motor_go=5; //左電機前進(IN2) int Right_motor_go=6; // 右電機前進(IN3) int Right_motor_back=7; // 右電機後退(IN4) int ENA = 10; //PWM輸入A int ENB = 11; //PWM輸入B int speed_default = 100; //0-255之間,小車最低速度爲70,最佳速度爲100 char ch; bool inverse_left=false; bool inverse_right=false; void setup() { //初始化電機驅動IO爲輸出方式 pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM) pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM) pinMode(Right_motor_go,OUTPUT);// PIN 7 (PWM) pinMode(Right_motor_back,OUTPUT);// PIN 8 (PWM) pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); pinMode(13, OUTPUT);////端口模式,輸出 Serial.begin(BAUD_RATE); //波特率9600 irrecv.enableIRIn(); // Start the receiver Wire.begin(); delay(1000); // 給OpenMV一個啓動的時間 } void back() // 前進 { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH); // 左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Break() //剎車,停車 { digitalWrite(Right_motor_go,LOW); digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void right() //左轉(左輪不動,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪不動 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_left() //左轉(左輪後退,右輪前進) { digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void left() //右轉(右輪不動,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機不動 digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void spin_right() //右轉(右輪後退,左輪前進) { digitalWrite(Right_motor_go,LOW); //右電機後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } void Run() //後退 { digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); analogWrite(ENA,speed_default); analogWrite(ENB,speed_default); } //============================================================================= //讀取各個按鍵須要用到這段代碼 //============================================================================= void read_key() { if(irrecv.decode(&results)){ //若是接收到信息 Serial.print("code:"); Serial.println(results.value,HEX);//results.value爲16進制,unsigned long Serial.print("bits:"); Serial.println(results.bits);//輸出元位數 irrecv.resume(); } } //============================================================================= //處理字符串buff //============================================================================ void getCode(){ //buff通過傳輸,尾部有干擾,故用兩個空格分割 String temp1,temp2; String string = String(buff); int postion = string.indexOf(" "); temp1 = string.substring(0,postion); string = string.substring(postion+1,string.length()); postion = postion = string.indexOf(" "); temp2 = string.substring(0,postion); left_speed = temp1.toFloat(); right_speed = temp2.toFloat(); } //============================================================================= //PWM模式的小車運動 //============================================================================ void openmvrun(){ if(inverse_left) left_speed=-left_speed; if(inverse_right) right_speed=-right_speed; int l_speed = abs(left_speed); int r_speed = abs(right_speed); if(left_speed<0){ digitalWrite(Left_motor_go,LOW); //左輪後退 digitalWrite(Left_motor_back,HIGH); }else{ digitalWrite(Left_motor_go,HIGH);//左電機前進 digitalWrite(Left_motor_back,LOW); } analogWrite(ENA,l_speed); if(right_speed<0){ digitalWrite(Right_motor_go,LOW); //右輪後退 digitalWrite(Right_motor_back,HIGH); }else{ digitalWrite(Right_motor_go,HIGH); // 右電機前進 digitalWrite(Right_motor_back,LOW); } analogWrite(ENB,r_speed); Serial.print(l_speed); Serial.print(" "); Serial.print(r_speed); } void loop() { if(Serial.available()>0){ ch = Serial.read(); if(ch == 'I'){ //紅外模式 mode = 'I'; }else if(ch == 'B'){ //藍牙模式 mode = 'B'; }else if(ch == 'O'){ //openmv模式 mode = 'O'; } } if(mode == 'I'){ //紅外模式控制代碼 //Serial.println("紅外模式"); read_key(); if(irrecv.decode(&results)){ //若是接收到信息 Serial.println(results.value); switch(results.value){ case 0xFF18E7: //前,對應2 Run(); break; case 0xFF4AB5: //後,對應8 back(); break; case 0xFF10EF: //左,對應4 left(); break; case 0xFF5AA5: //右,對應6 right(); break; case 0xFF38C7: //中止,對應5 Break(); break; default: break; } irrecv.resume(); } } if(mode == 'B'){ //藍牙模式控制代碼 //Serial.println("藍牙模式"); char ch1 = '0'; if(ch == '1'){ //前進 Run(); Serial.print("前進"); }else if(ch == '2'){ //後退 back(); Serial.print("後退"); }else if(ch == '3'){ //左轉 left(); Serial.print("左轉"); }else if(ch == '4'){ //右轉 right(); Serial.print("右轉"); }else if(ch=='0'){ //停車 Break(); Serial.print("停車"); }else if(ch=='5'){ speed_default +=5; ch = ch1; }else if(ch=='6'){ speed_default -=5; ch = ch1; } ch1 = ch; Serial.println(speed_default); } if(mode == 'O'){ //openmv模式控制代碼 //Serial.println("openmv模式"); int32_t temp = 0; Wire.requestFrom(0x12, 2); if (Wire.available() == 2) { // got length? temp = Wire.read() | (Wire.read() << 8); delay(1); // Give some setup time... Wire.requestFrom(0x12, temp); if (Wire.available() == temp) { // got full message? temp = 0; while (Wire.available()) buff[temp++] = Wire.read(); } else { while (Wire.available()) Wire.read(); // Toss garbage bytes. } } else { while (Wire.available()) Wire.read(); // Toss garbage bytes. } //Serial.println(buff); getCode(); //Serial.println(left_speed+" "+"right_speed="+right_speed); //Serial.print(left_speed); //Serial.print(" "); //Serial.print(right_speed); openmvrun(); delay(1); // Don't loop to quickly. } }
#define Do 495 #define Re 556 #define Mi 624 #define Fa 661 #define Sol 742 #define La 833 #define Si 935 #define hDo 990 #define hRe 1112 #define hMi 1178 #define hFa 1322 #define hSol 1484 #define hLa 1665 #define hSi 1869 #define dDo 248 #define dRe 278 #define dMi 294 #define dFa 330 #define dSol 371 #define dLa 416 #define dSi 467 int pin=12; //自行選擇做爲輸出的接口 int scale[]={Do,Re,Mi,Fa,Sol,La,Si,dDo,dRe,dMi,dFa,dSol,dLa,dSi,hDo,hRe,hMi,hFa,hSol,hLa,hSi}; int pu[100]={1,3,5,6,5,5,5,5,1,1,3,3,100,100,1,3,4,6,5,5,5,5,4,4,3,3,100,100,1,3,5,6,5,5,5,5,4,4,3,3,2,2,1,1,100,1,1,1,1,2,3,2,2,100,100}; void setup(){ pinMode(pin,OUTPUT); } void loop(){ for(int i=0;i<61;i++){ if(pu[i]!=100) { tone(pin,scale[pu[i]-1]); } else noTone(pin); delay(200); noTone(pin); delay(100); } delay(5000); }