基于stm32f103实现电机的速度调控--pid算法实现速度环(开源) ...

打印 上一主题 下一主题

主题 504|帖子 504|积分 1512

 一、PID算法先容

PID算法,即比例-积分-微分控制算法,是一种广泛应用的控制策略。在自动控制体系中,PID控制器根据体系的输入(设定值)和输出(实际值)之间的偏差,通过比例、积分和微分三种运算方式,产生适当的控制信号,从而实现对被控对象的精确控制。
一、PID算法的基本原理
PID算法的焦点头脑是根据偏差的比例(P)、积分(I)和微分(D)来盘算控制量。这三种运算方式在控制过程中起到了差别的作用:

  • 比例控制(P):根据偏差的巨细直接调整控制量,偏差越大,控制量调整幅度越大。比例控制可以或许敏捷响应偏差的变化,但可能导致体系振荡。
  • 积分控制(I):对偏差进行积分运算,以消除体系中的稳态误差。积分控制可以或许逐渐减小偏差,使体系趋于稳定,但可能导致体系响应速度变慢。
  • 微分控制(D):根据偏差的变化率来调整控制量,具有猜测偏差趋势的能力。微分控制可以或许提前调整控制量,以抑制体系振荡,提高体系的稳定性。
二、PID算法的应用场景

PID算法因其简朴、实用、鲁棒性强的特点,在各个领域得到了广泛应用。以下是一些典型的应用场景:

  • 工业自动化:PID控制器在工业自动化领域中具有重要职位,如温度控制、压力控制、流量控制等。
  • 机器人控制:PID算法可用于机器人的活动控制,如轨迹跟踪、姿态调整等。
  • 航空航天:PID控制器在航空航天领域也发挥着重要作用,如飞机姿态控制、卫星轨道控制等。
三、PID算法的优缺点

PID算法的优点主要表现在以下几个方面:

  • 原理简朴:PID算法基于基本的数学运算,易于明白和实现。
  • 适应性强:PID算法可以或许适应各种非线性、时变和不确定性体系,具有较强的鲁棒性。
  • 控制效果好:通过公道调整PID参数,可以实现较高的控制精度和稳定性。
然而,PID算法也存在一些缺点:

  • 参数调整困难:PID算法的参数(比例系数、积分系数、微分系数)需要根据具体体系进行调整,调整过程可能较为繁琐。
  • 可能存在超调现象:在某些情况下,PID控制器可能导致体系超调,即控制量过大或过小,影响体系稳定性。
四、基本原理及代码实现

        通过红外对射及码盘的团结搭配测得实际速度,再设定目标速度,pid算法根据目标速度及实际速度进行调控。
