基于串级PID的箱体自动恒温控制系统

目 录

引言 1
1 系统整体框架 2
1.1系统设计要求 2
1.2系统设计思路 2
1.3 驱动器方案介绍 3
1.3.1 PWM脉冲宽度调制原理介绍 3
1.3.2 PID自动控制算法介绍 3
1.3.3 Buck降压斩波电路介绍 5
1.3.4电流采样原理介绍 6
1.4 温度传感器介绍 8
1.5 本章小结 9
2 硬件设计 10
2.1 电源电路设计 10
2.1.1开关电源的工作特点 10
2.1.2系统电源电路 10
2.2 中央控制器电路 12
2.3 恒流源电路设计 13
2.3.1 PWM输出电路 14
2.3.2电流采样电路 15
2.3.3 Buck同步降压恒流源电路 16
2.4 传感器电路设计 17
2.4.1温度检测电路 17
2.5 按键输入电路设计 17
2.6 显示电路设计 18
2.7 本章小结 18
3 程序设计 19
3.1 整体程序设计框架 19
3.2 电流环程序设计 20
3.2.1 PWM输出程序设计 20
3.2.2 AD采样程序设计 21
3.2.3 PID电流环闭环程序设计 23
3.3 温度环程序设计 26
3.3.1 DS18B20温度传感器工作过程 26
3.3.2温度采集程序设计 27
3.3.3串级PID温度环闭环程序设计 28
3.4 OLED显示程序设计 31
3.4.1 OLED显示原理 31
3.4.2 OLED显示程序设计 32
3.5 按键输入程序设计 33
3.6 本章小结 35
4 结论 36
谢 辞 37
参考文献 38
附 录 39

1 系统整体框架
1.1 系统设计要求
设计半导体制冷片的驱动电路,恒流源供电电压24V,箱子尺寸303030立方厘米,恒温20~30℃,可调节,误差0.5℃。
1.2 系统设计思路
通过相关专业论坛、专业网站、实时新闻等查询资料以及在指导老师的悉心指导下,对半导体制冷恒温箱的设计进行总结分析,作为本次整体系统设计的思路如下:
(1) 在医药制药行业中,一些药物的医用效果需在特定的温度环境下储藏才可保持药效,病毒、疫苗等需在特定的温度下方可保持活性,为避免药物失效,病毒、疫苗失活,并且由于需求,需将此类物品转移地点时,这就需要一种能够设定恒定温度的装置进行储存移动。
(2) 在国内的外卖配送行业中,在冬季时,外卖人员在配送过程中,由于长时间未送达客户手中,食物在气候的原因下已经冷化,不适宜入口,因此在这过程中需对食物进行保温;而在夏季,食物长时间放置又会导致食物变质或是一些需要低温储藏的食物发生融化,这就必须设计一种可适应环境温度的装置以避免上述情况发生。
(3) 传统的制冷技术是通过驱动压缩机进行制冷制热进行能量的交换,但由于压缩机体积巨大,不适宜应用在微小型的装置设备中,这就有必要另寻他法,而半导体制冷片正满足这点要求,不仅体积小、重量轻,而且其驱动方式是通过控制电流来控制温度。在控制领域中,PID自动控制是一种应用领域广泛且已经得到大量工程师验证的算法,只需设计PID控制的Buck降压电流源,利用AD转换原理采集输出的电流,反馈至电流环的输入即可实现恒流源的设计,利用它驱动半导体实现制冷制热,再通过温度传感器采集箱内的温度反馈至温度环的输入,即可实现恒温箱的设计,方式简单易实现。
综上所述:本文通过将恒温箱的驱动方式、应用领域因素:buck降压电路、AD转换、电流采集、温度采集、体积重量、适应环境气候等因子通过传感器采集处理后,通过PID自动控制形成闭环控制来达到恒温效果。如图1.1所示,整个系统由一个中央控制器和多个传感器、两路半导体驱动器组成,半导体驱动器使用Buck降压电路设计成恒流源的方式实现。主控器输出PWM波控制电流源的输出电流,再通过AD转换采集电流源输出端电流,对采集的信号反馈至Buck降压电路的输入作比较,通过PID算法形成电流环驱动Buck降压电路,当期望值高于采样值时,驱动制热部分电路,反之,驱动制冷电路,将电流送至半导体制冷片,半导体制冷片与主控制器及温度传感器形成温度环,整体通过串级PID控制形成闭环控制从而达到控温效果。
基于串级PID的箱体自动恒温控制系统_第1张图片

