本系列教程讲解零知小车套件以零知迷你板为主控,使用零知开源平台进行智能小车开发。
使用的硬件:零知智能小车套件-零知智能小车高级版(零知mini主控)
实现的功能:红外循迹、超声波避障、直线运行、手机蓝牙控制、灭火等基本功能。
扩展:可以在小车上加入其它传感器模块进行扩展,比如加入摄像头模块进行监控、加入更多超声波模块实现自动跟随...
高级版系列教程将使用多文件编程的方式来编写程序,教程主要包含以下几个部分:
零知两轮小车高级版(零知mini主控)系列教程-小车组装(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-程序控制电机开跑(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-加入蓝牙实现手机控制(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-红外循迹走S弯(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-超声波自动避障(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-灭火小车(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-使用PID走直线(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-魔术手(点击跳转)
零知两轮小车高级版(零知mini主控)系列教程-贴边行驶(点击跳转)
一、工具原料
(1)组装好的智能小车
二、电机驱动说明
这里使用电机驱动为DRV8833型号,我们需要根据它的逻辑表来驱动电机:
其完整的datasheet文件:http://www.ti.com/lit/ds/symlink/drv8833.pdf
三、程序代码
高级版教程将使用多文件编程的方式来编写代码,将电机的控制以及其它模块封装成多个类,部分内容如下:
/*
* @文件: \motor.cpp
* @作者:零知实验室
* -^^- 零知开源,让电子制作变得更简单! -^^-
* @时间: 2019-12-05 13:53:55
* @说明:
*/
#include "motor.h"
LZSmartCarMotor::LZSmartCarMotor(bool is2WD)
{
if (is2WD)
{
_wheelNum = 2;
pinMode(MotorIN1, OUTPUT);
pinMode(MotorIN2, OUTPUT);
pinMode(MotorIN3, OUTPUT);
pinMode(MotorIN4, OUTPUT);
}
else
{
_wheelNum = 4;
pinMode(MotorIN1, OUTPUT);
pinMode(MotorIN2, OUTPUT);
pinMode(MotorIN3, OUTPUT);
pinMode(MotorIN4, OUTPUT);
pinMode(MotorIN5, OUTPUT);
pinMode(MotorIN6, OUTPUT);
pinMode(MotorIN7, OUTPUT);
pinMode(MotorIN8, OUTPUT);
}
}
void LZSmartCarMotor::speedGo(byte number, int speed, bool reverse)
{
if (speed < 0)
{
speed = 0;
}
if (speed > 255)
{
speed = 255;
}
speed = 255 - speed;
if(number > _wheelNum){
Serial.println("轮子个数是否正确?");
return;
}
if (number == 1)
{
if (reverse)
{
analogWrite(MotorIN1, speed);
analogWrite(MotorIN2, 255);
}
else
{
analogWrite(MotorIN1, 255);
analogWrite(MotorIN2, speed);
}
}
if (number == 2)
{
if (reverse)
{
analogWrite(MotorIN3, speed);
analogWrite(MotorIN4, 255);
}
else
{
analogWrite(MotorIN3, 255);
analogWrite(MotorIN4, speed);
}
}
if (number == 3)
{
if (reverse)
{
analogWrite(MotorIN5, 255);
analogWrite(MotorIN6, speed);
}
else
{
analogWrite(MotorIN5, speed);
analogWrite(MotorIN6, 255);
}
}
if (number == 4)
{
if (reverse)
{
analogWrite(MotorIN7, speed);
analogWrite(MotorIN8, 255);
}
else
{
analogWrite(MotorIN7, 255);
analogWrite(MotorIN8, speed);
}
}
}
void LZSmartCarMotor::stop()
{
analogWrite(MotorIN1, 255);
analogWrite(MotorIN2, 255);
analogWrite(MotorIN3, 255);
analogWrite(MotorIN4, 255);
analogWrite(MotorIN5, 255);
analogWrite(MotorIN6, 255);
analogWrite(MotorIN7, 255);
analogWrite(MotorIN8, 255);
}
void LZSmartCarMotor::goWithDirec(carDirec cmd)
{
switch(cmd){
case carForward:
speedGo(1,MotorSpeedNormal);
speedGo(2,MotorSpeedNormal);
speedGo(3,MotorSpeedNormal);
speedGo(4,MotorSpeedNormal);
break;
case carForwardSlow:
speedGo(1,MotorSpeedSlow);
speedGo(2,MotorSpeedSlow);
speedGo(3,MotorSpeedSlow);
speedGo(4,MotorSpeedSlow);
break;
case carBack:
speedGo(1,MotorSpeedNormal,true);
speedGo(2,MotorSpeedNormal,true);
speedGo(3,MotorSpeedNormal,true);
speedGo(4,MotorSpeedNormal,true);
break;
case carLeft:
speedGo(1,MotorSpeedRotate);
speedGo(2,MotorSpeedFast);
speedGo(3,MotorSpeedRotate);
speedGo(4,MotorSpeedFast);
break;
case carRight:
speedGo(1,MotorSpeedFast);
speedGo(2,MotorSpeedRotate);
speedGo(3,MotorSpeedFast);
speedGo(4,MotorSpeedRotate);
break;
case carForLeft:
speedGo(1,MotorSpeedRotate);
speedGo(2,MotorSpeedNormal);
speedGo(3,MotorSpeedRotate);
speedGo(4,MotorSpeedNormal);
break;
case carForRight:
speedGo(1,MotorSpeedNormal);
speedGo(2,MotorSpeedRotate);
speedGo(3,MotorSpeedNormal);
speedGo(4,MotorSpeedRotate);
break;
case carLeftFast:
speedGo(1,MotorSpeedTrace);
speedGo(2,MotorSpeedRoFast);
speedGo(3,MotorSpeedTrace);
speedGo(4,MotorSpeedRoFast);
break;
case carLeftSlow:
speedGo(1,MotorSpeedTrace);
speedGo(2,MotorSpeedRoSlow);
speedGo(3,MotorSpeedTrace);
speedGo(4,MotorSpeedRoSlow);
break;
case carRightFast:
speedGo(1,MotorSpeedRoFast);
speedGo(2,MotorSpeedTrace);
speedGo(3,MotorSpeedRoFast);
speedGo(4,MotorSpeedTrace);
break;
case carRightSlow:
speedGo(1,MotorSpeedRoSlow);
speedGo(2,MotorSpeedTrace);
speedGo(3,MotorSpeedRoSlow);
speedGo(4,MotorSpeedTrace);
break;
case carStop:
stop();
break;
default:
stop();
break;
}
}
LZSmartCarMotor::~LZSmartCarMotor()
{
}
完整工程可在下面下载
主程序代码如下:
/**********************************************************
* 文件: .ino by 零知实验室([url=http://www.lingzhilab.com]www.lingzhilab.com[/url])
* -^^- 零知开源,让电子制作变得更简单! -^^-
* 时间: 2019/12/11 10:33
* 说明:
************************************************************/
#include "pinsdefine.h"
#include "motor.h"
LZSmartCarMotor myMotor;
// 复位或上电后运行一次:
void setup() {
//在这里加入初始化相关代码,只运行一次:
Serial.begin(9600);
Serial.println("开车啦...");
myMotor.stop();
}
//一直循环执行:
void loop() {
// 在这里加入主要程序代码,重复执行:
if(Serial.available()){
char cmd = Serial.read();
Serial.print("cmd:");Serial.write(cmd);Serial.println();
if(cmd == '1'){
myMotor.goWithDirec(carForward);
}
else if(cmd == '2'){
myMotor.goWithDirec(carForLeft);
}
else if(cmd == '3'){
myMotor.goWithDirec(carForRight);
}
else if(cmd == '4'){
myMotor.goWithDirec(carBack);
}
else{
myMotor.goWithDirec(carStop);
}
}
}
完整工程: lzsmartcar_v5.zip
将以上代码验证上传至小车,然后我们在串口调试窗口发送不同的命令,看小车是否按照我们预期的动作运转,如果有冲突是很正常的,因为有时候安装电机的方向不一样,这时候我们就可以根据实际情况修改上述代码,使之和我们安装好的小车运行情况一致。