(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); }