基于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恒温烙铁

相关推荐
清风6666665 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm6 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu10 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客10 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭11 小时前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽11 小时前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊13 小时前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头13 小时前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭13 小时前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗13 小时前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件