图1.1 系统构架图
1.3 驱动器方案介绍
1.3.1 PWM脉冲宽度调制原理介绍
脉冲宽度调制(PWM),就是对方波的高电平时间进行配置,从而得到需要的脉冲宽度信号(包括幅度以及波形形状),以达到利用微处理器输出的数字信号对模拟电路进行控制的一种非常有效的方法,应用于多种领域:测量领域、变换领域、通信领域与功率控制领域等多种领域中。如要实现调制频率只要更改脉冲序列的频率,实现调制电压只要更改脉冲的高电平宽度从而做到改变信号的占空比,即电压与频率做出更改是通过处理脉冲的相应参数实现。因此修改脉冲的频率、脉冲的占空比而达到控制输出幅度的目的。
对模拟信号量以数字方式编码是脉冲宽度调制(PWM)的基本原理。在工作的任意瞬间,满幅状态的直流供电只有两种状态,全部供电或者全部不供电,那么这样的信号即PWM信号。实际上它依旧是数字信号,本文转载自http://www.biyezuopin.vip/onews.asp?id=15140其实也就是方波。所以加到模拟负载上的电流或电压源实际上是一种全部供电或全部不供电的周期性脉冲序列。全部不供电的时候是将供电断开,全部供电的时候是将直流供电全部施加到负载上[1]。对一个实际模拟信号的电平进行数字方式调节编码实际上就是通过将方波的占空比进行计数,这就是脉冲宽度调制。因此,当带宽足够,所有的模拟量都是能够应用PWM进行编码。

