【毕业设计】stm32智能水杯设计与实现(恒温控制) – 单片机 物联网 嵌入式

首页 » 物联网 » 【毕业设计】stm32智能水杯设计与实现(恒温控制) – 单片机 物联网 嵌入式

文章目录

  • 0 简介
  • 1 项目介绍
  • 2 系统设计
  • 3 恒温控制实现
    • 3.1 功能描述
    • 3.2 PID算法原理
      • 3.2.1 P:比例
      • 3.2.2 I:积分
      • 3.2.3 D:微分
    • 3.3 温控代码实现
  • 4 实现效果

0 简介

🔥 Hi,大家好,这里是丹成学长的毕设系列文章!

🔥 对毕设有任何疑问都可以问学长哦!

这两年开始,各个学校对毕设的要求越来越高,难度也越来越大… 毕业设计耗费时间,耗费精力,甚至有些题目即使是专业的老师或者硕士生也需要很长时间,所以一旦发现问题,一定要提前准备,避免到后面措手不及,草草了事。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的新项目是

🚩 基于stm32的智能水杯 – 恒温控制

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

🧿 选题指导, 项目分享:

https://blog.csdn.net/molodi/article/details/125933857

1 项目介绍

今天向大家介绍学长设计的一个毕设项目,基于STM32单片机控制的智能水杯,可利用插口式电源或无线充电底座为加热器提供能量,并在达到某种饮品所需温度时进行保温。 水杯内置充电电池,可选用 USB 接口或无线充电。 在水杯内部设置无线模块,用户利用上位机与水杯进行匹配进行加热操作,加热完后水杯会通过上位机和液晶显示屏实时反馈液体温度,通过指示灯显示电量情况等,给用户进行提醒。

2 系统设计

该智能水杯控制系统是由 STM32 单片机作为主要控制芯片,接受和发送信号给温度传感器,进行温度检测;温度检测是由温度传感器来执行,实时采集水杯内液体温度并利用 LCD 屏显示; 电池检测由电池电压指示电路进行操控, 实时检测电池电量, 并通过 LED 灯进行提示;内置充电电池充电可提供无线和 USB接口充电方式;控温及发热系统由 PTC 发热体构成, 并利用闭环控制使水杯液体温度恒温;利用无线模块,接收来自手机App所发出的指令, 通过手机App与水杯进行匹配进行加热操作,并反馈水杯的使用状态

系统设计

【毕业设计】stm32智能水杯设计与实现(恒温控制) - 单片机 物联网 嵌入式

3 恒温控制实现

智能水杯的核心功能是水温的恒温控制,为了实现这一点,学长选用了以下元器件

stm32f103核心板、L298N模块(当然用MOS管更好)、led一个、NPN三极管一个、蜂鸣器一个、DHT11一个、LCD1602一个、电阻200欧两个、可调电阻10K一个、加热丝一个

3.1 功能描述

用DHT11检测当前环境温湿度,并将数据显示在LCD1602上,在用设定温度与当前温度相减,通过PID算法计算出当前输出脉宽,并将其加在L298N模块中,使加热丝发热,形成一个闭环,经过一段时间温度稳定在设定值。

【毕业设计】stm32智能水杯设计与实现(恒温控制) - 单片机 物联网 嵌入式

3.2 PID算法原理

【毕业设计】stm32智能水杯设计与实现(恒温控制) - 单片机 物联网 嵌入式

3.2.1 P:比例

成比例地反映控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用,以减小偏差。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
P参数越小比例作用越强,动态响应越快,消除误差的能力越强。通常将P参数由大向小调,以能达到最快响应又无超调(或无大的超调)为最佳参数。

3.2.2 I:积分

为消除静差,提高系统的无差度。积分作用的强弱取决于积分时间常数T,T越大,积分作用越弱,反之则越强。

3.2.3 D:微分

反映偏差信号的变化趋势,并能在偏差信号变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间。在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。
D越大,微分作用越强,D越小,微分作用越弱。系统调试时通常把D从小往大调,具体参数由试验决定。

3.3 温控代码实现

LedAndBeep.h

#ifndef _LEDANDBEEP_H
#define _LEDANDBEEP_H

#include "sys.h"
#include "DHT11.h"


#define led_1 GPIO_SetBits(GPIOB,GPIO_Pin_0)
#define led_0 GPIO_ResetBits(GPIOB,GPIO_Pin_0)

#define beep_1 GPIO_SetBits(GPIOB,GPIO_Pin_1)
#define beep_0 GPIO_ResetBits(GPIOB,GPIO_Pin_1)

void GPIO_init_Alert(void);
void Delay_ms(int k);
void Alert(void);

#endif

