C51

C51单线循迹小车

硬件材料

C51最小系统板,L298N电机驱动模块,TCRT5000五路循迹传感器,USB转TTL模块,小车模组,电池

制作思路

红外传感器检测黑线(黑色低电平,白色高电平),对检测结果进行分析判断,并控制轮子的转速来达到转弯等的控制.

流程

  1. 选择需要使用的IO口,然后将对应的管脚连接对应的模块.(注意各模块和系统板的相对位置,不然连线会比较乱)
  2. 写程序,实地测试,不断调整差速修改程序.

代码

#include <reg52.h>
#include <stdio.h>
#define TrackPort P2  //循迹模块接口

//电机驱动接口
sbit M2PWM = P1^0;
sbit M2B = P1^2;      
sbit M2A = P1^1;
sbit M1B = P1^3;
sbit M1A = P1^4;
sbit M1PWM = P1^5;

unsigned char timeCnt; //周期计数值
unsigned char DutyRatio_L,DutyRatio_R; //占空比0-100

char Motor_L_e = 0; //机械误差
char Motor_R_e = 0;

bit enableMotor = 1; //电机启动开关

void PWM_Config();
void setPWM(char set_L,char set_R);
unsigned char ScanLine();

void PWM_Config()  //定时器初始化
{
	TH2=0xFE;
	TL2=0x0c;
	ET2=1;
	EA=1;
	M2PWM=0;
	M1PWM =0;
	TR2=1;
}

void Timer2_PWM(void) interrupt 5  //定时器中断函数
{
	TF2 =0;
	TH2=0xFE;
	TL2=0x0c;
	
	timeCnt++; //计数
	if(timeCnt>100)
	{
		timeCnt=0;  //计数周期100归零
	}
	if(enableMotor)  //电机启动开关
	{
		//启动
		M2PWM = (timeCnt<DutyRatio_L)? 1 : 0;
		M1PWM = (timeCnt<DutyRatio_R)? 1 : 0;
	}
	else
	{
		//关闭
		M2PWM = 0;
		M1PWM = 0;
	}
}

void setPWM(char set_L,char set_R)
{
		
	if(set_L>=0)
	{
		//正转
		M2B=1;
		M2A=0;
		//设置占空比  Motor_L_e是机械误差校正
		DutyRatio_L = set_L + Motor_L_e;
	}
	else
	{
		//反转
		M2B=0;
		M2A=1;
		//设置占空比(负号代表取绝对值) Motor_L_e是机械误差校正
		DutyRatio_L = -set_L + Motor_L_e;
	}
	if(set_R>=0)
	{
		M1B=0;
		M1A=1;
		DutyRatio_R = set_R + Motor_R_e;
	}
	else
	{
		M1B=1;
		M1A=0;
		DutyRatio_R = -set_R + Motor_R_e;
	}
	
	//限幅
	if(DutyRatio_L > 100)
		DutyRatio_L = 100;
	if(DutyRatio_L < 0)
		DutyRatio_L = 0;
	if(DutyRatio_R > 100)
		DutyRatio_R = 100;
	if(DutyRatio_R < 0)
		DutyRatio_R = 0;
}

unsigned char ScanLine()
{
	unsigned char scanTemp; 
	int scanResult;	 //返回值

	scanTemp = TrackPort;   //读取TrackPort
	scanTemp = TrackPort & 0x1F; //在TrackPort中提取Px.0-Px.4

	switch(scanTemp)
	{
		case 0x1e: scanResult = 1;break; //11110  左偏3级
        case 0x1d: scanResult = 2;break; //11101  左偏1级
		case 0x19: scanResult = 2;break; //11001  左偏1级
        case 0x1c: scanResult = 2;break; //11100  左偏2级
		case 0x18: scanResult = 2;break; //11000  左偏2级(new)
        case 0x1b: scanResult = 3;break; //11011  √
        case 0x17: scanResult = 4;break; //10111  右偏1级
		case 0x13: scanResult = 4;break; //10011  右偏1级(new)
        case 0x0f: scanResult = 5;break; //01111  右偏3级
        case 0x07: scanResult = 5;break; //00111  右偏2级
		case 0x03: scanResult = 5;break; //00011  右偏2级(new)
        case 0x00: scanResult = 6;break; //00000  后退
		default: scanResult = 0; break;		//其他情况	
	}
	return scanResult;  //返回最后结果
}

void main()
{
	PWM_Config(); //PWM定时器初始化
	while(1)
	{
		switch (ScanLine())
		{
			case(1):setPWM(50,-50);break;   //右转
			case(2):setPWM(60,30);break;   //小幅右转
			case(3):setPWM(60,60);break;   //前进
			case(4):setPWM(30,60);break;   //小幅左转
			case(5):setPWM(-50,50);break;  //左转
			case(6):setPWM(-50,-50);break;  //后退
			case(0):setPWM(30,30);break;  //小幅度前进
		}
	}
}

PID算法

