基于stc12单片机的PID恒温烙铁设计

1.设计灵感

一把普通的60W烙铁总是再焊接电路板时因为温度过高而对焊接的质量产生影响,但是如果可以用外部电路来控制烙铁的温度,就能很好的解决这个问题。

2.硬件采购

首先恒温烙铁那必须要有烙铁,我选取了60w的普通烙铁,因为便宜只要7块钱其次是这次的主控单片机stc12c5a60s2,这款单片机相较于普通单片机有更多的程序库,像PWM,ADC,也有更多的IO口,在做电路设计的时候,12单片机更为合适然后是烙铁的控制,采用固态继电器,有更高的通断频率,也可以控制交流220V电压

最后是反馈元件k型热电偶,PID的整定需要反馈元件的反馈,而k型热电偶,加上max6675热电偶温度转换芯片,非常合适作为这次的反馈原件

3.位置式PID概述

1. 位置式PID公式

在离散系统中,位置式PID的控制量输出公式为:

u(k)=Kp⋅e(k)+Ki⋅T⋅∑j=0ke(j)+Kd⋅e(k)−e(k−1)Tu(k)=Kp​⋅e(k)+Ki​⋅T⋅j=0∑k​e(j)+Kd​⋅Te(k)−e(k−1)​

  • 参数说明

    • u(k)u(k):第kk次采样时刻的控制量输出。

    • e(k)e(k):当前时刻的偏差(设定值与实际值之差)。

    • Kp,Ki,KdKp​,Ki​,Kd​:比例、积分、微分系数。

    • TT:采样时间。

    • 积分项通过累加历史偏差实现,微分项通过差分近似微分。


2. 实现特点

  • 积分项处理:需要保存历史偏差的累加和,通常通过变量累积实现,无需存储所有历史数据。

  • 微分项处理:仅需保存前一次偏差e(k−1)e(k−1)。

  • 计算复杂度:每次计算需更新积分累加值和微分项的前次偏差。


3. 优缺点分析

  • 优点

    • 直接输出绝对控制量,适用于阀门开度、温度设定等场景。

    • 无需执行机构记忆前次输出,控制逻辑直观。

  • 缺点

    • 积分饱和:持续偏差导致积分项累积,可能超出执行机构限幅,需采用抗饱和措施(如积分限幅、积分分离)。

    • 对计算误差敏感,突发干扰可能导致输出突变。


4. 参数整定与采样时间

  • 参数调整:与常规PID一致,可采用试凑法、Ziegler-Nichols法等,需注意积分项限幅。

  • 采样时间TT

    • 过大:离散化误差显著,影响控制精度。

    • 过小:计算负担增加,硬件要求高。


5. 与增量式PID对比

  • 位置式:输出绝对控制量u(k)u(k),积分项为偏差累加,易积分饱和。

  • 增量式:输出控制量变化Δu(k)=u(k)−u(k−1)Δu(k)=u(k)−u(k−1),积分效果通过偏差增量实现,抗饱和能力强,但需执行机构记忆前次输出。


6. 应用场景

  • 位置式PID:适用于需直接设定执行机构位置的场合(如伺服电机位置控制、阀门开度调节)。

  • 增量式PID:适合步进电机等需控制量变化的场景。


7. 抗积分饱和措施

  • 积分限幅:限制积分项的最大值。

  • 积分分离:偏差较大时暂停积分,避免过度累积。

  • 变速积分:根据偏差大小动态调整积分速度。


位置式PID以其直接输出绝对控制量的特性,在工业控制中广泛应用,但需合理处理积分饱和问题并结合实际场景调整参数。

其实PID就是通过比例调节,积分调节,和微分调节,来输出一个结果,再通过反馈元件来回馈一个值,然后再循环这个过程,不断的整定和调节,来达到最终的输出效果

4.硬件接线图

单片机通过PWM输出控制固态继电器,固态继电器控制烙铁是否加热,热电偶读取烙铁的温度,反馈给单片机,oled实时显示当前控制进度,不断循环这个过程,来完成这个过程

5.程序实现

1.热电偶程序库

这是基于51内核单片机的热电偶程序,可直接使用,连接后以数码管形式输出。

cpp 复制代码
#include <REGX52.H>
#include "intrins.h"			//_nop_();延时函数

#define uchar unsigned char
#define uint  unsigned int

sbit  SO  = P3^6;  				//P3.6与SO连接
sbit  SCK = P3^4; 				//P3.4与SCK连接
sbit  CS  = P3^5;  				//P3.5与CS连接

sbit wx = P2^6;
sbit dx = P2^7;

