STM32——直流电机PI调速

所需元件

  STM32F103开发板、L298N一个、带编码器的直流电机一个(如下图所示,淘宝上有很多)
在这里插入图片描述

系统框图

在这里插入图片描述
  通过系统框图,我们需要做两件事,一是要测速,二是要调节。测速目前流行的就是通过编码器测速,调节器我采用的时PI调节,PI调节器调节的参数少,而且能够消除静差,当然用PID调节器也行。

编码器

  编码器的结构简化如下图:
在这里插入图片描述
  在电机转轴上安装了一个磁环,在磁环的下方有一个霍尔传感器,在磁环转动过程中就在霍尔传感器的附近产生了变化的磁场,于是霍尔传感器就输出了脉冲信号。我所用的这个直流电机是1:48的减速电机,电机转轴每转动1圈,编码器输出13个脉冲信号,也就是说输出转轴转动1圈,编码器输出13x48=624个脉冲,再通过STM32编码器接口 4 倍频就是 624x4=2496 个脉冲信号,通过STM32定时器的计数值除以2496就是输出转轴转动的圈数。
  所谓4倍频,如下图:
在这里插入图片描述
  编码器中有两个线路,即A相和B相。我们以A相或B相为例,1个上升沿或者下降沿代表1个脉冲信号,由图中可知有2个上升沿或2个下降沿,即2个脉冲信号。而所谓的4倍频,就是把A、B相的上升沿和下降沿都加起来,一共8个,与之前的2个脉冲信号就是4倍,而所以要加起来做成4倍频,可以提高测量转速的精度。另外A、B相之间相差90度,从而可以判断电机的转向。如果电机正转,A相比B相先90度,也就是说A相已经上升沿了B还是低电平。

理论分析

建模

  直流有刷电机可以等效为下图结构。
在这里插入图片描述
在这里插入图片描述
经拉式变换得传递函数
在这里插入图片描述
  由于电枢电感和转子转动惯量都较小,故而传递函数中二次项系数非常小,可忽略二次项做降阶处理,得
在这里插入图片描述

PI调节器

  关于PID算法,可参考STM32——PID恒温控制
P I PI PI调节器表达式如下
在这里插入图片描述
P I PI PI算法省去了微分控制,以损失响应快速性为代价以保证系统的可靠性。

理论计算

  直流电机的相关参数可以测量出来,但由于没有工具只得通过系统辨识的方法获取电机的传递函数
在这里插入图片描述
已知电源电压为 12 v 12v 12v,单片机PWM配置中计数值为100时代表100%占空比,周期为10ms,可近似pwm的传递函数为
在这里插入图片描述
输入为占空比 D D D,输出为电压,且 0 < D < 100 0<D<100 0<D<100(因为计数值为100时代表 100 % 100 \% 100%占空比,所以可认为占空比就在 0 < D < 100 0<D<100 0<D<100之间,但实际上真正的占空比数值在 0 − 1 0-1 01之间)。令 G ( s ) = G G(s)=G G(s)=Gm ( s ) ∗ G (s)*G (s)Gpwm ( s ) (s) (s),得
在这里插入图片描述
可近似为一阶系统
在这里插入图片描述
此时系统框图如下
在这里插入图片描述

得系统闭环传递函数
在这里插入图片描述
我希望电机响应的超调量很低,调节时间可以长一点,相关参数如下
在这里插入图片描述

在这里插入图片描述
计算出来的参数还不能直接使用,由于单片机控制电机是离散控制,所以实际使用的积分系数 K K Ki等于计算出的 K K Ki乘以采样周期 T T T。由于传递函数误差或者其他一些原因会造成理论计算的参数并不一定与实际效果高度一致,还需手动微调一下,找到一个更为合适的参数。
仿真结果如下
在这里插入图片描述
通过仿真来看,超调量仍然较大,调节时间在 0.7 s 0.7s 0.7s左右,超调量大是由于引入了一个闭环零点,调节时间与理论值有误差是由于理论计算是取近似值等原因造成的。如果要追求更低的超调量,可以在输入端加入一个前置滤波器,该前置滤波器的作用就是用滤波器的极点对消闭环系统的零点,系统框图如下
在这里插入图片描述
仿真结果如下
在这里插入图片描述
从图像上看,调节时间变化不大,但是超调量明显的小了许多。
  这里贴两张速度曲线图:
  1、
在这里插入图片描述
  2、
在这里插入图片描述
  这两组响应的曲线的参数是试凑得来的,与理论计算的参数相差不是很大,理论计算的参数使用效果上略好一些。图1中设定目标值为400,从图上可以看出超调量还是比较小的,调节时间也比较短,调节的效果还是可以的。图2中,目标值每隔一段时间增加100,加到400后又设为100,整体的调节效果还是蛮不错的。

主要程序

TIM_Encoder.c

#include "TIM_Encoder.h"

float RPM_1=0;            //存储上一次测速结果

