【毕业设计】基于stm32的智能水杯 您所在的位置:网站首页 水杯设计图纸大全 【毕业设计】基于stm32的智能水杯

【毕业设计】基于stm32的智能水杯

2024-02-03 06:12| 来源: 网络整理| 查看: 265

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

0 简介

Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目

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

大家可用于 课程设计 或 毕业设计

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052

1 项目介绍

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

2 系统设计

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

系统设计

在这里插入图片描述

3 恒温控制实现

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

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

3.1 功能描述

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

在这里插入图片描述

3.2 PID算法原理

在这里插入图片描述

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] 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|=8 //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 != '\0') { 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.OUT=pid.pwmcycle; } else if(out 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]='\0'; 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 实现效果

在这里插入图片描述

在这里插入图片描述

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052

5 最后


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有