main.c
  1. #include "stm32f10x.h"                  // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "CountSensor.h"
  5. #include "mortpwm.h"
  6. #include "Motor.h"
  7. #include "usart.h"
  8. #include "Timer.h"
  9. float num;
  10. extern int CountSensor_Count;
  11. float speed;
  12. // PID控制器结构体  
  13. typedef struct {  
  14.     float Kp;     // 比例系数  
  15.     float Ki;     // 积分系数  
  16.     float Kd;     // 微分系数  
  17.     float SetPoint; // 目标值  
  18.     float ProcessVariable; // 过程变量(当前速度)  
  19.     float ErrorSum; // 误差和  
  20.     float LastError; // 上一次误差  
  21.     float Output; // PID输出  
  22. } PIDController;
  23. // 初始化PID控制器的函数  
  24. void PID_Init(PIDController *pid, float kp, float ki, float kd, float setPoint) {  
  25.     pid->Kp = kp;             // 设置比例系数  
  26.     pid->Ki = ki;             // 设置积分系数  
  27.     pid->Kd = kd;             // 设置微分系数  
  28.     pid->SetPoint = setPoint; // 设置目标值  
  29.     pid->ProcessVariable = 0.0f; // 初始化过程变量  
  30.     pid->ErrorSum = 0.0f;     // 初始化误差累积和  
  31.     pid->LastError = 0.0f;     // 初始化上一次误差  
  32.     pid->Output = 0.0f;       // 初始化输出值  
  33. }
  34. // 计算PID控制器输出的函数  
  35. float PID_Calculate(PIDController *pid, float processVariable) {  
  36.     float error = pid->SetPoint - processVariable; // 计算当前误差  
  37.     pid->ErrorSum += error;                       // 更新误差累积和  
  38.     float derivative = error - pid->LastError;    // 计算误差的微分  
  39.     pid->Output = pid->Kp * error                 // 比例项  
  40.                    + pid->Ki * pid->ErrorSum       // 积分项  
  41.                    + pid->Kd * derivative;         // 微分项  
  42.     pid->LastError = error;                       // 更新上一次误差  
  43.     pid->ProcessVariable = processVariable;       // 更新过程变量  
  44.     return pid->Output;                           // 返回PID输出值  
  45. }
  46. int main(void)
  47. {
  48.         /*模块初始化*/
  49.         OLED_Init();                        //OLED初始化
  50.         CountSensor_Init();                //计数传感器初始化
  51.         Motor_Init();       
  52.         mortpwm_Init();
  53.         Timer_Init();
  54.         uart_init(9600);
  55.         /*显示静态字符串*/
  56.         OLED_ShowString(1, 1, "Count:");        //1行1列显示字符串Count:
  57.         static PIDController speedPID;  // 定义并初始化PID控制器
  58.         static int initialized = 0; // 用于判断PID是否已初始化  
  59.         while (1)
  60.         {
  61.                 if (!initialized) {  
  62.                                 PID_Init(&speedPID, 0.2f, 0.01f, 0.001f, 2.5f); // 初始化PID,目标速度为2.5
  63.                                 initialized = 1;  
  64.                 }
  65.                
  66.                 // 计算PID输出  
  67.                 float pwmValue = PID_Calculate(&speedPID, speed);
  68.                 OLED_ShowNum(1, 7, CountSensor_Get(), 5);                //OLED不断刷新显示CountSensor_Get的返回值
  69.                                 // 设置电机PWM值  
  70. //                printf("%.3f\r\n",pwmValue);
  71.                 Goahead(pwmValue*10);
  72.         }
  73. }
  74. /**
  75.   * 函    数:TIM3中断函数
  76.   * 参    数:无
  77.   * 返 回 值:无
  78.   * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  79.   *           函数名为预留的指定名称,可以从启动文件复制
  80.   *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  81.   */
  82. void TIM3_IRQHandler(void)
  83. {
  84.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)                //判断是否是TIM2的更新事件触发的中断
  85.         {
  86.                 num=CountSensor_Get();                //Num变量获取20孔码盘所经过的孔数
  87.                 speed=num/20.000;         //每秒获取到的num数除以20为圈数,speed为每秒多少圈
  88.                 printf("每秒%.3f\r\n",speed);//串口打印输出速度
  89.                 CountSensor_Count=0;
  90.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);                        //清除TIM2更新事件的中断标志位
  91.                                                                                                                         //中断标志位必须清除
  92.                                                                                                                         //否则中断将连续不断地触发,导致主程序卡死
  93.         }
  94. }