程序部分
PID.C文件
void TempCurr_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
//	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    
	//设置该引脚为复用输出功能,输出TIM3CH1 TIM3CH2的PWM脉冲波形GPIOA.6  GPIOA.7
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //TIM3_CH1,TIM3_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //使能指定的TIM3中断,允许更新中断
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	//初始化TIM3 Channel1 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC1
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的预装载寄存器
	//初始化TIM3 Channel2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性低
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	TIM_SetCompare1(TIM3, 300);	//Current1
	TIM_SetCompare2(TIM3, 300);	//Current2
}
u32 sam_time = 0;
u8 sam_time5 = 0;
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
	{
		sam_time++;
		if(sam_time%8000 == 0)//200ms
		{
			sec_flag = 1;
		}
		if(sam_time%40000 == 0)//1s
		{
			dis_flag = 1;
		}
		if(sam_time >= 40000){
			sam_time5++;
			if(sam_time5 >= 19){
				sam_time5 = 0;
				TempLoop();
			}
			sam_time = 0;
		}
		CurrLoop();	//电流环
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源 
	}
}
/* 电流环,内环 */
_iq PIDCurrentNow1 = _IQ(0);
_iq PIDCurrentNow2 = _IQ(0);
void CurrLoop(void)
{
	/********CurrentColdPID1处理**********/
	GetCurrVa1 = _IQdiv(_IQ(GET_CRURR1_V), _IQ(806.78));
	PIDCurrentNow1 = (IncPID_Calc(&CurrentColdPID1, GetCurrVa1));	 //计算增量并累加 
	if((CurrentColdPID1.SumErr < 0) && (PIDCurrentNow1 < 0))
	{
		if((PIDCurrentNow1 + CurrentColdPID1.SumErr) <= _IQ(-5))
		{
			CurrentColdPID1.SumErr = _IQ(-5);
		}else
		{
			CurrentColdPID1.SumErr += PIDCurrentNow1;
		}
	}
	else if((CurrentColdPID1.SumErr > 0) && (PIDCurrentNow1 > 0))
	{
		if((PIDCurrentNow1 + CurrentColdPID1.SumErr) >= _IQ(1800))
		{
			CurrentColdPID1.SumErr = _IQ(1800);
		}else
		{
			CurrentColdPID1.SumErr += PIDCurrentNow1;
		}
	}else
	{
		CurrentColdPID1.SumErr += PIDCurrentNow1;
	}
	CurrPWM1 = _IQsat(CurrentColdPID1.SumErr, _IQ(1620), _IQ(0));//限幅
	/********CurrentHotPID2处理**********/
	GetCurrVa2 = _IQdiv(_IQ(GET_CRURR2_V), _IQ(806.78));
	PIDCurrentNow2 = (IncPID_Calc(&CurrentHotPID2, GetCurrVa2));	 //计算增量并累加 
	if((CurrentHotPID2.SumErr < 0) && (PIDCurrentNow2 < 0))
	{
		if((PIDCurrentNow2 + CurrentHotPID2.SumErr) <= _IQ(-5))
		{
			CurrentHotPID2.SumErr = _IQ(-5);
		}else
		{
			CurrentHotPID2.SumErr += PIDCurrentNow2;
		}
	}
	else if((CurrentHotPID2.SumErr > 0) && (PIDCurrentNow2 > 0))
	{
		if((PIDCurrentNow2 + CurrentHotPID2.SumErr) >= _IQ(1800))
		{
			CurrentHotPID2.SumErr = _IQ(1800);
		}else
		{
			CurrentHotPID2.SumErr += PIDCurrentNow2;
		}
	}else
	{
		CurrentHotPID2.SumErr += PIDCurrentNow2;
	}
	CurrPWM2 = _IQsat(CurrentHotPID2.SumErr, _IQ(1620), _IQ(0));//限幅
	TIM_SetCompare2(TIM3, _IQint(CurrPWM2));	//Current2 PA7
	TIM_SetCompare1(TIM3, _IQint(CurrPWM1));	//Current2 PA6
}
_iq PIDTempErrNow = _IQ(0);
_iq PIDTempErrNow2 = _IQ(0);
_iq TempIerr = _IQ(0);
void TempLoop(void)
{
	TempIerr = TempPID.SetPoint-iq_GetTempAve;
	if(_IQabs(TempIerr) > _IQ(2.0)){
		if(TempIerr > _IQ(2.0))
		{
			PID_SetPoint(&CurrentHotPID2, MIN_CRURR);
			PID_SetPoint(&CurrentColdPID1, MAX_CRURR);
			
			MortorPWM1 = _IQmpy(TempIerr, _IQ(1000));
			MortorPWM1 = _IQsat(MortorPWM1, _IQ(900), _IQ(0));//限幅
			TIM_SetCompare2(TIM2, _IQint(MortorPWM1));	//motor PA1
			TIM_SetCompare3(TIM2, 0);	//motor PA2
		}else if(TempIerr < _IQ(-2.0))
		{
			PID_SetPoint(&CurrentHotPID2, MAX_CRURR);
			PID_SetPoint(&CurrentColdPID1, MIN_CRURR);
			TIM_SetCompare2(TIM2, 0);	//motor PA1
			MortorPWM2 = _IQmpy(-TempIerr, _IQ(1000));
			MortorPWM2 = _IQsat(MortorPWM2, _IQ(1799), _IQ(0));//限幅
			TIM_SetCompare3(TIM2, _IQint(MortorPWM2));	//motor PA2
		}
	}else{
		/********TempPID处理**********/
		PIDTempErrNow = (IncPID_Calc(&TempPID, iq_GetTempAve));	 //计算增量并累加 
	//	PIDTempErrNow2 = -PIDTempErrNow;
		if((TempPID.SumErr < 0) && (PIDTempErrNow < 0))
		{
			if((PIDTempErrNow + TempPID.SumErr) <= _IQ(-3))
			{
				TempPID.SumErr = _IQ(-5);
			}
			else
			{
				TempPID.SumErr += PIDTempErrNow;
			}
		}
		else if((TempPID.SumErr > 0) && (PIDTempErrNow > 0))
		{
			if((PIDTempErrNow + TempPID.SumErr) >= _IQ(5))
			{
				TempPID.SumErr = _IQ(5);
			}
			else
			{
				TempPID.SumErr += PIDTempErrNow;
			}
		}
		else
		{
			TempPID.SumErr += PIDTempErrNow;
		}
		iq_PIDTempOut = _IQmpy(TempPID.SumErr, _IQ(0.5)) + _IQ(1.0);
		iq_PIDTempOut = _IQsat(iq_PIDTempOut, MAX_CRURR, MIN_CRURR);//限幅
		PID_SetPoint(&CurrentColdPID1, iq_PIDTempOut);
		iq_PIDTempOut2 = _IQmpy(-TempPID.SumErr, _IQ(0.5)) + _IQ(1.5);
		iq_PIDTempOut2 = _IQsat(iq_PIDTempOut2, MAX_CRURR, MIN_CRURR);//限幅
		PID_SetPoint(&CurrentHotPID2, iq_PIDTempOut2);
		MortorPWM1 = _IQmpy(iq_PIDTempOut, _IQ(150));
		MortorPWM1 = _IQsat(MortorPWM1, _IQ(900), _IQ(0));//限幅
		TIM_SetCompare2(TIM2, _IQint(MortorPWM1));	//motor PA1
		MortorPWM2 = _IQmpy(iq_PIDTempOut2, _IQ(800));
		MortorPWM2 = _IQsat(MortorPWM2, _IQ(1799), _IQ(0));//限幅
		TIM_SetCompare3(TIM2, _IQint(MortorPWM2));	//motor PA2
	}
}
void PIDInit(void)
{
	
	CurrentPID_Init();
	TempPID_Init();
	Mot_PWM_Init(1800-1, 400-1);	//400分频180kHz,PWM 1800计数周期,定时器溢出频率100Hz
	TempCurr_PWM_Init(1800-1, 0);	//72MHz不分频,PWM 1800计数周期,定时器溢出频率40kHz
}
void PID_SetPoint(PIDtypedef *PIDx, _iq SetValue)
{
	PIDx->SetPoint = SetValue;
}
/* 增量式PID */
_iq IncPID_Calc(PIDtypedef *PIDx, _iq NextPoint)
{
	_iq IErr, IincPID;
		IErr = PIDx->SetPoint - NextPoint;  //当前误差
	/* 形式二:△u(k) = Kp[e(n)-e(n-1)] + Ki*e(n) + Kd[e(n)-2e(n-1)+e(n-2)] */
	//增量计算
	IincPID = \
				_IQmpy(PIDx->Proportion, IErr - PIDx->LastErr) + \
				_IQmpy(PIDx->Integral, IErr) + \
				_IQmpy(PIDx->Derivative, IErr - PIDx->LastErr - PIDx->LastErr + PIDx->PrevErr);

	PIDx->PrevErr = PIDx->LastErr; //存储误差,便于下次计算
	PIDx->LastErr = IErr;
	return(IincPID);
}
/* 设定PID  kp ki kd三个参数 */
void PID_SetCoefficient(PIDtypedef *PIDx, _iq Kp, _iq Ki, _iq Kd)
{
	PIDx->Proportion = Kp;//比例系数
	PIDx->Integral = Ki;//积分系数
	PIDx->Derivative = Kd;//微分系数
}

基于串级PID的箱体自动恒温控制系统_第2张图片
基于串级PID的箱体自动恒温控制系统_第3张图片
基于串级PID的箱体自动恒温控制系统_第4张图片
基于串级PID的箱体自动恒温控制系统_第5张图片
基于串级PID的箱体自动恒温控制系统_第6张图片
基于串级PID的箱体自动恒温控制系统_第7张图片
基于串级PID的箱体自动恒温控制系统_第8张图片

你可能感兴趣的:(串级PID,箱体自动恒温,恒温控制系统,电路图,毕业论文)