设计任务
本文设计了一种基于智能室内温度控制的自动调速风扇。以STM32系列单片机为核心主控板,通过程序代码驱动和使用温度传感器模块实现对环境温度的实时监测,并可以实时显示环境温度。同时,可以设置温度检测的上下警告值,根据需求自行调节。
一、 本文主要研究的内容
在本设计中,将选用STM32系列单片机为主控核心板,通过程序驱动和温度传感器模块实现对周围环境温度的实时监测,并能够实时显示温度数据。同时可以对温度检测的上下限警戒值进行设置。当温度超过上限警戒值时,开启风扇,借助PWM调速法,根据环境温度与设置的温度之间的温差来调节风扇的风力,以保证周围环境温度的稳定。
二、系统的整体设计
以单片机stm32实时处理为重要技术手段,运用温度采集和数据处理的知识,使用温度传感器和减速电机等硬件协调下,系统的研究温度监控反馈处理技术。其中使用了液晶屏显示具体温度值和风扇挡位等信息,当超过预定温度值时,报警器报警并且利用pwm调速控制风扇转速。温控风扇处理系统框图如图2.1所示的,系统通过温度数据的采集、预处理、整合计算、剔除不稳定数据、实时采集、实时计算等处理方法,实现对周围温度的准确把控,完成对特定区域的实时监测和控制。
三、 元器件的选择
1、温度传感器的选择方案
可以从以下多种选项中选出一个温度传感器:
第一,选择一个热敏感的电阻器,用它来控制环境中的电流,然后用AD变换器把它变成数字信号,然后把它送到MCU上。
第二:采用热敏电阻,作为本次测试的温控传感器,将外界的温度变化传输至一台单片机,并与桥接IC、运放及AD变换等元件一起工作。
方案三:利用DS18B20型温度测量电子元件,通过将外界温度转换成数据,将其输出至单片机。
第一个办法,热敏电阻器价格低廉,也方便,不过在相对较低的温度下,感应能力不强,同时,在放大的时候,也会出现一些畸变,从而出现错误,从而使电阻器的比例不能保持直线,从而出现很大的偏差,这就需要用线路进行修正,只是会更加的繁琐和不稳定。所以,这个方法在这个体系中是行不通的。
方案二采用热敏电阻器,比热敏电偶法和电桥法更能探测到器件的温敏和非线性的错误,还可以在-50℃到1600℃之间进行测温。但是,由于线路复杂,温度敏感性达不到要求,所以没有采用该线路。
至于第三个问题,DS18B20的温度计由于高度集成,导致了极低的温度误差,再加上DS18B20和其他测温元件的原理不同,因此两者的测量精度都很高。通过将外界的温度转化为数据,可以将其转化为数据,从而大大降低了控制程序的难度,同时,它还使用了最先进的单总线技术(1 WRIE),可以让它与微处理器之间的联系更加方便,并且具有很强的抗干性。
2、DS18B20简介
DALLAS半导体继DS18B20后,推出了一种全新的集成式温度传感器,它就是DS18B20。相较于传统的热敏电阻,只能通过按照需要,经过程序的进行读写测试温度,同时也只能读写九或十二位的数码值。九位和十二位数码值分别只能在九十三点七五ms和七百五十ms范围内实现,只能通过双端口线读取和写入(单线接口)方式从DS18B20上读写信息或输入,而温度转换电源则取自于地址总线,同时DS18B20上也只能使用总线电源,不需要其他的电源即可连接。所以,使用DS18B20可以使整个系统更加的简单,也更加的安全。改善了DS18B20的温度检测精度、传递时间、传递距离、分辨率等方面,使我们应用起来更为的简单,而且最后的成绩也很理想。
3、主控芯片的选择
本设计中使用了STM32F103系列核心板,采用了软件编程的方式实现温度测量与判断,并在I/O口传递了温度控制信息。
方案一:采用AT89C51系列单片机,此单片机使用51 Core,8Bit@2MHz Max(分频后),0.06DMIPS;通过编程软件进行编程判断方式对温度传感器内部获取的控制温度信号进行编程判断,并在控制端口内部输出编程控制温度信号。
方案二:采用STM32F103系列高度集成化核心板,核心使用ARM Cortex-M3,32Bit@72MHz ,1.25DMIPS;以相同的控制软件和可编程控制方式对温度传感器内部获取的控制温度信号进行远程判断,并在控制端口内部输出远程控制温度信号。
相比方案一和方案二,STM32在运算速度和精度上均优于51。
4、显示模块的选择
方法一:通过动态扫描显示方式,用五位标准阳极通过数码管指示温度。
方法二:使用液晶显示屏LCD显示温度
针对于第一种方法,该方案具有成本低、显示温度清晰好、夜间能见度好、耗电量极低、显示驱动记录相对容易、应用广泛等特点。缺点是显示器一次有五个 LED 用于扫描。因此,尽管它会眨眼,但对人眼睛的视觉保持时限仍为二十ms。如果数码管的扫描时间比这个时候短,则可利用增加的扫描频率来消除闪光现象,让人眼完全感受不到眩光。
对于方案2,液晶显示器的优势在于显示独特的符号,不仅可以显示数字,还可以通过LED数码管显示无与伦比的符号和图形。硬件连接简单,所以系统采用了第二种方法。
5、调速方式的选择
方法一:利用DAC832进行温度控制,通过把DAC832中的环境温度数值转换成数字量,然后利用DAC832中产生一定的模拟频率信息来调节晶闸管导通角,进而完成对风扇电动机转速无级调压的手动调节及温度控制电路。
方法二:PWM(Pulse Width Modulation)的调制方法,利用数字机器人或软件系统程序完成。PWM是Pulse Width Modulation的英文简称。通过改变输入输出的脉冲频率。在PWM的驱动系统中,最常见的就是正弦波信号,因为改变PWM信息的占空比。而所谓的占空比系数就是在一个时间中,最高电压持续时间所占的空间百分比,当占空比系数达到最大值之后,利用单片机的I/O端口输入输出PWM信息主要有以下二个方法:
(1)利用软件的延时技术。在高电平延长时限到期后,使I/O口电平倒置使之变为低电平,而后再延时到规定日期;在低电平推迟时间过去后,终端的高I/O电平会倒置,这一周期之后就能够获得PWM信息了。该方法也在本设计中使用。
(2)使用计时器。控制方法和(1)一样,都是为了在该方法中使用单片机的定时器,使高低电平产生有规律的跃变,而不会被其他软件延迟。采用这种方法进行程序设计非常复杂。
针对方案一,该方法可以完成直流风扇电机的无级调压,且切换速度更细腻,但是由于D/A变换芯片售价高昂,因此相比无级调压性价比并不高。控制性能与温度的控制。
6、人体感应模块
DYP-ME003人体传感器模块,使用PIR式热释电感应器
1、具有如下特点:
(1)低功耗、静态功耗 50uA
(2)宽电压范围、DC 4.5-20V
(3)电路板小体积32*24mm
(4)可重复/不重复触发方式选择
(5)使用简单、电源+ -信号输出
三、硬件设计
四、软件设计
1、 按键中断设计
2、温度采集与显示程序设计
3、系统初始化程序
五、系统调试
通过设置自动开关按键来控制多功能温控风扇系统是否根据环境温度来运行风扇,如下对开启自动与不开启自动的两种情况进行了相关测试,具体结果如图5.3所示,自动开关能够实现它的功能且能够在屏幕中显示出来。
七、说明书与代码展示
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include <LCD1602.h>
#include "bsp_ds18b20.h"
int main()
{ int PWM,low,zhouqi;
float wendu;
int wendu1;
zhouqi=500;
low=zhouqi-PWM;
SysTick_Init();
init1602();
lcdpos(1,0);
writestring("TEM: 00.0");
GPIO_SetBits(GPIOB,GPIO_Pin_0);
while( DS18B20_Init())
{
lcdpos(0,0);
writestring(" no ds18b20 exit");
}
lcdpos(0,0);
writestring("ds18b20 exit");
for(;;)
{
DS18B20_Get_Temp(wendu);
if (wendu<0)
{ lcdpos(1,4);
writestring("-");
}
wendu1=wendu*100;
lcdpos(1,5);
write_dat(wendu1/10000+0x30);
lcdpos(1,6);
write_dat(wendu1%10000/1000+0x30);
lcdpos(1,7);
write_dat(wendu1%1000/100+0x30);
lcdpos(1,9);
write_dat(wendu1%100/10+0x30);
lcdpos(1,10);
write_dat(wendu1%10+0x30);
Delay_ms(2000);
if(wendu1>30)
{ low=500;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
}
if(wendu1<15)
{ low=0;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
}
if(wendu1>=15&wendu1<20)
{ low=100;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
if(wendu1>=20&wendu1<25)
{
low=200;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
if(wendu1>=25&wendu1<30)
{ low=300;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
}
}
附录二:DS18B20子程序
#include "bsp_ds18b20.h"
/*
* 函数名:DS18B20_GPIO_Config
* 描述 :配置DS18B20用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DS18B20_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启DS18B20_PORT的外设时钟*/
RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE);
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
}
/*
* 函数名:DS18B20_Mode_IPU
* 描述 :使DS18B20-DATA引脚变为输入模式
* 输入 :无
* 输出 :无
*/
static void DS18B20_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚模式为浮空输入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/*
* 函数名:DS18B20_Mode_Out_PP
* 描述 :使DS18B20-DATA引脚变为输出模式
* 输入 :无
* 输出 :无
*/
static void DS18B20_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚方式的通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/*
*主机给从机发送复位脉冲
*/
static void DS18B20_Rst(void)
{
/* 主机设置为推挽输出 */
DS18B20_Mode_Out_PP();
DS18B20_DATA_OUT(LOW);
/* 主机至少产生480us的低电平复位信号 */
Delay_us(750);
/* 主机在产生复位信号后,需将总线拉高 */
DS18B20_DATA_OUT(HIGH);
Delay_us(15);
}
/*
* 检测从机给主机返回的存在脉冲
* 0:成功
* 1:失败
*/
static uint8_t DS18B20_Presence(void)
{
uint8_t pulse_time = 0;
/* 主机设置为上拉输入 */
DS18B20_Mode_IPU();
while( DS18B20_DATA_IN() && pulse_time<100 )
{
pulse_time++;
Delay_us(1);
}
/ * 经过100us后,存在脉冲都还没有到来*/
if( pulse_time >=100 )
return 1;
else
pulse_time = 0;
/* 存在脉冲到来,且存在的时间不能超过240us */
while( !DS18B20_DATA_IN() && pulse_time<240 )
{
pulse_time++;
Delay_us(1);
}
if( pulse_time >=240 )
return 1;
else
return 0;
}
/*
* 从DS18B20读取一个bit
*/
static uint8_t DS18B20_Read_Bit(void)
{
uint8_t dat; /* 读0和读1的时间至少要大于60us */
DS18B20_Mode_Out_PP();
/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
DS18B20_DATA_OUT(LOW);
Delay_us(10);
/ * 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
DS18B20_Mode_IPU();
//Delay_us(2);
if( DS18B20_DATA_IN() == SET )
dat = 1;
else
dat = 0;
/* 这个延时参数请参考时序图 */
Delay_us(45);
return dat;
}
/*
* 从DS18B20读一个字节,低位先行
*/
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i, j, dat = 0;
for(i=0; i<8; i++)
{
j = DS18B20_Read_Bit();
dat = (dat) | (j<<i);
}
return dat;
}
/*
* 写一个字节到DS18B20,低位先行
*/
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t i, testb;
DS18B20_Mode_Out_PP();
for( i=0; i<8; i++ )
{
testb = dat&0x01;
dat = dat>>1;
/* 写0和写1的时间至少要大于60us */
if (testb)
{
DS18B20_DATA_OUT(LOW);
/* 1us < 这个延时 < 15us */
Delay_us(8);
DS18B20_DATA_OUT(HIGH);
Delay_us(58);
}
else
{
DS18B20_DATA_OUT(LOW);
/* 60us < Tx 0 < 120us */
Delay_us(70);
DS18B20_DATA_OUT(HIGH);
/* 1us < Trec(恢复时间) < 无穷大*/
Delay_us(2);
}
}
}
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */
}
uint8_t DS18B20_Init(void)
{
DS18B20_GPIO_Config();
DS18B20_Rst();
return DS18B20_Presence();
}
float DS18B20_Get_Temp(float f_tem)
{
uint8_t tpmsb, tplsb;
short s_tem;
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0XBE); /* 读温度值 */
tplsb = DS18B20_Read_Byte();
tpmsb = DS18B20_Read_Byte();
s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;
I f( s_tem < 0 ) /* 负温度 */
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = s_tem * 0.0625;
return f_tem;
}
目 录
有问题私聊, 微信:lwfw123456789