LedAndBeep.c

#include "LedAndBeep.h"
#include "PID.h"

void GPIO_init_Alert()
{
	GPIO_InitTypeDef Alert_GPIO;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	Alert_GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
	Alert_GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	Alert_GPIO.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &Alert_GPIO);
	
	led_0;
	beep_0;
}


void Alert()
{
	if((DHT_Data[0]>70)||(DHT_Data[0]==70)||(DHT_Data[0]45)||(DHT_Data[0]==45))//湿度不在45~70之间就报警
	{
		  led_1;
		  if(pid.C10ms(pid.T/2))//pid.C10ms在中断函数中,蜂鸣器响的时间小于250ms
				beep_1;
			else
				beep_0;
	}
	else
	{
		  led_0;
		  beep_0;
	}
}

DHT11.h

#ifndef __DHT11_H
#define __DHT11_H 
#include "sys.h"   

extern char DHT_Data[5];
 
//IO方向设置
#define DHT11_IO_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=812;}
#define DHT11_IO_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=312;}
IO操作函数											   
#define	DHT11_DQ_OUT PBout(11) //数据端口	PB11输出
#define	DHT11_DQ_IN  PBin(11)  //数据端口	PB11输入


u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(void);//读取温湿度
u8 DHT11_Read_Byte(void);//读出一个字节
u8 DHT11_Read_Bit(void);//读出一个位
u8 DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11    
#endif


LCD1602.h

#ifndef LCD1602_H
#define LCD1602_H

#include "sys.h"

#define RS GPIO_Pin_8	//设置PB8为RS
#define RW GPIO_Pin_6	//PB6为RW
#define EN GPIO_Pin_7	//PB7为EN使能

void ReadBusy(void);
void LCD_WRITE_CMD( char CMD );
void LCD_WRITE_StrDATA( char *StrData, char row, char col );
void LCD_WRITE_ByteDATA( char ByteData );
void LCD_INIT(void);
void GPIO_INIT(void);

#endif

LCD1602.c

#include "LCD1602.h"
#include "delay.h"
void GPIO_INIT(void)
{		//GPIO初始化
GPIO_InitTypeDef GPIO;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	//禁用jtag
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE );
GPIO.GPIO_Pin = EN|RW|RS;
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO);
GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO);
}
void LCD_INIT(void)
{	//初始化
GPIO_INIT();		
GPIO_Write(GPIOA, 0x0000);		
GPIO_Write(GPIOB, 0x0000);
delay_us(500);	
LCD_WRITE_CMD(0x38);
LCD_WRITE_CMD(0x0d);	//开启光标和闪烁
LCD_WRITE_CMD(0x06);
LCD_WRITE_CMD(0x01);
}
void LCD_WRITE_CMD(char CMD)
{
//写入命令函数
ReadBusy();
GPIO_ResetBits(GPIOB, RS);
GPIO_ResetBits(GPIOB, RW);
GPIO_ResetBits(GPIOB, EN);
GPIO_Write(GPIOA, CMD);		//
GPIO_SetBits(GPIOB, EN);
GPIO_ResetBits(GPIOB, EN);
}
void LCD_WRITE_ByteDATA(char ByteData )
{	//写入单个Byte函数
ReadBusy();
GPIO_SetBits(GPIOB, RS);
GPIO_ResetBits(GPIOB, RW);
GPIO_ResetBits(GPIOB, EN);
GPIO_Write(GPIOA, ByteData);
GPIO_SetBits(GPIOB, EN);
GPIO_ResetBits(GPIOB, EN);
}
void LCD_WRITE_StrDATA(char *StrData,char row, char col)
{//写入字符串
char baseAddr = 0x00;			//定义256位地址
if (row)
{
baseAddr = 0xc0;
}
else
{
baseAddr = 0x80;																				   
} 	
baseAddr += col;
while (*StrData != ' ')
{
LCD_WRITE_CMD( baseAddr );
LCD_WRITE_ByteDATA( *StrData);	
baseAddr++;			  
StrData++;
}
}
void ReadBusy(void)
{		//读忙函数,读忙之前记得更改引脚的工作方式!!!因为STM32的IO不是准双向IO
GPIO_InitTypeDef GPIO;
GPIO_Write(GPIOA, 0x00ff);	
GPIO.GPIO_Pin = GPIO_Pin_7;		//选定GPIOA的第七Pin
GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//第七Pin的工作方式为浮空输入模式,用于检测LCD1602的忙状态
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO);
GPIO_ResetBits(GPIOB, RS);//RS拉低
GPIO_SetBits(GPIOB, RW);//RW拉高
GPIO_SetBits(GPIOB, EN);	//使能开
while( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7 ));	//读第七Pin状态,如果一直为1则循环等待
GPIO_ResetBits(GPIOB, EN);//使能关
GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;		//使GPIOA的状态还原成推挽模式
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO);
}

