STM32通过PID调节混水比例调节阀开度的调试心得

本文介绍了一个真实的PID控制案例,用于保持混水中心出水温度的稳定性。详细解析了PID调节代码,包括初始化和计算函数,以及如何根据PID计算结果控制混水比例调节阀的动作,实现温度控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有关PID的理论相关的内容,网上有很多介绍很全很专业,然而看完后并不能应用于项目落地,本文描述一个真实的PID控制混水中心出水温度的案例。

关于PID控制,借用一下网上的图片:

本案例目的是混水中心输出温度基本恒定的水温,在一定误差范围内。故Setpoint为出水设定温度(该数据保留1位小数,并乘以10,按照整数形式计算);实际出水温度通过PT100采样,并经过A/D转换相关计算后得到(该数据保留1位小数,并乘以10,按照整数形式计算);执行机构是混水比例调节阀,控制方式是通过固定时间的脉冲形式,令阀向左或向右调节固定的步数,从而调节混水中心的出水温度。

PID调节的代码如下:

#ifndef __Z_UTIL_PID_H
#define __Z_UTIL_PID_H
#include "z_util_pid.h"
#endif

Obj_pid obj_pid;

void init_pid(float sv, float fv)
{
	obj_pid.set_target = sv;
	obj_pid.actual_value = fv;
	obj_pid.err = 0;
	obj_pid.err_next = 0;
	obj_pid.err_last = 0;
	obj_pid.kp = 2;
	obj_pid.ki = 2;
	obj_pid.kd = 0.2;
}

float func_pid_acting(float sv, float fv)
{
	float incr;
	obj_pid.set_target = sv;
	obj_pid.err = obj_pid.set_target - fv;
	incr = obj_pid.kp*(obj_pid.err - obj_pid.err_next) + obj_pid.ki*obj_pid.err + 
		obj_pid.kd*(obj_pid.err - 2*obj_pid.err_next + obj_pid.err_last);
	obj_pid.actual_value += incr;
	obj_pid.err_last = obj_pid.err_next;
	obj_pid.err_next = obj_pid.err;
	return incr;
}

该PID调节方式为增量型的。

在主函数中,如何使用PID的计算结果,控制阀的向左和向右的动作,是我们关心的,以及如何调节PID的系数。控制阀的向左和向右,可以这样:

pred_v = func_pid_acting(C_TARGET, temp);
//mprintf((s16)pred_v);
				
if(pred_v <= -5)
{
	if(step_cur < MIXED_VALVE_DEFAULT_STEP)
	{
		func_turn_right_steps((u8)(-pred_v/5));
		step_cur += (u8)(-pred_v/5);
	}					
}
else if(pred_v >= 5)
{
	if(step_cur > MIXED_VALVE_MIN_STEP)
	{
		func_turn_left_steps((int)pred_v/5);
		step_cur -= (int)pred_v/5;
	}					
}

通过PID计算出的增量值,与系统设计要求的误差做比较来控制向左调阀还是向右调阀。当然阀所在位置是有极限位置的。

关于PID系数的选择,P在PID调节公式中,当I和D均为0时,公式为 obj_pid.kp*(obj_pid.err - obj_pid.err_next),解释为误差的误差,当实际值下降时,该值总为负数;当实际值平稳时,该值总为0;当实际值上升时,该值为正数。

I在PID调节公式中,当P和D均为0时,公式为 obj_pid.ki*obj_pid.err,表示了当前的实际值和设定值相差有多远,值越大相差越远,值越小相差越近。

D在PID调节公式中,当P和I均为0时,公式为 obj_pid.kd*(obj_pid.err - 2*obj_pid.err_next + obj_pid.err_last), 表示了实际值的变化程度有多剧烈。当测量值稳定不变时,该值总为0;当实际值平稳上升或平稳下降时,该值总为0。当实际值逐渐快速增长时,该值总为正;当实际值逐渐快速减小时,该值总为负。