复制代码
电机pwm控制转速
mortpwm.c
  1. #include "stm32f10x.h"                  // Device header
  2. #include "stm32f10x_tim.h"   
  3. #include "mortpwm.h"   
  4. void mortpwm_Init(void)
  5. {
  6.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  8. //        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  9.        
  10. //        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//用来打开AFIO外设的时钟。AFIO外设用于控制引脚重映射功能。引脚重映射功能允许将某些外设的引脚映射到其他引脚上,以便更灵活地配置引脚功能。
  11. //        GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);//将TIM2定时器的引脚部分重映射到其他引脚上
  12. //        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//禁用JTAG调试接口。在某些情况下,需要释放JTAG接口的引脚以供其他功能使用,这时就需要禁用JTAG调试接口。
  13.        
  14. GPIO_InitTypeDef GPIO_InitStructure;  // 定义一个GPIO_InitTypeDef类型的变量GPIO_InitStructure
  15. //GPIO_InitTypeDef GPIO_InitStructure2;
  16. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 设置GPIO_InitStructure的GPIO模式为复用推挽输出
  17. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;  // 设置GPIO_InitStructure的引脚为GPIOA的第0号引脚
  18. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  // 设置GPIO_InitStructure的输出速度为50MHz
  19. GPIO_Init(GPIOA, &GPIO_InitStructure);  // 初始化GPIOA的引脚配置为GPIO_InitStructure所定义的配置
  20. //GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF_PP;  // 设置GPIO_InitStructure的GPIO模式为复用推挽输出
  21. //GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_6;  // 设置GPIO_InitStructure的引脚为GPIOA的第0号引脚
  22. //GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;  // 设置GPIO_InitStructure的输出速度为50MHz
  23. //GPIO_Init(GPIOA, &GPIO_InitStructure2);  // 初始化GPIOA的引脚配置为GPIO_InitStructure所定义的配置       
  24. TIM_InternalClockConfig(TIM2);  // 配置TIM2的内部时钟
  25. //TIM_InternalClockConfig(TIM3);  // 配置TIM2的内部时钟
  26. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;  // 定义一个TIM_TimeBaseInitTypeDef类型的变量TIM_TimeBaseInitStructure
  27. //TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure2;
  28. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 设置时钟分频为不分频
  29. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 设置计数模式为向上计数
  30. TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;  // 设置周期为100-1,即ARR寄存器的值
  31. TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;  // 设置预分频器的值为720-1,即PSC寄存器的值
  32. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;  // 设置重复计数器的值为0
  33. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);  // 初始化TIM2的时间基础设置为TIM_TimeBaseInitStructure所定义的配置
  34. //TIM_TimeBaseInitStructure2.TIM_ClockDivision = TIM_CKD_DIV1;  // 设置时钟分频为不分频
  35. //TIM_TimeBaseInitStructure2.TIM_CounterMode = TIM_CounterMode_Up;  // 设置计数模式为向上计数
  36. //TIM_TimeBaseInitStructure2.TIM_Period = 100 - 1;  // 设置周期为100-1,即ARR寄存器的值
  37. //TIM_TimeBaseInitStructure2.TIM_Prescaler = 720 - 1;  // 设置预分频器的值为720-1,即PSC寄存器的值
  38. //TIM_TimeBaseInitStructure2.TIM_RepetitionCounter = 0;  // 设置重复计数器的值为0
  39. //TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure2);  // 初始化TIM2的时间基础设置为TIM_TimeBaseInitStructure所定义的配置
  40. TIM_OCInitTypeDef TIM_OCInitStructure;  // 定义一个TIM_OCInitTypeDef类型的变量TIM_OCInitStructure
  41. TIM_OCStructInit(&TIM_OCInitStructure);  // 初始化TIM_OCInitStructure为默认值
  42. //TIM_OCInitTypeDef TIM_OCInitStructure2;  // 定义一个TIM_OCInitTypeDef类型的变量TIM_OCInitStructure
  43. //TIM_OCStructInit(&TIM_OCInitStructure2);  // 初始化TIM_OCInitStructure为默认值
  44. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  // 设置输出比较模式为PWM模式1
  45. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  // 设置输出极性为高电平有效
  46. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  // 启用输出
  47. TIM_OCInitStructure.TIM_Pulse = 0;  // 设置脉冲值为0,即CCR寄存器的值,值越大,LED越暗
  48. TIM_OC1Init(TIM2, &TIM_OCInitStructure);  // 初始化TIM2的输出比较通道1为TIM_OCInitStructure所定义的配置
  49. TIM_OC2Init(TIM2, &TIM_OCInitStructure);  // 初始化TIM2的输出比较通道1为TIM_OCInitStructure所定义的配置
  50. TIM_Cmd(TIM2, ENABLE);  // 使能TIM2定时器
  51. //TIM_OCInitStructure2.TIM_OCMode = TIM_OCMode_PWM1;  // 设置输出比较模式为PWM模式1
  52. //TIM_OCInitStructure2.TIM_OCPolarity = TIM_OCPolarity_High;  // 设置输出极性为高电平有效
  53. //TIM_OCInitStructure2.TIM_OutputState = TIM_OutputState_Enable;  // 启用输出
  54. //TIM_OCInitStructure2.TIM_Pulse = 0;  // 设置脉冲值为0,即CCR寄存器的值,值越大,LED越暗
  55. //TIM_OC1Init(TIM3, &TIM_OCInitStructure2);  // 初始化TIM2的输出比较通道1为TIM_OCInitStructure所定义的配置
  56. //TIM_Cmd(TIM3, ENABLE);  // 使能TIM2定时器
  57. }
  58. void MORT_SetCompare1(uint16_t Compare)  //设置通道1的ccr的值
  59. {
  60.         TIM_SetCompare1(TIM2, Compare);
  61.        
  62. }
  63. void MORT_SetCompare2(uint16_t Compare)  //设置通道1的ccr的值
  64. {
  65.         TIM_SetCompare2(TIM2, Compare);
  66.        
  67. }
复制代码
mortpwm.h
  1. #ifndef __TIMER_H
  2. #define __TIMER_H
  3. #include "stdint.h"
  4. void mortpwm_Init(void);
  5. void MORT_SetCompare1(uint16_t Compare);
  6. void MORT_SetCompare2(uint16_t Compare);
  7. #endif
复制代码
五、测速结果

颠末一定时间速度到达2.5圈每秒,可给电机添加一定阻力减缓运转速度,通过pid调控后会加大pwm输出,从而调控其速度再次到达所设定值。

 
关于测速篇可看: 
测c基于stm32F103实现MH-Sensor红外对射模块加测速码盘进行测速
 
 源代码:链接: 通过百度网盘分享的文件:对射式红外传感器…
链接:https://pan.baidu.com/s/1bN8mKGs-qY6nfrjemnctpA?pwd=nxmx 
提取码:nxmx
复制这段内容打开「百度网盘APP 即可获取」
 
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小小小幸运

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表