美文网首页
技术专栏 | 基于Arduino开发的智能小车

技术专栏 | 基于Arduino开发的智能小车

作者: 挽风_Sonny | 来源:发表于2020-04-06 16:17 被阅读0次

    一、概述

    1. 设计内容

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

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

    (3)循迹、避障

    (4)视觉

    (5)装饰:音乐播放器

    2.材料清单

    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

    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 //红外遥控库函数

    #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 //红外遥控库函数

    #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

    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]

    {

    //左转

    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("

    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

    #include

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

    }

    相关文章

      网友评论

          本文标题:技术专栏 | 基于Arduino开发的智能小车

          本文链接:https://www.haomeiwen.com/subject/sfybphtx.html