<think>好的,我现在需要帮用户找到关于STM32控制的示例代码或教程。首先,我得仔细看看用户提供的引用内容,看看有没有相关的信息。用户提到了四个引用,其中引用1是关于STM32控制数字电位器的,引用2和3是关于盲人智能饮水机的,引用4是关于智能灌溉系统的,里面提到了控制水泵和阀。 从引用4来看,智能灌溉系统使用了STM32控制水泵和阀,根据传感器数据自动调节灌溉。这可能涉及到阀的开关控制,但具体代码示例没有直接给出。不过,用户可能需要类似的GPIO控制或者PWM调节的方法。 接下来,我需要考虑用户可能的场景。控制通常涉及GPIO输出高低电平来驱动继电器或电磁阀,或者使用PWM信号来调节阀开度。比如,在智能灌溉系统中,可能通过GPIO控制电磁阀的开关,而在更复杂的系统中,可能需要PWM来控制比例阀。 用户提供的引用中没有直接的阀控制代码,但引用1中的SPI控制数字电位器和引用4中的系统设计可以作为参考。可能需要结合GPIO控制的基本方法,比如如何初始化GPIO,设置输出模式,以及如何通过定时器生成PWM信号。 另外,引用2和3提到了使用STM32F103RCT6,这个型号的MCU有丰富的定时器和GPIO资源,适合控制。用户可能需要示例代码来展示如何配置这些外设。 我需要确保回答中提到的控制方法正确,比如高低电平驱动继电器,或者PWM调节。同时,需要给出代码的结构,比如初始化GPIO,控制逻辑,并建议参考相关的项目,如引用4的智能灌溉系统,那里可能有类似的实现。 另外,用户可能对如何集成传感器(如湿度传感器)与控制的逻辑感兴趣,所以相关问题中可以提到这些方面。需要确保提供的步骤清晰,并且引导用户到具体的开源项目或教程,比如引用1和4的项目地址,或者推荐其他资源如HAL库的PWM配置教程。 总结一下,回答需要包括: 1. 控制的基本方法(GPIO和PWM) 2. 示例代码结构,如初始化、控制函数 3. 参考项目,如智能灌溉系统的设计 4. 相关扩展建议,如传感器集成、通信协议 5. 相关问题,引导进一步学习 需要确保代码示例符合用户的引用格式,比如使用代码块,并且正确标注引用来源。同时,提醒用户注意实际应用中的电路保护,如隔离和防反接,这可能在实际项目中很重要。</think>### STM32控制实现方法及示例代码 控制通常需要STM32通过GPIO输出高低电平驱动继电器/电磁阀,或使用PWM信号控制比例开度。以下是基于引用内容的实现思路和示例代码: --- #### **1. 基础GPIO控制电磁阀** 若阀为开关型电磁阀,可通过GPIO输出高低电平控制其开关: ```c // 初始化GPIO(以PA0为例) void Valve_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } // 控制开关 void Valve_Control(uint8_t state) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, (state == 1) ? GPIO_PIN_SET : GPIO_PIN_RESET); } ``` --- #### **2. PWM控制比例阀** 若需调节阀开度(如比例阀),需配置定时器输出PWM信号: ```c // 初始化TIM2_CH1(PA0)输出PWM void Valve_PWM_Init(void) { TIM_HandleTypeDef htim; htim.Instance = TIM2; htim.Init.Prescaler = 71; // 72MHz / 72 = 1MHz htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 999; // 1MHz / 1000 = 1kHz频率 HAL_TIM_PWM_Init(&htim); TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 初始占空比50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); } // 调节阀开度(0~100%) void Set_Valve_Open(uint8_t percent) { uint16_t pulse = (percent * 999) / 100; __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, pulse); } ``` --- #### **3. 参考实际项目** - **智能灌溉系统**(引用[4])中通过土壤湿度传感器触发阀控制逻辑,可参考其传感器集成与阀联动的设计[^4]。 - **数字电位器控制**(引用[1])的SPI通信方法可扩展至阀反馈信号的读取[^1]。 - **盲人饮水机设计**(引用[2])中多任务处理逻辑对复杂阀控制场景有借鉴意义[^2]。 --- #### **4. 扩展建议** - **电路保护**:添加光耦隔离和续流二极管,防止电磁阀反向电动势损坏MCU。 - **通信协议**:通过Modbus或CAN总线实现多阀协同控制。 - **库支持**:使用STM32CubeMX生成HAL库初始化代码(推荐TIM + GPIO配置)。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值