零知两轮小车高级版(零知mini主控)教程-贴边行驶

本系列教程讲解零知小车套件以零知迷你板为主控,使用零知开源平台进行智能小车开发。
使用的硬件:零知智能小车套件-零知智能小车高级版(零知mini主控)

实现的功能:红外循迹、超声波避障、直线运行、手机蓝牙控制、灭火等基本功能。

扩展:可以在小车上加入其它传感器模块进行扩展,比如加入摄像头模块进行监控、加入更多超声波模块实现自动跟随...

高级版系列教程将使用多文件编程的方式来编写程序,教程主要包含以下几个部分:

零知两轮小车高级版(零知mini主控)系列教程-小车组装(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-程序控制电机开跑(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-加入蓝牙实现手机控制(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-红外循迹走S弯(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-超声波自动避障(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-灭火小车(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-使用PID走直线(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-魔术手(点击跳转)

零知两轮小车高级版(零知mini主控)系列教程-贴边行驶(点击跳转)

一、工具原料
(1)组装好的智能小车


二、程序代码
高级版教程将使用多文件编程的方式来编写代码,包含所有功能的完整工程可在下面下载。贴边行驶我们分别使用红外避障模块和超声波来完成。其中使用红外避障模块的主程序代码如下所示:


				
/**********************************************************
*    文件: .ino      by 零知实验室([url=http://www.lingzhilab.com]www.lingzhilab.com[/url])
*    -^^- 零知开源,让电子制作变得更简单! -^^-
*    时间: 2019/08/14 11:43
*    说明:
************************************************************/
  
#include "pinsdefine.h"
#include "motor.h"
#include <PID_v1.h>
#include "caravoidance.h"
 
CarAvoidance carAvoidance;
 
LZSmartCarMotor myMotor;
 
void nearWall()
{
        bool leftIR, rightIR;
        carAvoidance.getIRAvoidData(&leftIR, &rightIR);
        Serial.print("leftIR: ");Serial.print(leftIR);
        Serial.print("   rightIR: ");Serial.println(rightIR);
        if (leftIR == 0 && rightIR == 0)
        {
                myMotor.motorRun(80,80);
                Serial.println("前进");
        }
        else if (leftIR == 0 && rightIR == 1)
        {
                myMotor.motorRun(0,70);
                Serial.println("左转");
        }
        else if (leftIR == 1 && rightIR == 0)
        {
                myMotor.motorRun(70,0);
                Serial.println("右转");
        }
        else{
                myMotor.stop();
                Serial.println("停车");
        }
}
 
void setup()
{
        Serial.begin(9600);
        Serial.println("开车啦...");
         
        myMotor.stop();
}
 
void loop()
{
        nearWall();
}
				

包含全部功能的完整工程:  lzsmartcar_v5.zip 

下载上面的附件,在程序中选择贴边行驶的功能,验证上传至零知智能小车的主控板上就完成了。

使用超声波模块完成贴边行驶就要用到PID算法了,根据测量的距离计算出两边轮子的输出,主程序代码如下所示:


				
/**********************************************************
*    文件: .ino      by 零知实验室([url=http://www.lingzhilab.com]www.lingzhilab.com[/url])
*    -^^- 零知开源,让电子制作变得更简单! -^^-
*    时间: 2019/08/14 11:43
*    说明:
************************************************************/
  
#include "pinsdefine.h"
#include "motor.h"
#include <PID_v1.h>
#include "caravoidance.h"
#include <PID_v1.h>
 
CarAvoidance carAvoidance;
 
LZSmartCarMotor myMotor;
 
// PID参数根据小车实际行驶的情况调整至最佳
double Kp =4, Ki = 0.02, Kd = 0.2;
double Input, Output, Setpoint = 17;  // 设置想要贴近的距离
 
PID nearpid(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
 
int leftPwm, rightPwm, initialPwm = 70;
 
 
void nearWall()
{
    //检测车身左右两侧的距离,贴距离近的一边行驶
    carAvoidance.servoRun(90, 0, 0);
    int leftDis = carAvoidance.getDistance();
    carAvoidance.servoRun(0, 180, 10);
    int rightDis = carAvoidance.getDistance();
    if(leftDis <= rightDis)
    {
        carAvoidance.servoRun(180, 30, 10);  // 将超声波移动到左前方30°
    }else
        carAvoidance.servoRun(180, 150, 10);  // 将超声波移动到右前方30°
     
    //开始贴边行驶
    while(1){
        int interval = carAvoidance.getDistance();  // 检测距离
        Serial.println("距离:");Serial.println(interval);
        if(interval > Setpoint*2)
            interval = Setpoint*2;
        Input = (double)interval;
        nearpid.Compute();
        if(leftDis <= rightDis){
            leftPwm = initialPwm - Output;
            rightPwm = initialPwm + Output;
        }else{
            leftPwm = initialPwm + Output;
            rightPwm = initialPwm - Output; 
        }
         
        Serial.print("leftPwm:");Serial.print(leftPwm);
        Serial.print("   rightPwm:");Serial.println(rightPwm);
         
        myMotor.motorRun(leftPwm, rightPwm);
    }
}
 
void setup()
{
    Serial.begin(9600);
    Serial.println("开车啦...");
     
    nearpid.SetMode(AUTOMATIC);
    nearpid.SetOutputLimits(initialPwm - 255,255 - initialPwm);
     
    myMotor.stop();
}
 
void loop()
{
    nearWall();
}