夸克之书

  • 首页
  • 科普
  • 笔记
  • C#
  • 物联网
  • 算法
  • Linux
  • 树莓派
夸克之内,别有洞天
  1. 首页
  2. 树莓派
  3. 正文

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用

2019-09-19 1696点热度 0人点赞 0条评论

前言

为什么将DHTx放在第二篇来讨论?第一是DHT12,DHT22温湿度采用单总线方式传输数据,使用简单且广泛。第二是DHTx系列包含在Iot.Device.DHTxx命名空间下面,可以直接调用。

DHT22简介

AM2302湿敏电容数字温湿度模块是一款含有己校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个高精度测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在单片机中,传感器内部在检测信号的处理过程中要调用这些校准系数。标准单总线接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选择。(来源于官方手册)

产品手册下载:

DHT22数字温湿度传感器AM2302温湿度下载

电路图

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图

DHT22当中VCC接树莓派5V引脚,GND接树莓派GND,Data接树莓派GPIO26(物理引脚37)。

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图1

注意:需要在Data引脚和Vcc引脚之间并联一个10KΩ电阻作为上拉电阻。

编写代码

using System;
using System.Device.Gpio;
using System.Threading;

namespace _2.Dht22
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //使用GPIO 16
                using (Iot.Device.DHTxx.Dht22 dht = new Iot.Device.DHTxx.Dht22(26, PinNumberingScheme.Logical))
                {
                    while (true)
                    {
                        Console.WriteLine($"Temperature: {dht.Temperature.Celsius.ToString("0.0")} ℃, Humidity: { dht.Humidity.ToString("0.0")} %");
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

同样。发布之后上传至树莓派运行,可以看到正常获取当前环境温度和湿度。

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图2
运行结果

分析

接下来咋们来一步一步分析整个数据读取流程是怎么样的?首先更具DataSheet所给出的流程图

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图3

整个读取流程可以分为三个步骤:

(1)SDA处于上拉状态,等待外部信号

AM2302 上电后(AM2302 上电后要等待 2S 以越过不稳定状态,在此期间读取设备不能发送任何指令),测试环境温湿度数据,并记录数据,此后传感器自动转入休眠状态。AM2302 的 SDA 数据线由上拉电阻拉高一直保持高电平,此时 AM2302 的 SDA 引脚处于输入状态,时刻检测外部信号。

(2)主机发起读取信号,并应答

树莓派的 I/O 设置为输出,同时输出低电平,且低电平保持时间不能小于 800us,典型值是拉低 1MS,然后树莓派的 I/O 设置为输入状态,释放总线,由于上拉电阻, 树莓派的 I/O 即 AM2302的 SDA 数据线也随之变高,等主机释放总线后,AM2302 发送响应信号,即输出 80 微秒的低电平作为应答信号,紧接着输出 80 微秒的高电平通知外设准备接收数据,信号传输如图 所示:

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图4

(3)接收数据

AM2302 发送完响应后,随后由数据总线 SDA 连续串行输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据。
位数据“0”的格式为: 50 微秒的低电平加 26-28 微秒的高电平;
位数据“1”的格式为: 50 微秒的低电平加 70 微秒的高电平;
位数据“0”、位数据“1”格式信号如图所示:

树莓派.Net Core Iot入门系列篇(2):DHT22温湿度传感器的使用插图5

AM2302 的数据总线 SDA 输出 40 位数据后,继续输出低电平 50 微秒后转为输入状态,由于上拉电阻随之变为高电平。同时 AM2302 内部重测环境温湿度数据,并记录数据,测试记录结束,传感器内部单片机自动进入休眠状态。传感器内部单片机只有收到主机的起始信号后,才重新唤醒传感器,进入工作状态。

整个流程用程序表示如下:

static byte[] Read(int pin)
{
    uint loopCount = 10000;
    Stopwatch stopwatch = new Stopwatch();
    byte[] readBuff = new byte[5];
    byte readVal = 0;
    uint count;

    try
    {
        using (GpioController controller = new GpioController())
        {
            //第一步 打开GPIO,准备读取
            controller.OpenPin(pin);
            if (!controller.IsPinOpen(pin))
            {
                throw new Exception($"Open pin {pin} failed.");
            }

            //第二步 主机发起读取,并接收应答
            controller.SetPinMode(pin, PinMode.Output);
            controller.Write(pin, PinValue.Low);
            // wait at least 18 milliseconds
            // here wait for 18 milliseconds will cause sensor initialization to fail
            DelayMicroseconds(20000, true);

            //拉高,然后等待30us,准备接收信号
            controller.Write(pin, PinValue.High);
            DelayMicroseconds(30, true);
            controller.SetPinMode(pin, PinMode.InputPullUp);

            //传感器拉低,作为应答信号
            count = loopCount;
            while (controller.Read(pin) == PinValue.Low)
            {
                if (count-- == 0)
                {
                    return null;
                }
            }

            //拉高,作为开始信号
            count = loopCount;
            while (controller.Read(pin) == PinValue.High)
            {
                if (count-- == 0)
                {
                    return null;
                }
            }

            //第三步 读取40bit的数据
            for (int i = 0; i < 40; i++)
            {
                //每位数据的起始信号,50us的低电平信号
                count = loopCount;
                while (controller.Read(pin) == PinValue.Low)
                {
                    if (count-- == 0)
                    {
                        return null;
                    }
                }

                // 26 - 28 microseconds represent 0
                // 70 microseconds represent 1
                stopwatch.Restart();
                count = loopCount;
                while (controller.Read(pin) == PinValue.High)
                {
                    if (count-- == 0)
                    {
                        return null;
                    }
                }
                stopwatch.Stop();

                //位数据“0”的格式为: 50 微秒的低电平加 26-28 微秒的高电平;
                //位数据“1”的格式为: 50 微秒的低电平加 70 微秒的高电平;
                //这里取30us
                readVal <<= 1;
                if (!(stopwatch.ElapsedTicks * 1000000F / Stopwatch.Frequency <= 30))
                {
                    readVal |= 1;
                }

                if (((i + 1) % 8) == 0)
                {
                    readBuff[i / 8] = readVal;
                }
            }

            //数据总线 SDA 输出 40 位数据后,继续输出低电平 50 微秒后转为输入状态
            //一次读取结束,拉高总线,有上拉电阻的话,会自动拉高
            DelayMicroseconds(50, true);
            controller.SetPinMode(pin, PinMode.Output);
            controller.Write(pin, PinValue.High);
        }
        //校验
        if ((readBuff[4] == ((readBuff[0] + readBuff[1] + readBuff[2] + readBuff[3]) & 0xFF)))
        {
            return readBuff;
        }
        else
        {
            return null;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

参考资料

1、DHTxx - Digital-Output Relative Humidity & Temperature Sensor Module
2、Demo下载

本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2020-12-13

afirefish

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

管理员

这个人很懒,什么都没留下

搜索文章
分类
  • C# (29)
  • Linux (3)
  • 树莓派 (13)
  • 物联网 (19)
  • 科普 (4)
  • 笔记 (30)
  • 默认 (46)
最新 热点 随机
最新 热点 随机
C#几种深拷贝方法探究及性能比较 获取访问IP信息接口(暂不开放) Vieu主题作者疑似跑路?这人品?!!! 树莓派PWM风扇控制 PVE重启后LVM Thin数据丢失,错误:Volume group "****" has insufficient free space (128 extents): 4048 required. OpenWrt配置SmartDNS OpenWrt x86安装Frpc Intel网卡开机显示Initializing Intel(R) Boot Agent GE v1.5.50
树莓派PWM风扇控制Error response from daemon: cannot stop container: ******: Cannot kill container *******:.....单机Docker搭建FastDFSC# Json序列化时将长整型(long)属性序列化为Json字符串使用淘宝npm以及安装cnpm免费本地解析域名(locallocal.cn),支持HTTPSIdentityServer4证书创建Intel网卡开机显示Initializing Intel(R) Boot Agent GE v1.5.50
ESXi 6.7 切换时区(已经确认无效) 23种常见的设计模式(9):命令模式 ASP.NET Core Code First使用MySQL以及初始化默认数据 Chrome显示完整URL和HTTP协议 .Net Core在Linux下操作图片报错 C# Json序列化时将长整型(long)属性序列化为Json字符串 这10本物理科普书籍,足以回答你的N多问题!(转) 在VS Code开发Arduino项目
最近评论
发布于 3 周前(03月21日) function getCpuTemp() 函数结束之前使用close关闭 文件流 不关闭的话长...
发布于 3 周前(03月19日) 闹了半天找到问题了 原来是gpio版本问题 pi@raspberrypi:~/Desktop $ ...
发布于 3 周前(03月19日) sudo下执行 无法控制小风扇 普通用户却可以 这是可能是什么原因 :redface:
发布于 2 个月前(02月21日) 好的谢谢,那我只能通过kill杀死推流指令进程来实现了。
发布于 2 个月前(02月21日) 要用这个项目的话,你得自己拉代码来改了。做这玩意儿主要是考虑全天候的,没考虑过关[笑哭]
书签
  • 打赏
  • 毒鸡汤(有点意思)
  • 米店
  • 金鱼直播间
放松一下
https://www.quarkbook.com/wp-content/uploads/2020/09/Yanni-Nightingale.flac
用户您好!请先登录!
登录 注册

COPYRIGHT © 2020 夸克之书. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

蜀ICP备15036129号-9

登录
注册|忘记密码?