使用51单片机完成一辆巡边线循迹的小车
小车赛道
小车车模
传感器
使用4个灰度传感器。
小车循迹代码
#include <REG52.h> //51头文件
#define N 10000 //PWM峰值 F = 1 / N 频率
#define speed_car 2000 //小车直行运行速度
//数据类型定义
//无符号数据类型的定义
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long int uint32_t;
//有符号数据类型的定义
typedef char int8_t;
typedef int int16_t;
typedef long int int32_t;
//小红外传感器权值 ,Kd1为外侧红外的权值,Kd2为内侧红外传感器的权值
uint16_t Kd1 = 100, Kd2 = 300;
//四路红外引脚口
//左边
sbit Left_LED1 = P1^2;
sbit Left_LED2 = P1^0;
//右边
sbit Right_LED1 = P1^3;
sbit Right_LED2 = P1^1;
//两路PWM引脚端
sbit PWM_Left = P1^4;
sbit PWM_Right = P1^7;
//负端 为1时电机反转
sbit PWM_Left_GND = P1^5;
sbit PWM_Right_GND = P1^6;
//左右两路PWM值 为正时电机正转,为负时电机反转
int16_t PWM_Left_Data = 0,PWM_Right_Data = 0;
//定时器计数器
uint16_t T_count = 0;
//主函数
void main()
{
//红外传感器阈值
uint16_t Left_sum = 0 , Right_sum = 0;
//打开定时器0
TMOD = 0X02;//定时器0 工作方式2 八位重装载计数器
TH0 = 255; //定时器初值 每1ns计数一次
TL0 = 255;
TR0 = 1;//打开定时器0
ET0 = 1;//打开定时器0允许位
EA = 1;//打开总终端
//死循环
while(1)
{
//读取红外数据 当扫描到黑线时赋值为1 当没有黑线时为零
//Kd1为外侧红外的权值,Kd2为内侧红外传感器的权值
Left_sum = (Left_LED1) * Kd1 + (Left_LED2) * Kd2 ;
Right_sum = (Right_LED1) * Kd1 + (Right_LED2) * Kd2 ;
//当红外传感器只有其中一边检测到黑线时 小车沿边沿循迹
//差速转弯
PWM_Left_Data = speed_car + Left_sum - Right_sum ;
PWM_Right_Data = speed_car + Right_sum - Left_sum ;
//PWM限幅
//上限
PWM_Left_Data = (PWM_Left_Data > N) ? N : PWM_Left_Data;
PWM_Right_Data = (PWM_Right_Data > N ) ? N : PWM_Right_Data;
//下限
PWM_Left_Data = (PWM_Left_Data < -N) ? -N : PWM_Left_Data;
PWM_Right_Data = (PWM_Right_Data < -N ) ? -N : PWM_Right_Data;
}
}
//定时器中断函数
void Timer0() interrupt 1
{
TH0 = 255; //定时器初值 每1ns计数一次
TL0 = 255;
//定时器循环计数
T_count = (T_count < N ) ? (++T_count ) : 0;
//发生PWM波
//正端
PWM_Left = ((PWM_Left_Data >= 0) && ( T_count < PWM_Left_Data )) ? 1 : 0;
PWM_Right = ((PWM_Right_Data >= 0) && (T_count < PWM_Right_Data)) ? 1 : 0;
//负端
PWM_Left_GND = ((PWM_Left_Data < 0) && (T_count < -PWM_Left_Data)) ? 1 : 0;
PWM_Right_GND = ((PWM_Right_Data < 0) && (T_count < -PWM_Right_Data)) ? 1 : 0;
}