完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
PID控制算法是工业控制领域使用最广泛的算法之一,嵌入式系统是工业领域和生活中最常见的智能控制系统之一。本文以单片机控制两个带编码器的直流电机使二者转速保持一致为例讲PID算法与直流电机的PWM技术控制。本文围绕下面几个问题展开: 什么是PID控制算法? PID控制算法即比例、积分、微分控制算法。PID控制分为两种:模拟PID和数字PID,前者处理的是连续信号,后者处理的是离散信号。因为单片机只能处理离散信号,本文主要谈后者。对于后者,又分为两种常用的算法即增量式数字PID和位置式数字PID,其中增量式用的更多,所以本文以增量式数字PID为例。PID控制的数学原理比较复杂,限于作者水平,大家可以点击这里进一步了解其控制原理。另外,根据实际控制需求,PID控制算法不一定三个环节都要用,一般常用的还有PI控制、PD控制。 典型的闭环控制系统结构图 PID控制算法的典型的结构图 PID控制算法的设计过程中最重要的一个环节就是确定三个参数值的大小的确定,即PID参数整定。为了方便叙述,我们直接用上面的链接里的思路,即确定三个系数A、B、C的大小。其中 : A = Kp + Ki + Kd,B = Kp + 2 * Kd,C = Kd。 ------- (1) Kp,Ki,Kd分别是PID控制器的三个参数。 注:上图直接从链接中截取 从本人实际的调试经历中,对于电机控制,我一般设置三个参数的大小关系为:Kp>>Kd,Ki,至于具体的数值以及Kp,Ki的相对大小需要根据控制需求和调试过程中输出的情况做一些调整,必要的话,还可能需要做一些算法上的调整,下面分情况详述:
直流编码电机的控制与转速的检测 带编码器的直流减速电机 编码器:所谓编码,就是它可以把电机的角位移或者角速度信号转换为电脉冲信号,通过对脉冲信号的检测可以确定电机的转速。在上面的结构图中,编码器就是传感器,它将电机转速经测量变速传给单片机。 编码器的驱动:我们用stm32f10xxx系列的单片机作为主控芯片,stm32单片机的定时器外设资源丰富,并且它的通用定时器本身就带有控制编码电机的工作模式,简直就是“量身定做”! 直流电机的控制:直流电机的转速控制用PWM技术实现,调节PWM的占空比可以线性地改变电机两端的电压,从而控制电机的转速,控制结构图如下: 直流电机的控制流程 上面的电机驱动本质是一个功率放大器,将单片机产生的、一定占空比的PWM矩形波转为一定电压电流的模拟信号,进而驱动电机。 程序实现的问题 程序流程如下: 下面挑重要的几步讲一下,然后总的源代码程序工程会以压缩包的形式共享出来。 1. 初始化 初始化这一步主要完成一些全局变量、外设的赋值和配置工作。具体是:PID控制相关参数的初始化,定时器、串口等其他辅助性的外设的配置: delay_init(); //延时函数初始化 TIM5_PWM_Init(1000,9); //PWM初始化 8KHz TIM3_ENC_Init(); //编码器初始化 TIM4_ENC_Init(); //编码器初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级配置 pid_init(); uart_init(115200); //初始化串口,波特率设置为115200 2. PID参数设置 do //下面的循环语句是为了调节PID参数,串口接收到'0',跳出循环 { switch(go) //注意大小写 { case 'P': mts.Kp += val; go = 0; break; case 'I': mts.Ki += val; go = 0; break; case 'D': mts.Kd += val; go = 0; break; case 'p': mts.Kp -= val; go = 0; break; case 'i': mts.Ki -= val; go = 0; break; case 'd': mts.Kd -= val; go = 0; break; default: break; } delay_ms(10); }while(go != '0'); 这一步是为了后面程序复位后方便调整PID参数,即便于PID参数整定。 3. 循环体 while(1) { detPID_PWM_out();//调用PID函数,计算控制增量 if(sendFlag) //每刷新一次控制输出,往上位机发一次数据 { send_intData(mts.detPWM_out); sendFlag = 0; } TIM_SetCompare1(TIM5,BASE_SPEED - mts.detPWM_out); //注意电机的正反转,这里的4个通道可以控制两个电机正反转 TIM_SetCompare2(TIM5,BASE_SPEED + mts.detPWM_out); TIM_SetCompare3(TIM5,0); //通道3、4为0,此时假设两个电机刚好往同一个方向转,如果转向不一致,请对调硬件或再修改代码,这里只举例说明 TIM_SetCompare4(TIM5,0); } } 循环体里面计算控制输出,并根据控制输出调整PWM矩形波的占空比。 4. 中断 /*下面是中断服务函数,定时器中断的优先级高于串口中断*/ void USART1_IRQHandler(void) //串口1中断服务程序 { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d(回车) 0x0a(换行)结尾) { if(sendFlag%2) { val = USART_ReceiveData(USART1); //读取接收到的数据 } else { go = USART_ReceiveData(USART1); //读取接收到的数据 } sendFlag = ++sendFlag >= 255?1:sendFlag; } } void TIM6_IRQHandler(void) //TIM6中断 { if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 { TIM_ClearITPendingBit(TIM6, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源 // (u_16) = TIM_GetCounter(TIM4); // (U_16) = TIM_GetCounter(TIM3); mts.Ek_2 = mts.Ek_1; mts.Ek_1 = mts.Ek; mts.Ek = TIM_GetCounter(TIM3) - TIM_GetCounter(TIM4); //计算偏差 sendFlag = 1; } } 循环体里面计算控制输出,并根据控制输出调整PWM矩形波的占空比。 程序中只用了两个中断,一个是串口接收中断,用于接收上位机的命令和数据,以便调试或者监控程序里面一些变量的变化;另一个是定时器中断,为了以50Hz的频率采集编码器反馈的速度信号,同时计算偏差。 总结 本文只介绍了最简单的PID控制算法C语言实现,上面提到的那几种常用的PID改进算法每一个都可以单独拿出来讲一下如何实现,但限于篇幅且本文重点不是这个所以大家感兴趣的话可以先查查相关的文章,后面有机会我会再单独讲一下我个人对这些算法的理解和实际应用中的实现。本文的基于uKeil的C源码工程共享在公众号“24K纯学渣”上面,回复“PID电机控制”即可获取。另外,限于作者水平,如有描述错误或不妥之处,欢迎大家在下面评论指出。如果希望进一步的交流学习,可以在公众号上联系作者,任何学习上的交流本人都非常欢迎! |
|
|
|
只有小组成员才能发言,加入小组>>
2435 浏览 0 评论
9100 浏览 4 评论
36773 浏览 19 评论
5026 浏览 0 评论
24745 浏览 34 评论
1528浏览 2评论
1743浏览 1评论
2193浏览 1评论
1553浏览 0评论
524浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 20:39 , Processed in 1.108149 second(s), Total 44, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号