6. 直流电机电流环控制实现

您所在的位置:网站首页 无刷电机怎么转 6. 直流电机电流环控制实现

6. 直流电机电流环控制实现

2024-07-15 05:47:50| 来源: 网络整理| 查看: 265

6.2. 直流电机电流环控制-位置式PID实现¶ 6.2.1. 软件设计1¶

软件部分和上一章大体相同,区别在于更换了输入PID的参数为电流值,代码中也增加了电流获取的功能,本章代码在野火电机驱动例程中\improve_part\F407\直流有刷电机-电流环控制-位置式PID目录下,下面我们详细来看。

6.2.1.1. 编程要点1¶

配置定时器可以输出PWM控制电机

配置定时器可以读取当前电路中驱动电机的电流值

配置基本定时器可以产生定时中断来执行PID运算

编写位置式PID算法

编写电流控制函数

增加上位机曲线观察相关代码

编写按键控制代码

6.2.2. 软件分析1¶ 6.2.2.1. PWM定时器配置¶

定时器如何配置前面章节多次提到,这边就略过不讲了,只展示初始化输出PWM的定时器初始化所调用的函数。如有疑问,之前的章节有详细讲解,代码也非常简单易懂。

Motor_TIMx_Configuration()函数¶ 1 2 3 4 5 6 7 8 9 10 /** * @brief 初始化控制通用定时器 * @param 无 * @retval 无 */ void Motor_TIMx_Configuration(void) { TIMx_GPIO_Config(); TIM_PWMOUTPUT_Config(); } 6.2.2.2. 通用定时器定时获取电流值、计算PID¶

此代码位于野火电机开发板例程:直流有刷电机-电流环控制-位置式PID\User\motor_control\bsp_motor_control.c

