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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

二、程序代码

高级版教程将使用多文件编程的方式来编写代码,完整工程可在下面下载,循迹我们将分为不含PID算法和含PID算法的循迹,不含PID算法的主程序代码如下所示:


				
/**********************************************************
*    文件: lzsmartcar_track.ino      by 零知实验室([url=http://www.lingzhilab.com]www.lingzhilab.com[/url])
*    -^^- 零知开源,让电子制作变得更简单! -^^-
*    时间: 2019/12/11 14:56
*    说明: 
************************************************************/
#include "pinsdefine.h"
#include "motor.h"
#include "cartrack.h"
 
//两轮车
LZSmartCarMotor myMotor;
 
//红外循迹,5路
CarTracking carTrack(5);
 
//#define BLACK 0
//#define WHITE 1
 
void doTrackLine()
{
        byte buff[5];
        carTrack.getLineData(buff);
        // 设置底的颜色和线的颜色,只有黑白,不设置默认白底黑线
        //carTrack.setGround(BLACK);
        //carTrack.setLine(WHITE);
 
        int decide = carTrack.getDecide(buff);
 
        switch (decide)
                {
                case biggerLeft:
                        myMotor.goWithDirec(carLeft);
                        break;
                case smallLeft:
                        myMotor.goWithDirec(carForLeft);
                        break;
                case straight:
                        myMotor.goWithDirec(carForwardSlow);
                        break;
                case smallRight:
                        myMotor.goWithDirec(carForRight);
                        break;
                case biggerRight:
                        myMotor.goWithDirec(carRight);
                        break;
                case ninetyLeft:
                        myMotor.goWithDirec(carLeft);
                        delay(160);
                        break;
                case ninetyRight:
                        myMotor.goWithDirec(carRight);
                        delay(160);
                        break;
                default:
                        break;
                }
}
 
// 复位或上电后运行一次:
void setup() {
    //在这里加入初始化相关代码,只运行一次:
        Serial.begin(9600);
        Serial.println("开车啦...");
        myMotor.stop();
 
}
 
//一直循环执行:
void loop() {
    // 在这里加入主要程序代码,重复执行:
        doTrackLine();
 
}
				

包含了所有功能的完整工程:  lzsmartcar_v5.zip     默认白底黑线。
若是黑底白线,请在程序代码中修改如下部分:

// 设置底的颜色和线的颜色,只有黑白,不设置默认白底黑线
carTrack.setGround(BLACK);
carTrack.setLine(WHITE);
				

验证上传以上代码至智能小车上的mini板上,循迹小车就完成了。
这里注意的是,循迹模块的安装高度需要根据实际进行调整,否则无法识别到白色和黑色的区域导致无法循迹。

含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 "cartrack.h"
 
//红外循迹,5路
CarTracking carTrack(5);
 
LZSmartCarMotor myMotor;
//PID参数根据实际情况调整至最佳
//double Kp = 6.5, Ki = 1, Kd = 0;
 
double Kp = 6.5, Ki = 0.05, Kd = 0.5;
double Input, Output, Setpoint = 0;
 
static int speed = 90;
 
PID trackpid(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
 
 
void doTrackLine()
{
        byte buff[5];
        carTrack.getLineData(buff);
        // 设置底的颜色和线的颜色,只有黑白,默认白底黑线
//        carTrack.setGround(BLACK);
//        carTrack.setLine(WHITE);
 
        int decide = carTrack.getDecide(buff);
//        Serial.print("decide:");Serial.println(decide);
 
        while(decide == ninetyLeft){
                myMotor.motorRun(0,80);
                carTrack.getLineData(buff);
                if(carTrack.getDecide(buff) == smallLeft){
                        return;
                }
        }
        while(decide == ninetyRight){
                myMotor.motorRun(80,0);
                carTrack.getLineData(buff);
                if(carTrack.getDecide(buff) == smallRight){
                        return;
                }
        }
        Input = decide;
        trackpid.Compute();
         
        int leftspeed = speed - Output;
        int rightspeed = speed + Output;
        Serial.print("leftspeed:");
        Serial.print(leftspeed);
        Serial.print("  rightspeed:");
        Serial.println(rightspeed);
         
        myMotor.motorRun(leftspeed, rightspeed);
}
 
void setup()
{
        Serial.begin(9600);
        Serial.println("开车啦...");
         
        trackpid.SetMode(AUTOMATIC);
        trackpid.SetOutputLimits(speed - 255, 255 - speed);
         
        myMotor.stop();
}
 
void loop()
{
        doTrackLine();
}