P(比例),I(积分),D(微分),理学堂上讲了PID算法,听得一知半解,我在网上搜了一些PID算法的解析,总算是更加理解了算法核心。
以下称为闭环控制系统,就是让输入指令执行得到的结果反馈给我们,再做出一系列判断实现对我们原始指令的调整,来达到我们需要的输出目的。
在这里插入图片描述
在这里插入图片描述e(k)为输出值与设定值之间的差值,
第一项为比例控制,每次对差值进行比例调整,相当于每次的e(k)都成比例变化,逐渐到0.
第二项为积分控制,为了防止某些因素导致的影响使输出结果永远达不到设定值(稳态误差),于是采用积分控制来不断对每次的e(k)进行积分,当长时间未达到设定值,第二项的比重会越来越大,知道影响u(k),从而系统不会存在稳态误差。
第三项为微分控制,对于这个的解释,我看了一个例子讲的比较好

考虑刹车情况。平稳的驾驶车辆,当发现前面有红灯时,为了使得行车平稳,基本上提前几十米就放松油门并踩刹车了。当车辆离停车线非常近的时候,则使劲踩刹车,使车辆停下来。整个过程可以看做一个加入微分的控制策略。
微分,说白了在离散情况下,就是error的差值,就是t时刻和t-1时刻error的差,即u=kd*(error(t)-error(t-1)),其中的kd是一个系数项。可以看到,在刹车过程中,因为error是越来越小的,所以这个微分控制项一定是负数,在控制中加入一个负数项,他存在的作用就是为了防止汽车由于刹车不及时而闯过了线。从常识上可以理解,越是靠近停车线,越是应该注意踩刹车,不能让车过线,所以这个微分项的作用,就可以理解为刹车,当车离停车线很近并且车速还很快时,这个微分项的绝对值(实际上是一个负数)就会很大,从而表示应该用力踩刹车才能让车停下来。
切换到上面给水缸加水的例子,就是当发现水缸里的水快要接近1的时候,加入微分项,可以防止给水缸里的水加到超过1米的高度,说白了就是减少控制过程中的震荡。

STM32GPIO初学

GPIO称为通用输入输出。
STM32的GPIO分为GPIOA–>GPIOG共七组,每组端口又被分为0-15共计16个不同的引脚。每个GPIO可被寄存器配置成8种工作模式(4种输入模式4种输出模式)。

GPIO点亮LED灯实验

跟着B站视频学习主要是从STM32CubeMX建立工程配置GPIO模式,之后的实验是自己查资料学习的。自己使用的是STM32F103C8T6最小系统板。

  1. 建立工程
    在STMCubeMX将PC13配置为GPIO_OUTPUT,然后再建立工程在keil中打开,在main.c文件中的main函数中写LED代码。
  2. 烧录程序
    烧录程序与51不同的是,STM32有几种烧录方式。
  • 通过ST-LINK烧录,因为这个东西比较贵,我就没有用。
  • 通过USB转TTL进行烧录。
    我这种烧录方式还需要手动调一下BOOT。
    在这里插入图片描述
    一般使用的好像都是将BOOT0设置为1,BOOT1为0,通过mcuisp进行下载。步骤如下:
  1. 手动调节跳线帽将BOOT0设置为1,BOOT1设置为0
  2. 将USB转TTL的3V3和GND与系统板上的对应位置连线,再讲RXD接PA9(TXD),将TXD接系统板的PA10(RXD).
  3. 打开mcuisp进行下载
  4. 下载完后将跳线帽调节BOOT0至0,按RESET进行启动运行

在这里插入图片描述
可以看到开发板上面的灯在闪烁。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
前言: 开始之前先要说为什么要采用PID的算法来控制小车。玩过小车的DIY爱好者们都会碰到这样一种情况:为什么本该直线行驶的小车走着走着轨迹就会发生偏移,即所谓的“走不直”。 小车走不直的原因有:两个电机本身的驱动特性不可能完全相同,两个电机外形大小不可能是完全一致,组装时精度也会出现差异,另外轮胎在滚动时打滑、遇到细小的障碍物等因素都会造成左右轮的速度出现差异,从而走不直。开环控制是无法消除左右轮的速度误差的,因为上述的扰动是随机的。 要想小车走一条直线,唯有实现闭环控制,当小车受到扰动时能对左右轮及时给予反馈,修正两轮的速度偏差,从而可以走出一条直线。PID算法就是一种闭环控制算法,实现PID算法需得从硬件上实现闭环控制,即存在反馈,所以我采用的是带测速装置的电机。 项目简介: 本项目采用的是PID控制算法来修正小车行走时两轮的速度偏差,实现小车可以走直线。小车是使用一个安卓App来控制小车的行走路径,App通过App Inventor2来进行编写。 完成作品图: 需要用到的材料: 1. Arduino Uno 2. Arduino Uno的扩展板 3. DFRobot L298 双路2A直流电机驱动板 4. HC-05或HC-06的蓝牙模块 5. 坦克小车底盘 6. 两个带霍尔传感器的电机 7. 锂电池 8. 杜邦线若干 软件部分: 1. Arduino IDE 2. App Invent 附件内容截图:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值