void TIM_Encoder_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
    TIM_ICInitTypeDef TIM_ICInitStructure;  
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);        //使能定时器4的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);       //使能PB端口时钟
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	    //端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;       //浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);					    //根据设定参数初始化GPIOB
    
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = 0x0;                  // 预分频器 
    TIM_TimeBaseStructure.TIM_Period = 65535;                   //设定计数器自动重装值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //选择时钟分频:不分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;
    TIM_ICInit(TIM4, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);                       //清除TIM的更新标志位
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
    //Reset counter
    TIM_SetCounter(TIM4,0);
    TIM_Cmd(TIM4, ENABLE);  
}

int GetTIMCounter(void)          //获取计数值
{
    int count=TIM_GetCounter(TIM4);
    return count;
}

float GetRPM(int count)           //计算转速
{
//   int RPM=count/2496*2000+0.5;//30ms计算一次(pid.T=30),60000ms为1min,也就是1min计算了2000次,2496=13*4*48表示转动一圈的脉冲数,48表示1:48的减速比
    float RPM=count*0.8f;   //等同于上式,2000/2496约等于0.8
    if(RPM>1000)                 //过滤掉不合理的结果,仍然使用上次的速度,在按键设定速度的时候或者在减速为0时会有非常的大的错误测速结果,具体原因还未查清    {
    {
        return RPM_1;
    }
    RPM_1=RPM;                   //更新
    return RPM;
}

PID.c

#include "PID.h"

PID pid;
//int time=0;

void PID_Init()
{           
    pid.Sv=400;         //用户设定转速400
	pid.Kp=0.3;         //比例
    pid.Ki=0.015;       //积分
	pid.Kd=0;           //微分
	pid.pwmcycle=100;   
    pid.T=30;           //PID计算周期30ms
	pid.OUT0=0;
	pid.C1ms=0;
    pid.SEk=0;
    pid.Ek=0;
    pid.Ek_1=0;
    pid.DelEk=0;
    pid.Dout=0;
    pid.Iout=0;
    pid.Pout=0;
}

void PID_Calc(float data)        //pid计算
{
	float out;
    pid.Pv=data;
 	pid.Ek=pid.Sv-pid.Pv;       //得到当前的偏差值
 	pid.Pout=pid.Kp*pid.Ek;     //比例输出
 	pid.SEk+=pid.Ek;            //历史偏差总和
    if(pid.SEk<(-50))
    {
        pid.SEk=(-50);
    }
 	pid.DelEk=pid.Ek-pid.Ek_1;  //最近两次偏差之差
    pid.Iout=pid.Ki*pid.SEk;    //积分输出
    if(pid.Iout<(-10))
    {
        pid.Iout=(-10);
    }
    pid.Dout=pid.Kd*pid.DelEk;  //微分输出
 	out= pid.Pout+ pid.Iout+ pid.Dout;
 	if(out>pid.pwmcycle)
 	{
  		pid.OUT=pid.pwmcycle;
 	}
 	else if(out<=0)
 	{
		pid.OUT=pid.OUT0; 
 	}
 	else 
 	{
  		pid.OUT=out+0.5f;       //四舍五入
 	}
 	pid.Ek_1=pid.Ek;            //更新偏差
 	pid.C1ms=0;
}

工程链接
链接:https://pan.baidu.com/s/1dSXgPf0gzSvTdjlMHyOZ7w
提取码:f8h1

  PID调参比较麻烦,这里推荐一个ST官方的软件StmStdio,这个软件网上有很多教程,使用也比较简单。
链接:https://pan.baidu.com/s/1etsrBL80rCe_LouNEE1XEg
提取码:ckve

注:为更方便高效的控制直流有刷电机可见直流有刷电机的简单高性能控制方法一文。

  • 35
    点赞
  • 315
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
基于STM32直流电机PID调速系统设计通常包含以下几个主要步骤: 首先,需要明确系统的需求和性能指标,如电机的额定电压和电流,所需的转速范围,以及加速度和减速度等。根据这些需求确定合适的电机类型和参数。 接下来,在硬件设计方面,选择合适的STM32系列微控制器作为控制核心。确保其具有足够的计算能力和丰富的外设接口,以满足PID算法的实现和与电机驱动器的通信需求。 然后,进行软件设计和编程。首先,在STM32的开发环境下,搭建合适的开发环境,如Keil或STM32CubeIDE等,并导入所需的外设库文件。然后,编写主要的程序逻辑,包括PID算法的实现,电机驱动器的初始化和控制信号的输出等。此外,还需要编写其他辅助功能,如输入检测和滤波等。 接着,进行系统测试和调试。通过模拟器或实际硬件平台,进行PID调速系统的各项功能测试,包括速度设定、驱动电机并测量反馈信号、调整PID参数,以及响应性能和稳定性等。在测试过程中,根据实际需求和测试结果,进行参数调整和优化。 最后,进行系统集成和应用。将调试完成的PID调速系统与电机传动系统等进行集成,确保整个系统的正常运行和稳定性。同时,根据实际应用需求,添加必要的保护电路和相应的用户界面,以提高系统的可靠性和易用性。 总结起来,基于STM32直流电机PID调速系统设计需要经过需求分析、硬件设计、软件编程、系统测试和调试、系统集成和应用等几个主要步骤。通过合理的系统设计和参数调整,可以实现稳定、高效的直流电机PID调速系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值