本篇主要介绍电机驱动模块及小车控制逻辑
一、硬件介绍:
1.1 最小系统
直接使用是最小系统板模块,省去焊接的麻烦,晶振为11.0592M,芯片使用的是增强型8051单片机STC12C5A60S2,带有2路硬件PWM,方便控制电机调速,避免定时器输出PWM占用系统时间。
1.2 电源
电源采用9v 650mAh的USB充电电池,充满电能连续使用1-2h。
1.3 底盘及电机
底盘主要是固定各个部件,可自己画图然后3D打印出来,为了方便我直接使用智能小车底盘套件(2轮),配2个直流减速电机、轮子等若干安装孔,方便之后器件的安装固定。
1.4 电机驱动模块
由于只有2个轮子,因而只用一个驱动模块即可,我是用的是L298N电机驱动模块红色版。
二、接线介绍
首先是电源部分,9V电源给L298N电机驱动模块(VCC)供电,L298N电机驱动模块输出5V(+5V)给单片机供电,9V电源地和单片机(GND)要连在一起保证共地;其次是电机的四根线(OUT1-4),两个直流电机顺序无所谓,之后也可以在软件中调整左右方向;最后是电机控制的六根线,ENA和ENB(控制电机输入电压)要连接单片机(P1.3 P1.4)端口,两端口为MCU硬件PWM输出端,其余四根线(控制电机转动方向)接到四个端口即可。
三、软件编写
电机控制模块分为Motor_Control.c和Motor_Control.h。
小车姿态分为前进、后退、左转、右转、顺时针转动、逆时针转动、停止。可通过参数设定进行PWM调速,代码如下。
3.1 IO口定义
//L298N模块引脚定义
sbit PIN_IN1=P1^0;
sbit PIN_IN2=P1^1;
sbit PIN_IN3=P1^2;
sbit PIN_ENA=P1^3;
sbit PIN_ENB=P1^4;
sbit PIN_IN4=P1^5;
3.2 电机控制函数声明
void Run(u8 L,u8 R);
void Back(u8 L,u8 R);
void Left(u8 L,u8 R,u8 L_GorB,u8 R_GorB);
void Right(u8 L,u8 R,u8 L_GorB,u8 R_GorB);
void Rotate_Clockwise(u8 L,u8 R);
void Rotate_Counterclockwise(u8 L,u8 R);
void Stop(void);
void Pwm_Init(void);
void Pwm_Set(u8 x,u8 y);
3.3 电机控制函数定义
void Left_Motor_Go(void) //左电机 前进
{
PIN_IN3 = 0;PIN_IN4 = 1;
}
void Left_Motor_Back(void) //左电机 后退
{
PIN_IN3 = 1;PIN_IN4 = 0;
}
void Left_Motor_Stop(void) //左电机 停止
{
PIN_IN3 = 1;PIN_IN4 = 1;
}
void Right_Motor_Go(void) //右电机 前进
{
PIN_IN1 = 0;PIN_IN2 = 1;
}
void Right_Motor_Back(void) //右电机 后退
{
PIN_IN1 = 1;PIN_IN2 = 0;
}
void Right_Motor_Stop(void) //右电机 停止
{
PIN_IN1 = 1;PIN_IN2 = 1;
}
/**
* @brief 小车 前进
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快
* @retval 无
**/
void Run(u8 L,u8 R)
{
Pwm_Set(L,R);
Left_Motor_Go();
Left_Motor_Stop();
}
/**
* @brief 小车 前进
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快。
* @retval 无
**/
void Back(u8 L,u8 R)
{
Pwm_Set(L,R);
Left_Motor_Back();
Right_Motor_Back();
}
void Stop(void) //小车 停止
{
Pwm_Set(100,100);
Left_Motor_Stop();
Right_Motor_Stop();
}
/**
* @brief 小车 左转
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快。
L_GorB:电机转向(G:前进 / B:后退 / S:停止)
L_GorB:电机转向(G:前进 / B:后退 / S:停止)
* @retval 无
**/
void Left(u8 L,u8 R,u8 L_GorB,u8 R_GorB)
{
if(L > R)
{
Pwm_Set(L,R);
if (L_GorB == 'G') Left_Motor_Go();
else if (L_GorB == 'B') Left_Motor_Back();
else if (L_GorB == 'S') Left_Motor_Stop();
else Left_Motor_Stop();
if (R_GorB == 'G') Right_Motor_Go();
else if (R_GorB == 'B') Right_Motor_Back();
else if (R_GorB == 'S') Right_Motor_Stop();
else Right_Motor_Stop();
}
else
Stop();
}
/**
* @brief 小车 右转
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快。
L_GorB:电机转向(G:前进 / B:后退 / S:停止)
L_GorB:电机转向(G:前进 / B:后退 / S:停止)
* @retval 无
**/
void Right(u8 L,u8 R,u8 L_GorB,u8 R_GorB)
{
if(L < R)
{
Pwm_Set(L,R);
if (L_GorB == 'G') Left_Motor_Go();
else if(L_GorB == 'B') Left_Motor_Back();
else if(L_GorB == 'S') Left_Motor_Stop();
else Left_Motor_Stop();
if (R_GorB == 'G') Right_Motor_Go();
else if(R_GorB == 'B') Right_Motor_Back();
else if(R_GorB == 'S') Right_Motor_Stop();
else Right_Motor_Stop();
}
else
Stop();
}
/**
* @brief 小车 顺时针转动
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快。
* @retval 无
**/
void Rotate_Clockwise(u8 L,u8 R)
{
Pwm_Set(L,R);
Left_Motor_Go();
Right_Motor_Back();
}
/**
* @brief 小车 逆时针转动
* @param L:左电机PWM设定值(0-35);
R:右电机PWM设定值(0-35);
设定值越小电机转速越快。
* @retval 无
**/
void Rotate_Counterclockwise(u8 L,u8 R)
{
Pwm_Set(L,R);
Left_Motor_Back();
Right_Motor_Go();
}
void Pwm_Init(void) //PWM初始化函数,初始占空比为0
{
CMOD = 0x02; //空闲时不计数,不产生中断,时钟源为fosc/2
CL = 0x00; //初始化为0
CH = 0x00;
CCAPM0 = 0x42; //8位 PWM
CCAP0L = 0x00; //初始化为0
CCAP0H = 0x00;
CCAPM1 = 0x42; //8位 PWM
CCAP1H = 0x00; //初始化为0
CCAP1L = 0x00;
CR = 1; //开启PCA计数器
}
void Pwm_Set(u8 x,u8 y) //占空比设置函数
{
CCAP1H = x * 2.55; //占空比公式D=(256-CCAPnH)/ 256(8位PWM模式)
CCAP1L = x * 2.55; //乘2.55转换为0到100%
CCAP0H = y * 2.55;
CCAP0L = y * 2.55;
}