【无标题】PID控制TT编码器电机

编程入门 行业动态 更新时间:2024-10-21 07:45:51

【无标题】PID控制TT<a href=https://www.elefans.com/category/jswz/34/1762206.html style=编码器电机"/>

【无标题】PID控制TT编码器电机

记录本人学习的笔记

开始学习PID感觉他很难,其实并不是的。首先我们需要取了解PID控制电机的基本流程,然后再搭配你学的理论知识。

下面来讲讲具体的实现,首先设置单片机的定时器用来读取到AB相中的脉冲数目(首先注意的是获取脉冲的通道只能是定时器的前两个通道),然后在PID中将你设置的脉冲数目与测得的脉冲数目进行对比。通常来说我们设定的是转速,所以我们需要将转速转换成脉冲数目。举个例子:TT电机13线的使四倍频,一圈有2496个脉冲,我们设定50转每分钟(这里只轮子转速,如果是电机内部转速需要除以你的减速比),然后我们设置定时器10ms读取一次值。那么10ms脉冲数应该为50*2496/6000(一分钟有6000个10ms),因此将设定脉冲与目前测得得脉冲带入PID计算公式算出值,抽象地来说它就是个依据偏差,产生的控制作用。通过计算值产生一个PWM信号。

下面是部分代码,可以看一看,基本上就这些东西。

1.对定时器进行设置

#include "encoder.h"
#include "delay.h"
#include "usart.h"//PA0
//PA1
void TIM5_Encoder_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x00;  // No prescaling TIM_TimeBaseStructure.TIM_Period = 65535;  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = 10;TIM_ICInit(TIM5, &TIM_ICInitStructure);TIM_SetCounter(TIM5,0);TIM_Cmd(TIM5, ENABLE);    
}

2.PID计算部分

这里有两种计算公式就是写法不同,用哪个都可以,PID计算公式用很多看你自己需求。

#include "pid.h"static double Kp=10;
static double Ki=0;
static double Kd=0;
int shouxie_PID_ZLP(int now , int set)
{int PWM,Bias,Bias_D;static int error,last_Bias;Bias = now - set;error +=Bias;Bias_D=Bias-last_Bias;PWM = Kp*Bias + Ki*error +Kd*Bias_D;last_Bias = Bias;return PWM;}
static double   ProportionA=70;                               
static double   IntegralA=25;                                
static double   DerivativeA=35;int SPEED_PID_A(int now,int set)
{static int  LastError;	//Error[-1]static int  PrevError;  //Error[-2]int iError,Output;     iError=set-now;Output = ((ProportionA * (iError - LastError)) + (IntegralA * iError) + (DerivativeA * (iError - 2*LastError + PrevError)));	PrevError=LastError;                    LastError=iError;return Output;                              
}

3.对输出进行控制

#include "control.h"
#include "pid.h"
#include "datascope.h"
#include "motor.h"
#include "usart.h"int para_A;
int Motor_A;
int SetRPMA=100;
#define SetPointA SetRPMA*2496/6000int myabs(int a){int temp;if(a < 0) temp = -a;else temp = a;return temp;
}
int Read_Encoder(u8 x)
{int Encoder_TIM;    switch(x){case 5:  Encoder_TIM= (short)TIM5 -> CNT;  TIM5 -> CNT=0;break;default: 	Encoder_TIM=0;}return Encoder_TIM;
}int Encoder_A;  
int Send_Count,i;
extern int adc_data;
int position_out;
int ac_speed_b;
int bigout_B;void TIM6_IRQHandler(void)
{if(TIM_GetFlagStatus(TIM6, TIM_IT_Update) != RESET) {Encoder_A=Read_Encoder(5);  //读取编码器得值                       para_A=SPEED_PID_A(Encoder_A,SetPointA);/*将设定脉冲与测得脉冲带入到PID控制器中*/	printf("%d\r\n",Encoder_A);if((para_A<-3)||(para_A>3)) {Motor_A +=para_A;  } if(Motor_A>7000)Motor_A=7000;//限幅if(Motor_A<-7000)Motor_A=-7000;if(Motor_A > 0){MotorA1 = 0;MotorA2 = 1;}else{MotorA1 = 1;MotorA2 = 0;}TIM8->CCR1 = myabs(Motor_A);/*定时器8 我使用得计数周期为一万,CCR1的值为 myabs(Motor_A)*/}TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update);   }

有不懂的或者是我错的可以写在评论区。

更多推荐

【无标题】PID控制TT编码器电机

本文发布于:2024-03-13 02:38:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732997.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:编码器   无标题   电机   TT   PID

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!