【STM32/HAL】嵌入式课程设计:简单的温室环境监测系统|DS18B20 、DHT11

news2024/11/13 9:33:23

前言  

  板子上的外设有限,加上想法也很局限,就用几个传感器实现了非常简单的监测,显示和效应也没用太复杂的效果。虽说很简单,但传感器驱动还是琢磨了不久,加上串口线坏了,调试了半天才发现不是代码错了而是线有问题,总而言之,课设不复杂,难度不高,凑合看吧。

电路图

系统的需求描述

温室环境监测系统的功能性需求描述如下:

1.光照监测与响应

系统对光敏电阻进行 AD 采样获取环境光照强度。当环境光照减弱至预设阈值以下时, 系统会自动点亮绿灯以提供照明。同时,LED 灯闪烁报警,蜂鸣器需发出报警声。

2.温度监测与响应

系统通过 DS18B20 数字温度传感器和 DHT11 数字湿温度传感器获取温室环境温度, 以两者平均值作为测量的温度。当温度低于预设的下限阈值时,系统自动启动加热装置进行 加热(开发板并无加热设备,这里使用点亮红灯来模拟),直到温度上升至正常水平。当温 度高于预设的上限阈值时,系统需驱动电机旋转(风扇)以进行散热。并且,温度异常(过 高或过低)时,LED 灯闪烁报警,蜂鸣器需发出报警声。

3.湿度监测与响应

系统通过 DHT11 数字湿温度传感器获取环境湿度。当湿度超出预设的正常范围时, LED 灯闪烁报警,蜂鸣器需发出报警声。湿度太高时,还会亮起蓝灯。湿度太低时,会驱动 电机模拟启动灌溉设备。

4.数据显示

LCD 屏幕会实时显示光照、温度和湿度的数据信息。显示要做到清楚、直观,更新频率 适中。

5.串口通信

上位机和系统能通过串口进行通信,系统能够将光照、温度和湿度的采样数据实时发送 给上位机,上位机可以将数据存储到本地文件或上传到云服务器,实现了环境数据的采集、 传输、存储,可以为后续大数据处理提供数据支持。数据传输需稳定可靠,数据格式要遵守 通信协议。

6.按键控制

管理员可以通过按键开关报警功能和手动开关全彩灯。按键操作简单直观,响应时间快, 如果系统自动化调整功能失效,还可以通过手动方式调整设备。 

结构图

 详细设计

只说明传感器的部分

DS18B20 模块:

用于环境温度的数据采集。

DS18B20 是常用的数字温度传感器,单总线结构。该传感器体积小、硬件开销低、抗干扰能力强、误差小。一般在启动传感器并与之通信前,需要先经过 ROM 检测,但是开发板上只挂载了一个 DS18B20 设备,可以在初始化总线之后直接发送 0xcc 跳过 ROM 检查。使用 Convert T 开始温度转化命令(0x44)开始温度转化之后,经过一定时间,DS18B20 会将温度转化之后的数据存储到暂存器内。通过 Read Scratchpad 读取命令(0xBE) 可以从暂存器读数据。只采集温度数据所以只用接受前两个字节,高八位的高五位是符号位,高八位的低三位和低八位的高四位表示温度的整数位,低八位的低四位表示小数位。在本系统中温度数据保留一位小数。该模块对应文件为"ds18b20.h"和"ds18b20.c"。

相关的讲解可看(这两篇文章并不是使用的stm32,主要看模块的时序):

蓝桥杯电子类单片机学习二——DS18B20温度传感器(onewire驱动)_蓝桥杯板子用ds18b20-CSDN博客

51单片机-18B20温度传感器-CSDN博客

 参考代码:

适配stm32板子 、hal库

#include "ds18b20.h"
#include "tim.h"


void DS18B20_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.Pin = GPIO_PIN_2;
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
}

void DS18B20_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_2;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
}

void DS18B20_Rst(void)
{
	DS18B20_IO_OUT();
	DS18B20_DQ_OUT_LOW;
	delay_us_by_Tim(750);
	DS18B20_DQ_OUT_HIGH;
	delay_us_by_Tim(15);
}
	