PID.h

#ifndef PID_H_
#define PID_H_
typedef struct Pid
{
float Sv;//用户设定值
float Pv;
float Kp;
int T;  //PID计算周期--采样周期
float Ti;
float Td; 
float Ek;  //本次偏差
float Ek_1;//上次偏差
float SEk; //历史偏差之和
float Iout;
float Pout;
float Dout;
float OUT0;
float OUT;
int C1ms;
int pwmcycle;//pwm周期
int times;
}PID;
extern PID pid;
void PID_Init(void);
void PID_Calc(void);
#endif

PID.c

#include "PID.h"
PID pid;
void PID_Init()
{
pid.Sv=38;//用户设定温度
pid.Kp=30;
pid.T=400;//PID计算周期
pid.Ti=4000000;//积分时间
pid.Td=1000;//微分时间
pid.pwmcycle=200;//pwm周期200
pid.OUT0=1;
pid.C1ms=0;
}
void PID_Calc()  //pid计算
{
float DelEk;
float ti,ki;
float td;
float kd;
float out;
if(pid.C1ms(pid.T))  //计算周期未到
{
return ;
}
pid.Ek=pid.Sv-pid.Pv;   //得到当前的偏差值
pid.Pout=pid.Kp*pid.Ek;      //比例输出
pid.SEk+=pid.Ek;        //历史偏差总和
DelEk=pid.Ek-pid.Ek_1;  //最近两次偏差之差
ti=pid.T/pid.Ti;
ki=ti*pid.Kp;
pid.Iout=ki*pid.SEk;  //积分输出
td=pid.Td/pid.T;
kd=pid.Kp*td;
pid.Dout=kd*DelEk;    //微分输出
out= pid.Pout+ pid.Iout+ pid.Dout;
if(out>pid.pwmcycle)
{
pid.OUT=pid.pwmcycle;
}
else if(out0)
{
pid.OUT=pid.OUT0; 
}
else 
{
pid.OUT=out;
}
pid.Ek_1=pid.Ek;  //更新偏差
pid.C1ms=0;
}

main.c

#include "LCD1602.h"
#include "DHT11.h"
#include "LedAndBeep.h"
#include "PID.h"
#include "PWMOUT.h"
#include "delay.h"
#include 
#include 
#define PERIOD    400
#define PRESCALER 36000
void Situation()
{
char hum[5]={0},temp[5]={0},PWM[10]={0},arr[5]={0x20,0x20,0x20,0x20,0x20};
sprintf(hum,"%d.%d",DHT_Data[0],DHT_Data[1]);
sprintf(temp,"%d.%d",DHT_Data[2],DHT_Data[3]);
//显示湿度
LCD_WRITE_StrDATA( hum,0,5 ); 	
LCD_WRITE_StrDATA("%",0,9 ); 
//显示温度
LCD_WRITE_StrDATA( temp,0,11); 
LCD_WRITE_StrDATA("C",0,15 );
//显示pid.out
LCD_WRITE_StrDATA("pid.out:",1,0);	
sprintf(PWM,"%f",pid.OUT);
PWM[6]=' ';
LCD_WRITE_StrDATA(PWM,1,9);		
}
int main() 
{
unsigned int num=0;
GPIO_init_Alert();
Time_init();
DHT11_Init();
PID_Init();
LCD_INIT();	
LCD_WRITE_CMD( 0x80 );				
LCD_WRITE_CMD(0x0C);	
LCD_WRITE_StrDATA( "situ:",0,0 );	
TimePwm_init(PERIOD-1,PRESCALER);
while(1)
{
while(DHT11_Read_Data());
PID_Calc();
num=(((pid.OUT*PERIOD)/pid.pwmcycle)-1);
TIM_SetCompare2(TIM3,num);
Situation();                                                                                                                                                                                   
}       
}

4 实现效果

【毕业设计】stm32智能水杯设计与实现(恒温控制) - 单片机 物联网 嵌入式

【毕业设计】stm32智能水杯设计与实现(恒温控制) - 单片机 物联网 嵌入式

🧿 选题指导, 项目分享:

https://blog.csdn.net/molodi/article/details/125933857

本文章来源于互联网,如有侵权,请联系删除!原文地址:【毕业设计】stm32智能水杯设计与实现(恒温控制) – 单片机 物联网 嵌入式

相关推荐: Java毕设项目酒店物联网平台系统(java+VUE+Mybatis+Maven+Mysql)

 Java毕设项目酒店物联网平台系统(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ I…