c8t6与PIID调节

本文章参考
https://blog.csdn.net/hbsyaaa/article/details/114715319?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167011700616800184129293%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=167011700616800184129293&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-4-114715319-null-null.142v67control,201v3add_ask,213v2t3_control2&utm_term=%E5%AE%9A%E6%97%B6%E5%99%A8%E7%9A%84%E7%BC%96%E7%A0%81%E5%99%A8%E5%8A%9F%E8%83%BD%E4%BD%9C%E7%94%A8%E6%98%AF%E5%95%A5&spm=1018.2226.3001.4187

一.PID概念
p:是一种比例控制,作用是相当与控制现在的输出与要求指令保持一致(存在着一种问题是静差,就不会达到目标值),在惯性系统中很实用(烧水)。
i:是一种积分控制,是用来研究过去产生的误差
D:是一种未来式的控制,用来演算以后可能出现的误差,反应误差信号变化控制的

在这里插入图片描述
其实PID是三种控制的和运算,也就是上面那个数学公式,第一项是p控制,第二项是i运算,第三项是d运算
但是对于单片机来说是没有这种连续的数据的,单片机都是离散的数据,所以用积分和微分最基本的定义来说就是:积分表示的是求和而微分所表示的意义就是求变化率。所以我们可以化简出下面的那 一个公式。

在这里插入图片描述
这个就是增量式pid算法,其实就是做个差
增量pid计算需要到:这次的误差,上次的误差,上上次的误差。

在这里插入图片描述
二。STM32F103C8T6定时器的编码器模式
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

这里我们使用定时器4作为我们的编码器模式接口

#include "ENCODER.h"

/*TIM4初始化为编码器接口*/
void Encoder_Init_TIM4(u16 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure; //定义一个引脚初始化的结构体  
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义一个定时器初始化的结构体
  TIM_ICInitTypeDef TIM_ICInitStructure; //定义一个定时器编码器模式初始化的结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能TIM4时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能CPIOB时钟
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//PB6、PB7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);	//根据GPIO_InitStructure的参数初始化GPIOB0

	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
	TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //选择时钟分频:不分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct的参数初始化定时器TIM4
	
	TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3:CH1、CH2同时计数,四分频
	TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
	TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度
	TIM_ICInit(TIM4, &TIM_ICInitStructure); //根TIM_ICInitStructure参数初始化定时器TIM4编码器模式

	TIM_Cmd(TIM4, ENABLE); //使能定时器4
}
/*TIM5初始化为编码器接口*/
void Encoder_Init_TIM5(u16 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure; //定义一个引脚初始化的结构体  
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义一个定时器初始化的结构体
  TIM_ICInitTypeDef TIM_ICInitStructure; //定义一个定时器编码器模式初始化的结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能CPIOB时钟
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;	//PA0、PA1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//根据GPIO_InitStructure的参数初始化GPIOB0

	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
	TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //选择时钟分频:不分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct的参数初始化定时器TIM4
	
	TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3:CH1、CH2同时计数,四分频
	TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
	TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度
	TIM_ICInit(TIM5, &TIM_ICInitStructure); //根TIM_ICInitStructure参数初始化定时器TIM4编码器模式

	TIM_Cmd(TIM5, ENABLE); //使能定时器4
}

//读取编码器计数
int Read_Encoder_TIM4(void)
{
	int Encoder_TIM;
	Encoder_TIM=TIM4->CNT; //定时器4取CNT寄存器的值
	if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于0正转,小于0反转。
	                                                      //TIM4->CNT范围为0-0xffff,初值为0。
	TIM4->CNT=0; //读取完后计数清零
	return Encoder_TIM; //返回值
}

int Read_Encoder_TIM5(void)
{
	int Encoder_TIM;
	Encoder_TIM=TIM5->CNT; //定时器5取CNT寄存器的值
	if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于0正转,小于0反转。
	                                                      //TIM5->CNT范围为0-0xffff,初值为0。
	TIM5->CNT=0; //读取完后计数清零
	return Encoder_TIM; //返回值
}

void PID_Init(PID_InitDefStruct* p)//左电机
{
p->velcity_Kp=5;
p->velcity_Ki=0.5;
p->velcity_Kd=0;
p->PID_is_Enable=1;
}
void PID2_Init(PID2_InitDefStruct* p)//右电机
{
p->velcity_Kp2=5;
p->velcity_Ki2=0.5;
p->velcity_Kd2=0;
p->PID2_is_Enable=1;
}

void velocity_PID(int Targetvelocity,int Currentvelocity,PID_InitDefStruct *p)
{
if(p->PID_is_Enable==1)
{
int En=Targetvelocity-Currentvelocity;//求出左电机误差值

	p->un+=p->velcity_Kp*(En-p->En_1)+p->velcity_Ki*En+p->velcity_Kd*(En-2*p->En_1+p->En_2);//pid计算
	p->En_2=p->En_1;//获取上上一次的误差
	p->En_1=En;//获得上次的误差
	p->PWM=p->un;//得到计算出来的误差值
	
}

else
{
PID_Init§;
}
}
void verocity_PID(int Targetvelocity,int Currentvelocity,PID2_InitDefStruct *p)
{
if(p->PID2_is_Enable==1)
{
int En=Targetvelocity-Currentvelocity;//求出右电机误差值

	p->un2+=p->velcity_Kp2*(En-p->En_3)+p->velcity_Ki2*En+p->velcity_Kd2*(En-2*p->En_3+p->En_4);//pid计算
	p->En_4=p->En_3;//获取上上一次的误差
	p->En_3=En;//获得上次的误差
	p->PWM2=p->un2;//得到计算出来的误差值
	
}

else
{
PID2_Init§;
}
}
剩下的内容后续补充

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,它具有多个定时器模块可以用于编码器模式的应用。 对于定时器4(TIM4)来说,它是一个16位的定时器/计数器,可以用于编码器模式。编码器模式是用于读取旋转编码器的脉冲信号,并计算出旋转方向和速度的模式。 要将TIM4配置为编码器模式,你可以按照以下步骤进行操作: 1. 启用TIM4的时钟。在RCC寄存器中设置对应的位(例如,使能APB1总线上的TIM4时钟)。 2. 配置TIM4的工作模式。将TIM4的控制寄存器(CR1)设置为适当的值,选择编码器模式。 3. 配置TIM4的计数方向。将TIM4的控制寄存器(CR1)中的DIR位设置为适当的值,以选择计数方向(正向或反向)。 4. 配置TIM4的输入滤波和预分频器。根据你的应用需求,设置TIM4的控制寄存器(SMCR)和预分频寄存器(PSC)。 5. 配置TIM4的编码器模式输入引脚。根据你的硬件连接,将相关引脚配置为TIM4的输入模式。 6. 启动TIM4。将TIM4的控制寄存器(CR1)中的CEN位设置为1,启动定时器。 7. 通过读取TIM4的计数器寄存器(CNT)来获取编码器的计数值。 请注意,以上步骤仅为大致的配置流程,具体的寄存器设置和引脚配置取决于你的应用需求和硬件连接。你需要参考STM32F103C8T6的参考手册和数据手册,以了解详细的寄存器位字段和功能。 希望以上信息能对你有所帮助!如有更多问题,请继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值