const unsigned char DevID = 1;		//本机设备ID
unsigned char buffer;			//串口接收缓冲区
unsigned char rcv_buffer[20];
unsigned char send_buffer[20];
unsigned char flag_ok = 0;		//接收完毕的标识
unsigned int MAX6675_Temp;
unsigned char Flag_connect;
unsigned char CRCH,CRCL;
unsigned char wd[2];	  		//wd[];BCD码的温度
unsigned char flag_dis;			//显示刷新的标识

unsigned char dis[4] = { 0x00, 0x00, 0x00,0x00 };
unsigned char code SMG[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

unsigned int MAX6675_ReadReg(void)
{ 
	unsigned char i;   
	unsigned int dat;
	 
	i   = 0;   
	dat = 0;   
	
	CS  = 0; 
	SCK = 0;     
	
	for(i=0; i<16; i++)		//get D15-D0 from 6675  
	{      
		SCK = 1;     
		dat = dat<<1;    
		if( SO==1 )   
			dat = dat|0x01;   
		SCK = 0;    
	} 
	CS = 1;   
	  
	return dat;   
}  
/*
* 功能;延时,若干毫秒
* 参数;毫秒数
* 返回值;无
*/
void DelayMs(unsigned int i)	//一个延时函数,这个函数再11.092Mhz下延时时间大概为1ms
{
	unsigned int j,k;

	for(j=i; j>0; j--)
		for(k=114; k>0; k--);
}
/*
* 数码管显示
*/
void SMG_DisChar(unsigned char place, unsigned char num)
{
	unsigned char i;

	i = 0x80 >> place;		

	P0 = SMG[num];	 
	dx = 1;
	dx = 0;
	
	P0 = i;	
	wx = 1;
	wx = 0;

	DelayMs(1);	
}
 
void Display(unsigned int temp)
{
	if(Flag_connect==0)		  	//Flag_connect为0,表示热电偶已经连接,这里显示温度
	{
		if(temp > 999)
		{
			SMG_DisChar(3,temp/1000);
		}
		if(temp > 99)
		{
			SMG_DisChar(2,(temp%1000)/100);
		}
		if(temp > 9)
		{
			SMG_DisChar(1,(temp/10)%10);
		}
		SMG_DisChar(0,temp%10);
	}
	else						//Flag_connect为1,表示热电偶未连接,这里显示fff
	{
		SMG_DisChar(3, 0x0F);
		SMG_DisChar(2, 0x0F);
		SMG_DisChar(1, 0x0F);
		SMG_DisChar(0, 0x0F);
		
	}
}

void main(void)
{
	unsigned char cnt = 11;
	unsigned int t;

	while(1)
	{
		t=MAX6675_ReadReg();

  		Flag_connect=t&0x04;		 	//读出数据的D2位是热电偶掉电标志位,该位为1表示掉线,该位为0表示连接
  		Flag_connect=Flag_connect>>2; 	//MAX6675是否在线

		t = t<<1;					   	//读出数据的D3-D14是温度值
		t = t>>4;
		MAX6675_Temp = t/4;				//测量单位为0.25,所以要乘0.25,(即除以4)才能得到准确的温度值
		
		for(t=0; t<200; t++)			//标识温度
		{  
			Display(MAX6675_Temp);
		}

	}
}

2.PID设定值给定

在一个函数里把一下不需要随时改变的变量赋值,方便后面的算法直接拿取使用

cpp 复制代码
void PID_Init()//PID设定值给定
{
	sv=120;/默认设定温度
	kd=3;//Dout输出
	T=200;
	Ti=2000;
	Td=600;
	PIDpwm=500;
	OUT0=5;
}

3.PID计算

对于PID的计算,这里要注意的是,Pout,Iout以及Dout都有不同的加入时段,调节这三个输出的进入时间对于PID的控制也至关重要,下面的程序是我在PID控温时采取的PID计算

cpp 复制代码
void PID_Calc()//PID计算
{
	int DelEK;
	float ti,Ki;
	float Iout;
	float Pout;
	float Dout;
	float td;
	float out;
	if(C10ms<T)
	{
		return;
	}
	if(C10ms>T)
	{
		EK=sv-pv;   //当前偏差
		Pout=kp*EK;  //比例输出
	
		if(pv<=(sv+4)&&pv>=(sv-4))
		{
			ki = 1.6;
			kp = 8;
			SEK+=EK;    //历史偏差总和
			ti=T/Ti;
			Ki=ti*ki;
			Iout=SEK*Ki*ki; //积分输出
			num3=Iout;
			out=Pout+Iout;//本次计算
			DelEK=EK-EK_1;//最近两次偏差
			td=Td/T*kd;
			Dout=DelEK*td; //微分输出
			out=Pout+Iout+Dout;//本次计算
		}
		else if(pv<=(sv+20)&&pv>=(sv-20))//设定Iout加入运算时间
		{
			if(pv<=(sv+20)&&pv>=sv)
			{
				kp = 0.5;
				ki = 0.8;
			}
			else if(pv>=(sv-20)&&pv<=sv)
			{	
				kp = 0.5;
				ki = 1.2;
			}
			SEK+=EK;    //历史偏差总和
			ti=T/Ti;
			Ki=ti*ki;
			Iout=SEK*Ki*ki; //积分输出
			num3=Iout;
			out=Pout+Iout;//本次计算
		}
		else{out = Pout;kp = 3;}//单纯的Pout输出
		num1=Dout;
		num3=Iout;
		num4=SEK;

		if(out>PIDpwm)
		{OUT=PIDpwm;}
		else if(out<0)
		{OUT=OUT0;}
		else{OUT=out;}
		num2 = out;
		EK_1=EK; //更新偏差
		C10ms=0;
	}
}

4.PWM输出

我的PWM采取的是计时器输出,通过调节输出方波脉宽,来调节实际的输出结果

cpp 复制代码
void Timer0_Init(void)
{
	TMOD &= 0xF0;
	TMOD |= 0x01;
	TL0 = 0x66;
	TH0 = 0xFC;
	TF0 = 0;
	TR0 = 1;
	ET0 = 1;
	EA = 1;
}
void TimerO(void) interrupt 1
{
	TL0 = 0x66;
	TH0 = 0xFC;
	Time1++;
	C10ms++;
	Time0++;
	if(Time0>=PIDpwm){Time0=0;}
	if(Time0>OUT){key=0;}
	else{key=1;}
}

5.oled显示

oled的显示程序比较简单 ,初始化程序用来初始化和显示一些固定的内容后面的OLED显示程序用来显示当前的加热过程,配上按钮进行人机交互

cpp 复制代码
void OLED1_Init()
{
	OLED_Init();//初始化OLED
	OLED_ColorTurn(0);
  OLED_DisplayTurn(0);
	OLED_ShowChinese(0,2,0,16);
	OLED_ShowChinese(18,2,1,16);
	OLED_ShowChinese(36,2,6,16);
	OLED_ShowChinese(54,2,3,16);
	OLED_ShowChinese(0,4,4,16);
	OLED_ShowChinese(18,4,5,16);
	OLED_ShowChinese(36,4,6,16);
	OLED_ShowChinese(54,4,7,16);
}

void OLEDshow()
{
	if(num1<=0){num1=0;}
	if(num3<=0){num3=0;}
	if(num4<=0){num4=0;}
	OLED_ShowNum(80,0,num3,5,16);
	OLED_ShowNum(0,6,num4,5,16);
	OLED_ShowNum(0,0,num1,5,16);
	OLED_ShowNum(80,6,OUT,5,16);
}

6.项目文件

链接: https://pan.baidu.com/s/1Sr8cdt3YnOtqlPE7zhhBoQ?pwd=t6qy 提取码: t6qy 复制这段内容后打开百度网盘

7.模块成果展示

模块搭建PID烙铁

8.集成电路板设计

1.原理图设计

主控依然是stc12单片机,采用220v交流电单电源供电,经过rc阻容耦合降压,在经过桥式整流,5v稳压管稳压,滤波后输出给后级电路,LED2为电源供电指示灯

2.PCB电路板

3.3D效果图

9.集成电路成果展示

集成板PID恒温烙铁

相关推荐
szxinmai主板定制专家4 小时前
基于 ZYNQ ARM+FPGA+AI YOLOV4 的电网悬垂绝缘子缺陷检测系统的研究
arm开发·人工智能·嵌入式硬件·yolo·fpga开发
光子物联单片机4 小时前
STM32G474单片机开发入门(八)内部FLASH详解及读写实战
stm32·单片机·嵌入式硬件·mcu
BreezeJuvenile4 小时前
通用定时器_输入捕获介绍及案例实操
stm32·单片机·嵌入式硬件·输入捕获·通用定时器
时空自由民.5 小时前
无人机系统耗电,低功耗管理问题解决方法(chatgpt)
单片机·嵌入式硬件·无人机
时空自由民.5 小时前
无人机系统耗电,低功耗管理问题解决方法(腾讯元宝)
单片机·嵌入式硬件·无人机
清风6666667 小时前
基于单片机的双档输出数字直流电压源设计
单片机·mongodb·毕业设计·nosql·课程设计
牛马大师兄7 小时前
STM32独立看门狗IWDG与窗口看门狗WWDG知识梳理笔记
笔记·stm32·单片机·嵌入式硬件·嵌入式·看门狗
夜月yeyue7 小时前
STM32 Flash 访问加速器详解(ART Accelerator)
linux·单片机·嵌入式硬件·uboot·bootloard
A9better7 小时前
嵌入式开发学习日志37——stm32之USART
stm32·嵌入式硬件·学习