uint8_t DS18B20_Check(void)
{
	uint8_t retry = 0;
	DS18B20_IO_IN();
	while(DS18B20_DQ_IN && retry < 200)
	{
		retry++;
		delay_us_by_Tim(1);
	}
	
	if(retry >= 200)
		return 1;
	else
		retry = 0;
	
	while(!DS18B20_DQ_IN && retry < 240)
	{
		retry++;
		delay_us_by_Tim(1);
	}
	
	if(retry >= 240)
		return 1;
	
	return 0;
}

uint8_t DS18B20_Read_Bit(void)
{
	uint8_t data;
	DS18B20_IO_OUT();
	DS18B20_DQ_OUT_LOW;
	delay_us_by_Tim(2);
	DS18B20_DQ_OUT_HIGH;
	DS18B20_IO_IN();
	delay_us_by_Tim(12);
	
	if(DS18B20_DQ_IN)
		data = 1;
	else
		data = 0;
	
	delay_us_by_Tim(50);
	return data;
}

uint8_t DS18B20_Read_Byte(void)
{
	uint8_t i,j,data;
	data = 0;
	for(i=1;i<=8;i++)
	{
		j = DS18B20_Read_Bit();
		data = (j<<7)|(data>>1);
	}
	return data;
}

void DS18B20_Write_Byte(uint8_t data)
{
	uint8_t j;
	uint8_t testb;
	DS18B20_IO_OUT();
	for(j=1;j<=8;j++)
	{
		testb=data&0x01;
		data=data>>1;
		if(testb)
		{
			DS18B20_DQ_OUT_LOW;
			delay_us_by_Tim(2);
			DS18B20_DQ_OUT_HIGH;
			delay_us_by_Tim(60);
		}
		else
		{
			DS18B20_DQ_OUT_LOW;
			delay_us_by_Tim(60);
			DS18B20_DQ_OUT_HIGH;
			delay_us_by_Tim(2);
		}
	}
}

void DS18B20_Start(void)
{
	DS18B20_Rst();
	DS18B20_Check();
	DS18B20_Write_Byte(0xcc);
	DS18B20_Write_Byte(0x44);
}

uint8_t DS18B20_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_2;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
	
	DS18B20_Rst();
	return DS18B20_Check();
}

short DS18B20_Get_Temperature(void)
{
	//uint8_t temp;
	uint8_t TL,TH;
	short temperature;
	
	DS18B20_Start();
	DS18B20_Rst();
	DS18B20_Check();
	DS18B20_Write_Byte(0xcc);
	DS18B20_Write_Byte(0xbe);
	TL = DS18B20_Read_Byte();
	TH = DS18B20_Read_Byte();
	
	if(TH>7)
	{
		TH = ~TH;
		TL = ~TL;
	//	temp = 0;
	}
//	else
//		temp = 1;
	
	temperature = TH;
	temperature <<= 8;
	temperature += TL;
	temperature = (float)temperature*0.625;//0.0625*10,保留小数一位,后面处理的时候要除以10
	
	if(temperature)
		return temperature;
	else
		return -temperature;
}

DHT11 模块:

用于环境温度和湿度的数据采集。

DHT11 数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。一次完整的数据传输为 40bit,高位先出,数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,校验和数据为前四个字节相加。

DHT11 传输时序为:总线空闲状态为高电平,主机把总线拉低等待 DHT11 响应(总线拉低必须大于 18 毫秒,保证 DHT11 能检测到起始信号),主机发送开始信号结束后,延时等待 20-40us,DHT11 接收到主机的开始信号后,等待主机开始信号结束,然后发送 80us(一般存在误差,20-100us 都可以认为是正常响应时间)低电平响应信号。如果读取总线为低电平,说明 DHT11 发送响应信号,如果读取总线为高电平,则 DHT11 没有响应。DHT11 发送响应信号后,再把总线拉高,准备发送数据,每 1bit 数据都以 50us 低电平时隙开始,告诉主机开始传输一位数据了。当 50us 低电平时隙过后拉高总线,高电平持续 26~28us 表示数据“0”;持续 70us 表示数据“1”。由于存在误差,程序中在延时 40us 后检测总线状态,为高说明该位数据为“1”,为低说明该位数据为“0”。当最后 1bit 数据传送完毕后,

DHT11 拉低总线 50us,表示数据传输完毕,随后总线由上拉电阻拉高进入空闲状态。该模块对应文件为"dht11.h"和"dht11.c"。

该模块可从下面博客移植:

HAL库:

STM32F103ZET6——DHT11温湿度传感器(hal库)_dht11stm32f103-CSDN博客

 标准库(主要参考其的时序讲解):