motor_pid_control()函数¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 /** * @brief 电机位置式 PID 控制实现(定时调用) * @param 无 * @retval 无 */ void motor_pid_control(void) { int32_t actual_current = get_curr_val(); // 读取当前电流值 if (is_motor_en == 1) // 电机在使能状态下才进行控制处理 { float cont_val = 0; // 当前控制值 cont_val = PID_realize(actual_current); // 进行 PID 计算 if (cont_val PWM_MAX_PERIOD_COUNT) { cont_val = PWM_MAX_PERIOD_COUNT; // 速度上限处理 } set_motor_speed(cont_val); // 设置 PWM 占空比 #if defined(PID_ASSISTANT_EN) set_computer_value(SEND_FACT_CMD, CURVES_CH1, &actual_current, 1); // 给通道 1 发送实际值 #else printf("实际值:%d. 目标值:%.0f\n", actual_speed, get_pid_actual()); // 打印实际值和目标值 #endif } } /** * @brief 定时器每25ms产生一次中断回调函数 * @param htim:定时器句柄 * @retval 无 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim==(&TIM_TimeBaseStructure)) { motor_pid_control(); } }

代码中,由基本定时器每25ms产生一次中断,并在中断中调用motor_pid_control函数。该函数主要功能是获取当前驱动电机电流,通过PID计算反馈值并输出到PWM中。在代码的最后,使用set_computer_value发送下位机参数与上位机进行同步,这样一来就可以很直观的在上位机看到PID调整输出的过程。接下来我们在看看电流环的位置式PID算法。

6.2.2.3. 电流环位置式PID算法实现¶

此代码位于野火电机开发板例程:直流有刷电机-电流环控制-位置式PID\User\pid\bsp_pid.c

PID算法实现¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 /** * @brief PID算法实现 * @param actual_val:实际值 * @note 无 * @retval 通过PID计算后的输出 */ float PID_realize(float actual_val) { /*计算目标值与实际值的误差*/ pid.err=pid.target_val-actual_val; /*误差累积*/ pid.integral+=pid.err; /*PID算法实现*/ pid.actual_val=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last); /*误差传递*/ pid.err_last=pid.err; /*返回当前实际值*/ return pid.actual_val; } /** * @brief PID参数初始化 * @note 无 * @retval 无 */ void PID_param_init() { /* 初始化参数 */ pid.target_val=80.0; pid.actual_val=0.0; pid.err=0.0; pid.err_last=0.0; pid.integral=0.0; pid.Kp = 0; pid.Ki = 3.5; pid.Kd = 0; #if defined(PID_ASSISTANT_EN) float pid_temp[3] = {pid.Kp, pid.Ki, pid.Kd}; set_computer_value(SEND_P_I_D_CMD, CURVES_CH1, pid_temp, 3); // 给通道 1 发送 P I D 值 #endif }

这个函数主要实现了位置式PID算法,用传入的目标值减去实际值得到误差值得到比例项,在对误差值进行累加得到积分项, 用本次误差减去上次的误差得到微分项,然后通过前面章节介绍的位置式PID公式实现PID算法,并返回实际控制值。

这个公式就是代码第14行中的公式形式,公式和代码的计算方式基本一致,只不过在公式中第二项的Ki是使用的对误差积分, 在代码中变成了对误差的累加,虽然表达形式不一样,但是达到的效果和目的是一样的。 计算过后将误差传递用于下一次使用,并将实际值返回。

其实不难发现,上述的代码与上章的速度环位置式PID控制几乎没有区别,甚至是仅有PID参数的差异,可以看出PID控制算法,基本是有一定规律性的,难点就在于调参。上述代码中实现了PID参数的初始化,和PID算法的具体实现,代码看起来也是简单易懂的。

6.2.2.4. 主函数¶

主函数中主要初始化一些外设与上位机的协议,例如串口、定时器、ADC等,最后在主循环中轮询按键的事件和处理上位机数据。

主函数¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101/** * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { int32_t target_curr = 80; /* HAL 库初始化 */ HAL_Init(); /* 初始化系统时钟为168MHz */ SystemClock_Config(); /* 初始化按键 GPIO */ Key_GPIO_Config(); /* 初始化 LED */ LED_GPIO_Config(); /* 协议初始化 */ protocol_init(); /* 初始化串口 */ DEBUG_USART_Config(); /* 电机初始化 */ motor_init(); set_motor_disable(); // 停止电机 /* 初始化基本定时器,用于处理定时任务 */ TIMx_Configuration(); /* PID 参数初始化 */ PID_param_init(); /* ADC 始化 */ ADC_Init(); #if defined(PID_ASSISTANT_EN) set_computer_value(SEND_STOP_CMD, CURVES_CH1, NULL, 0); // 同步上位机的启动按钮状态 set_computer_value(SEND_TARGET_CMD, CURVES_CH1, &target_curr, 1); // 给通道 1 发送目标值 #endif while(1) { /* 接收数据处理 */ receiving_process(); /* 扫描KEY1 */ if( Key_Scan(KEY1_GPIO_PORT, KEY1_PIN) == KEY_ON) { #if defined(PID_ASSISTANT_EN) set_computer_value(SEND_START_CMD, CURVES_CH1, NULL, 0); // 同步上位机的启动按钮状态 #endif set_pid_target(target_curr); // 设置目标值 set_motor_enable(); // 使能电机 } /* 扫描KEY2 */ if( Key_Scan(KEY2_GPIO_PORT, KEY2_PIN) == KEY_ON) { set_motor_disable(); // 停止电机 #if defined(PID_ASSISTANT_EN) set_computer_value(SEND_STOP_CMD, CURVES_CH1, NULL, 0); // 同步上位机的启动按钮状态 #endif } /* 扫描KEY3 */ if( Key_Scan(KEY3_GPIO_PORT, KEY3_PIN) == KEY_ON) { /* 增大目标速度 */ target_curr += 10; if(target_curr > 120) target_curr = 120; set_pid_target(target_curr); #if defined(PID_ASSISTANT_EN) set_computer_value(SEND_TARGET_CMD, CURVES_CH1, &target_curr, 1); // 给通道 1 发送目标值 #endif } /* 扫描KEY4 */ if( Key_Scan(KEY4_GPIO_PORT, KEY4_PIN) == KEY_ON) { /* 减小目标速度 */ target_curr -= 10; if(target_curr


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