基于Arduino开发的智能小车

Deadly 提交于 2020-05-02 16:06:13

一、概述

1. 设计内容

(1)智能小车自动运行(前后走,左右转)

(2)蓝牙控制、遥控器控制、无线手柄控制

(3)循迹、避障

(4)视觉

(5)装饰:音乐播放器

2.材料清单

材料

数量

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

 

3.掌握的内容

  (1)Arduino控制板引脚、连线及编程

  (2)电机驱动板L298N连线及编程

  (3)传感器模块的连线及使用,包括红外避障、红外循迹、超声波避障、数码管速度显示、OPENMV视觉捕捉、语音识别模块、音乐播放、

  (4)无线通信及遥控:蓝牙模块、WiFi模块、红外遥控、无线手柄、GPS定位。

二、小车组装

   小车实物图如图1所示,按照图示连接安装

 

图1 实物连接图

三、控制元件搭建

1.电机驱动板L298N连线

图2 L298N电路板图

 

  图中,通道A和通道B分别连接电机的两端(两端无方向性,关乎电机正反转);电源正负极分别接到图示主电源正负极(≤5V接到5V输入,≥5V接到12V);A、B相使能端靠外接线端接入3、5、6、9、10、11等任意两个接线端带~的接线端,此处接到D10 D11,靠内一侧的两个引脚悬空或接5V连线端;1,2,3,4输入端分别接入数字端口D4 D5 D6 D7。

2.电源连线

  电池盒放入两节2×3.4V的可充电锂电池,将正极线(红色)连接到开关一端,另一端连入面包板正极列,正极列连入图2电源正极端(12V或5V)和Arduino的VIN端;GND接到面包板负极,电源负极端连入面包板负极的同一列。

 
图3 电源连接线

3.传感器件连线

(1)超声波接线端

图4 超声波实物图

  VCC接5V,GND接GND,TRIG接2 ECHO接3

(2)蓝牙模块连线

 

  VCC接5V,GND接GND,TX接RX,RX接TX

(3)红外遥控连线

 

 

  -接GND,+接5V,S接信号端,此处接D8

(4)红外循迹模块

 

  四路循迹分别接到循迹主控板上,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

四、编程实现

 1. 蓝牙AT模式设置

  按住蓝牙模块黑色按钮,然后再接通电源,蓝牙以一秒间隔闪灭

  将下面程序串烧到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();
}

2. 电机PWM驱动程序

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

 4.蓝牙控制

#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");
      }
}

6.红外循迹

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

 8 OpenMV模块程序

(1)OpenMv IDE代码:

#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)

(2)Arduino程序

#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.
  }
}

 9.音乐播放——歌曲《小宇》

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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!