DHT11详细介绍(内含51和STM32代码)-CSDN博客

基于STM32的温湿度传感器(DHT11)+OLED屏显示(超详细)_stm32控制dht11-CSDN博客

参考代码

(注意这里的延时函数命名成了delay_us_by_Tim()): 

#include "dht11.h"
#include "tim.h"
 
void DHT11_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.Pin = GPIO_PIN_3;
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
}
 
void DHT11_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_3;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
}
 
 
//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//设置为输出
	DHT11_DQ_OUT_LOW; 	//拉低DQ
	HAL_Delay(20);    	//拉低至少18ms
	DHT11_DQ_OUT_HIGH; 	//DQ=1 
	delay_us_by_Tim(30);     	//主机拉高20~40us
}
 
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void) 	   
{   
	uint8_t retry=0;
	DHT11_IO_IN();      //设置为输出	 
	while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us_by_Tim(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
	while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay_us_by_Tim(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}
 
//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void) 			 
{
 	uint8_t retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us_by_Tim(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{
		retry++;
		delay_us_by_Tim(1);
	}
	delay_us_by_Tim(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}
 
//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)    
{        
	uint8_t i,dat;
	dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}
 
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi)    
{        
 	uint8_t buf[5];
	uint8_t i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=(buf[0]<<8) + buf[1];
			*temp=(buf[2]<<8) + buf[3];
		}
	}else return 1;
	return 0;	    
}
 
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在     	 
uint8_t DHT11_Init(void)
{ 
  DHT11_Rst();
	return DHT11_Check();
}

报告与源文件下载:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911836.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python大数据分析——决策树和随机森林

Python大数据分析——决策树和随机森林 决策树决策树节点字段的选择信息熵条件熵信息增益信息增益率 基尼指数条件基尼指数基尼指数增益 决策树函数 随机森林函数 决策树 图中的决策树呈现自顶向下的生长过程&#xff0c;深色的椭圆表示树的根节点&#xff1b;浅色的椭圆表示树…

降压转换器-从分立电路到完全集成的模块

降压转换器已存在了一个世纪&#xff0c;是当今电子电路中不可或缺的一部分。本文将讲述一个原始分立式器件如何演变成可以处理数百瓦功率的微型高集成器件。 降压转换器是将输入电压转换为较低的输出电压&#xff0c;基本原理如图 1所示。最初&#xff0c;开关 SW1 关断&…

设计模式之Facade设计模式

Facade设计模式&#xff0c;也称为外观模式&#xff0c;是一种结构型设计模式&#xff0c;它主要用于为子系统中的一组接口提供一个统一的高层接口&#xff0c;从而使得子系统更加容易使用。以下是关于Facade设计模式的详细介绍&#xff1a; 一、定义 Facade模式为多个复杂的…

数据库MySQL---基础篇

存储和管理数据的仓库 MySQL概述 数据库相关概念 数据库&#xff08;DataBase&#xff09;---数据存储的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统&#xff08;DBMS&#xff09;-----操纵和管理数据库的大型软件 SQL----操作关系型数据库的编程语言&#xff…

C++之goto陈述

关键字 goto用于控制程式执行的顺序&#xff0c;使程式直接跳到指定标签(lable) 的地方继续执行。 形式如下 标签可以是任意的识别字&#xff0c;后面接一个冒号。 举例如下 #include <iostream>int main() {goto label_one;label_one: {std::cout << "Lab…

0302GPIO外设输入功能

GPIO外设输入功能 输入部分硬件电路按键简介传感器模块简介按键和传感器模块的硬件电路 C语言的学习C语言数据类型宏定义typedef结构体枚举C语言知识总结 按键控制LED灯&光敏传感器蜂鸣器GPIO总结GPIO使用方法总结模块化编程的方法&#xff1a; 两个程序&#xff1a;按键控…

Error:sql: expected 1 arguments, got 2

一 背景 在测试一个API接口时&#xff0c;看到日志里面突然抛出一个错误&#xff1a;Error:sql: expected 1 arguments, got 2 看了下&#xff0c;对应的表里面是有相关数据的&#xff0c;sql语句放在mysql里面执行也是没问题&#xff01;那奇了怪了&#xff0c;为啥会产生这样…

【MindSpore学习打卡】应用实践-热门LLM及其他AI应用-使用MindSpore实现K近邻算法对红酒数据集进行聚类分析

在机器学习领域&#xff0c;K近邻算法&#xff08;K-Nearest Neighbor, KNN&#xff09;是最基础且常用的算法之一。无论是分类任务还是回归任务&#xff0c;KNN都能通过简单直观的方式实现高效的预测。在这篇博客中&#xff0c;我们将基于MindSpore框架&#xff0c;使用KNN算法…

alibabacloud学习笔记11

讲解什么是配置中心及使用前后的好处 讲解Nacos作为配置中心面板介绍 官方文档 Nacos config alibaba/spring-cloud-alibaba Wiki GitHub 加入依赖&#xff1a; 订单服务和视频服务也加上这个依赖。 讲解Nacos作为配置中心实战 订单服务添加配置。 我们注释掉之前的配置。 …

Java项目:基于SSM框架实现的农家乐信息管理平台含前后台【ssm+B/S架构+源码+数据库+答辩PPT+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的农家乐信息管理平台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

Mybatis Plus 3.X版本的insert填充自增id的IdType.ID_WORKER策略源码分析

总结/朱季谦 某天同事突然问我&#xff0c;你知道Mybatis Plus的insert方法&#xff0c;插入数据后自增id是如何自增的吗&#xff1f; 我愣了一下&#xff0c;脑海里只想到&#xff0c;当在POJO类的id设置一个自增策略后&#xff0c;例如TableId(value "id",type …

Linux多进程和多线程(八)多线程

多线程 线程定义线程与进程线程资源 线程相关命令 pidstat 命令 top 命令ps 命令常见的并发方案 1. 多进程模式2. 多线程模式 创建线程 1. pthread_create() 示例:创建一个线程 2. pthread_exit() 退出线程3. pthread_join() 等待线程结束 示例: 线程分离 创建多个线程 示例 1:…

Spring Boot集成grpc快速入门demo

1.什么是GRPC&#xff1f; gRPC 是一个高性能、开源、通用的RPC框架&#xff0c;由Google推出&#xff0c;基于HTTP2协议标准设计开发&#xff0c;默认采用Protocol Buffers数据序列化协议&#xff0c;支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务&#xff0c…

VUE之旅—day3

工程化开发和脚手架Vue CLI 开发Vue的两种方式&#xff1a; 核心包创痛开发模式&#xff1a;基于html/css/js文件&#xff0c;直接引入核心包&#xff0c;开发Vue。 工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue。…

『大模型笔记』GraphRAG:利用复杂信息进行发现的新方法!

GraphRAG:利用复杂信息进行发现的新方法! 文章目录 一. GraphRAG:利用复杂信息进行发现的新方法!1. 将RAG应用于私人数据集2. 整个数据集的推理3. 创建LLM生成的知识图谱4. 结果指标5. 下一步二. 参考文献微软官方推文:https://www.microsoft.com/en-us/research/blog/gra…

招投标信息采集系统:让您的企业始终站在行业前沿

一、为何招投标信息如此关键&#xff1f; 在经济全球化的大背景下&#xff0c;招投标活动日益频繁&#xff0c;成为企业获取项目、拓展市场的主流方式之一。招投标信息采集&#xff0c;作为企业战略决策的前置环节&#xff0c;其重要性不言而喻。它不仅关乎企业能否第一时间发…

实时消息推送系统,写得太好了!

websocket 协议是在 http 协议上的一种补充协议&#xff0c;是 html5 的新特性&#xff0c;是一种持久化的协议。其实 websocket 和 http 关系并不是很大&#xff0c;不过都是属于应用层的协议&#xff0c;接下来我们就开始实战。 websocket 定时推送 本教程基于 springboot …

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 问题概述 📒📒 解决方案 📒🔖 方法一🔖 方法二🔖 方法三⚓️ 相关链接 🚓️📖 介绍 📖 在群晖(Synology)NAS设备上使用Docker时,我们可能会遇到查询Docker注册表失败,无法拉取Docker镜像的问题。这种情况…

一文理解 Treelite,Treelite 为决策树集成模型的部署和推理提供了高效、灵活的解决方案

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、什么是 Treelite&#xff1f; Treelite 是一个专门用于将决策树集成模型高效部署到生产环境中的机器学习模型编译器&#xff0c;特别适合处理大批量数据的推理任务&#xff0c;能够显著提升推理性能…