电子发烧友App

硬声App

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示
电子发烧友网>电子资料下载>电子资料>用Arduino库来读取DHT11湿度和温度传感器数据

用Arduino库来读取DHT11湿度和温度传感器数据

2022-11-22 | zip | 0.28 MB | 次下载 | 免费

资料介绍

描述

介绍

在这个项目中,我开发了一个 Arduino 库来读取 DHT11 湿度和温度传感器生成的数据,并使用 AZDelivery ESP8266 ESP-12F NodeMCU Lua Amica V2 将其连续发送到 ThingSpeak 云服务。

有许多库可以用来读取 DHT11 传感器数据。那么,为什么要重新发明轮子呢?只是为了了解事物的运作方式并可能改进它们的乐趣。

我使用逻辑分析仪和 DHT11 传感器数据表来了解协议并为传感器开发自己的库。DHT11 温度和湿度传感器

DHT11 温度和湿度传感器具有温度和湿度传感器复合体,具有校准的数字信号输出。采用独有的数字信号采集技术和温湿度传感技术,确保高可靠性和出色的长期稳定性。该传感器包括一个电阻式湿度测量元件和一个NTC温度测量元件,并连接到一个高性能8位微控制器,具有卓越的品质、快速的响应、抗干扰能力和成本效益。

pYYBAGN6Xe-AY0PMAADaEY3sW2E139.png
 
poYBAGN6XfKAG56UAAHYq6B4Uh0186.png
 

PINOUT 和 MCU 连接

pYYBAGN6XfWAaOFwAADEYjqPc5g887.png
带 10KOhm 上拉电阻和 DHT11 引脚的 DHT11 分线模块
 

MCU 到 DHT11 连接

poYBAGN6XfiAOLT-AAEAJt1Mu5E855.png
 

使用的分线模块已经有一个 10 KOhm 的上拉电阻。

poYBAGN6Xf6AIGKwAAsvUTfh1rg013.jpg
NodeMCU ESP-8266 Amica 连接到 DHT11 分支
 

DHT11 数据引脚连接到 D1 (GPIO5)

pYYBAGN6XgGAU2JYAAChtgNoAhs954.png
 

GPIO 0-15 都有一个内置的上拉电阻器,如果直接使用 DHT11 而不是分线器,我们可以使用它。

有关如何在我的NodeMCU Amica V2 路试中设置此模块的更多信息

poYBAGN6XgOAFgo7AACDUMA5yOM453.png
 

AZ Delivery NodeMCU V2 路试,作者:Enrique Albertos

https://www.hackster.io/javagoza/nodemcu-amica-v2-road-test-2e8bff

MCU 到 DHT11 通信

DHT11 单总线数据格式

单总线数据格式用于 MCU 和 DHT11 传感器之间的通信和同步。一个通信过程大约是4ms。数据由小数部分和整数部分组成。一次完整的数据传输为 40 位,传感器先发送高位数据。

数据格式:

8 bit integral RH data + 8 bit decimal RH data + 8 bit integral T data + 8 bit decimal T data + 8 bit checksum.

如果数据传输正确,校验和应该是:

8 bit integral RH data + 8 bit decimal RH data + 8 bit integral T data + 8 bit decimal T data

poYBAGN6XgaAPJUaAAIa8AZ27fY398.png
使用 PulseView 解码通信
 
pYYBAGN6XgiAEvAJAADrvbClMQc057.png
来自 DHT11 数据表
 
pYYBAGN6XguAM80BAADF7foSwnw843.png
来自 DHT11 数据表
 

PulseView 和逻辑分析仪

PulseView 是 libsigrok 和 libsigrok 解码库的图形前端,允许访问各种设备和协议解码器,让您记录、分析、处理和导出模拟和逻辑数据。

https://sigrok.org/

逻辑分析仪

我们正在使用 AZ-Delivery 的这款廉价逻辑分析仪来监视 MCU 和 AZ Delivery NodeMCU 8266 Amica 模块之间的通信。

逻辑分析仪有 8 个并行输入 (0-5 V),每秒最多允许 2400 万个测量步骤。对于数字信号,采样速度必须比带宽快 4 倍。这意味着带宽是采样率的四分之一。

  • 最大数字采样率:24 MSPS
  • 最大数字带宽:6 MHz

这足以监视这种简单的通信所需的 200 Khz。

poYBAGN6XhSAVXjXABftNs9Y3iU406.jpg
 

脉冲视图

安装后,您会在开始菜单中找到一个名为 Zadig 的程序。默认情况下,Windows 识别的某些设备将安装 PulseView 无法使用的驱动程序。Zadig 的目的是让您更改 Windows 用于特定设备的驱动程序 - 对于大多数设备,您需要选择 WinUSB 以将它们与 PulseView 或原始专有 Windows 驱动程序一起使用以将其与您访问设备的任何其他软件一起使用和。

新会话

  • 打开一个新会话
  • 选择您要使用的设备:
  • 点击“运行”获取信号数据(设置了则等待触发)

放大直到看到信号,MCU 和 DHT11 之间的通信大约需要 135 毫秒。

这是向传感器请求数据时的位流。

poYBAGN6XhaAI7RpAACYHxXBDTE905.png
 

DHT11单线通讯协议解码器

Pulseview 带有一个 DHT11 协议解码器。让我们使用它。

添加解码器并将其关联到串行数据线。D1 在我们的例子中。

pYYBAGN6XhmAZiwUAADHxlqg-Hc682.png
 

该解码器处理傲松 AM230x/DHTxx/RHTxx 系列数字湿度和温度传感器使用的专有单线通信协议。

采样率:建议使用至少200 kHz的采样率来正确检测协议的所有元素。

选项:

AM230x 和 DHTxx/RHTxx 数字湿度和温度传感器使用相同的单线协议,测量值的编码不同。因此,必须使用选项“设备”来正确解码各个传感器的通信。dht11 设备类型”用于我们的目的。

pYYBAGN6XhyASLU0AAJlD3nKmwc187.png
 

缩放以查看解码数据

poYBAGN6XgaAPJUaAAIa8AZ27fY398.png
 

相对湿度 %

8 位积分 RH 数据 + 8 位十进制 RH 数据

poYBAGN6XiGAMEpUAAErcgYIds0314.png
 

温度

8位整数T数据+8位十进制T数据

pYYBAGN6XiSAaOGUAAHU828aLFQ992.png
 

校验和

8 位积分 RH 数据 + 8 位十进制 RH 数据 + 8 位积分 T 数据 + 8 位十进制 T 数据

poYBAGN6XieAfB72AAH2LcZd_Ew578.png
 

使用 ESP8266 内核为 Arduino 读取传感器数据

我们有几种方法来读取数据并处理 DHT11 使用的专有单线通信协议:

  • 盲循环:等待固定的时间,并假设 I/O 将在该固定延迟过去之前完成。此方法不适合我们读取传感器数据,因为 0s 和 1s 时序不同,您可能会失去同步,但我们将使用它来启动信号到 DHT,因为这是使 DHT11 从低电平变化的盲信号-power-consumption mode 到 running-mode。
  • 忙等待同步或轮询。检查完成状态的 I/O 状态的软件循环。这可能是我们读取 DHT11 发送数据的第一个候选者,因为系统非常简单,实时响应并不重要。
  • 中断。使用硬件导致特殊的软件执行。当输入设备有新数据时,硬件将请求并中断。软件中断服务将从输入设备中读取并保存在全局 RAM 中。为了简单起见,我们不会使用这种方法。

开始信号 - 盲循环

Data Single-bus free 状态为高电平。当 MCU 和 DHT11 开始通信时,MCU 程序会将 Data Single-bus 电压电平从高电平设置为低电平,这个过程必须至少需要 18 ms 才能确保 DHT 检测到 MCU 的信号,然后 MCU 会拉高电压并等待 20 -40 我们 DHT 的回应。

/**
   MCU Sends Start Signal to DHT as this is a blind cycle that makes DHT11
   to change from the low-power-consumption mode to the running-mode

   Consists of a pulse of at least 18 ms voltage-length
   @params void
   @return true if there no problem
*/
boolean DHT11::sendStartSignal(void) {
  digitalWrite(pin, LOW); // MCU Send start signal
  pinMode(pin, OUTPUT);
  delay(timeLengthWakeupSignal_ms); // at least 18 ms
  // MCU Pulls up voltage
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH); // Switch to receive data
  return true;
}

本项目使用的 DHT11 模块有一个 10K 的上拉电阻,所以我们不设置 INPUT_PULLUP。

DHT一旦检测到启动信号,就会发出一个低电平响应信号,持续80us。然后DHT程序将Data Single-bus电压电平由低到高并保持80us,为DHT发送数据做准备。

pYYBAGN6XimAUP-OAADFASMgtZE819.png
 

忙等待同步

然后我们将使用忙等待同步来检测以下脉冲沿,从 RAISING 到 FALLIN 以及从 FALLING 到 RAISING

/**
   Waits until digital port changes to final state or timeout occurs

   @param pin to check
   @param state to wait for
   @param maximum time to wait
   @return the elapsed time to reach the final state if less than timeout
   or the elapsed time that forced the timeout

*/
int DHT11::busyWait(const int pin, const int finalState, const int timeout) {
  int elapsedTime = 0;
  int startTime = micros();
  while ( digitalRead(pin) != finalState && elapsedTime < timeout ) {
    elapsedTime = micros() - startTime;
  }
  return elapsedTime;
}

忙于等待启动信号响应

首先等待启动信号响应

DHT一旦检测到启动信号,就会发出一个低电平响应信号,持续80us。所以我们将等待 DHT11 准备好。

/**
   Once DHT detects the start signal, it will send out a low-voltage-level
   response signal, which lasts 80us. So we will wait for the DHT11 to be ready.

   @param void
   @return true if there no problem
*/
boolean DHT11::waitForStartSignalResponse(void) {
  return busyWait(pin, LOW, timeoutForStartData_us) < timeoutForStartData_us;
}

忙于等待起始位

然后等待起始位

/**
   DHT sends out response signal and keeps it for 80 us
   then DHT pulls up voltage and keeps it for 80 us
   
   @param void
   @return true if there no problem
*/
boolean DHT11::waitForStartBit(void) {
  if ( busyWait(pin, HIGH, timeoutForResponseSignal_us) < timeoutForResponseSignal_us) { // DHT sends oit response signal and keeps it for 80 us
    return (busyWait(pin, LOW, timeoutForStartData_us) < timeoutForStartData_us); // then DHT pulls up voltage and keeps it for 80 us
  }
  return false;
}

忙等待读取 40 位数据

最后读取 40 位数据

/*
   Read the 40 bits in a Dht11 data record

   @param pointer to the record to be actualized
   @return true if there no problem
*/
boolean DHT11::readDht11DataRecord(DHT11::Dht11_data_type * dataRead)
{
  uint8_t integralRh = readByte(pin, timeoutForStartToTransmitData_us, timeoutForData_us, zeroLength_us);
  
  uint8_t decimalRh = readByte(pin, timeoutForStartToTransmitData_us, timeoutForData_us, zeroLength_us);
  
  uint8_t integralTemp = readByte(pin, timeoutForStartToTransmitData_us, timeoutForData_us, zeroLength_us);
  
  uint8_t decimalTemp = readByte(pin, timeoutForStartToTransmitData_us, timeoutForData_us, zeroLength_us);
  
  uint8_t checksum = readByte(pin, timeoutForStartToTransmitData_us, timeoutForData_us, zeroLength_us);
  
  // Verify checksum: integral RH + decimal RH + integral Temp data + decimal Temp data
  if ( (integralRh + decimalRh + integralTemp + decimalTemp ) != checksum ) {
    dataRead->error = ERROR_CHECKSUM;
    dataRead->status =  statusString[ERROR_CHECKSUM];
    return false;
  }
  
  dataRead->error = ERROR_NONE;
  dataRead->status =  statusString[ERROR_NONE];
  dataRead->temperature = (float)integralTemp +  (float)decimalTemp / 10.0;
  dataRead->humidity = (float)integralRh +  (float)decimalRh / 10.0;
  return true;
}

读取一个字节

如果检测到“1”位,则字节初始化为 b0000 0000,位位置使用 BIT_MASK 切换

const uint8_t BIT_MASK[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

/*
   Read 8 bits in a byte from the line

   @param pointer to the record to be actualized
   @param int pin,
   @param int timeout For Start To Transmit Data in us
   @param int timeout For Data in us,
   @param int bit Zero Length in us
   @return the read byte if any or FF if there is any problem reading
*/
uint8_t DHT11::readByte(const int pin,
                        const int timeoutForStartToTransmitData_us,
                        const int timeoutForData_us,
                        const int bitZeroLength_us) {
  uint8_t data = 0;
  for (int i = 7; i >= 0; i--) {
    if (busyWait(pin, HIGH, timeoutForStartToTransmitData_us) < timeoutForStartToTransmitData_us) { // wait for RAISING
      int bitLength = busyWait(pin, LOW, timeoutForData_us) ; // wait for FALLING
      if (bitLength > timeoutForData_us) {
        return 0xFF;
      }
      if (bitLength > bitZeroLength_us) { // 1 bit value, toggle bit
        data |= BIT_MASK[i];
      }
    }
  }
  return data;
}

检查解决方案

  • 创建 DHT11 对象
  • 通话设置
  • 需要新讲座时调用 readSensor。注意:间隔采样周期应不少于 1 秒。
#include "DHT11.h"

DHT11 dht11; // DHT11 sensor

void setup()
{
  Serial.begin(115200); // for debugging
  Serial.println();
  Serial.println("Status\tHumidity (%)\tTemperature (C)");

  // Initialize DHT11 sensor
  dht11.setup(D1);   // sensor in D1
}


void loop()
{
  DHT11::Dht11_data_type sensorData = dht11.readSensor();
  logData(&sensorData);
  // NOTE: Sampling periods at intervals should be no less than 1 second
  delay(2000); // Wait 2000 milliseconds for the next reading
} 

/*
 * Logs sensor data to serial log
 * 
 * @params void
 * @retun void
 */
void logData(DHT11::Dht11_data_type *sensorData){
  Serial.print(sensorData->status);/* status of communication */
  Serial.print("\t");
  Serial.print(sensorData->humidity, 0);
  Serial.print("\t\t");
  Serial.println(sensorData->temperature, 2);
}

通过串口记录数据。

poYBAGN6XiyAYYq1AACzSKkDDmg581.png
 

向 ThinkSpeak 发送数据

首先注册:

https://thingspeak.com/

使用两个字段创建通道:

  • 湿度
  • 温度
pYYBAGN6Xi-AWRZkAALWmYGxlvQ301.png
 

在文件 secrets.h 中填写您的秘密数据

// Use this file to store all of the private credentials 
// and connection details

#define SECRET_SSID "MySSID"    // replace MySSID with your WiFi network name
#define SECRET_PASS "MyPassword"  // replace MyPassword with your WiFi password

#define SECRET_CH_ID 0000000      // replace 0000000 with your channel number
#define SECRET_WRITE_APIKEY "XYZ"   // replace XYZ with your channel write API Key
poYBAGN6XjOABYRhAAN5d-_T5A8793.png
 

最终代码

主要代码:

void setup()
{
  Serial.begin(115200); // for debugging
  // Begin ThinkSpeak connection
  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);  // Initialize ThingSpeak

  Serial.println();
  Serial.println("Status\tHumidity (%)\tTemperature (C)");

  // Initialize DHT11 sensor
  dht11.setup(D1);   // sensor in D1
}

void loop()
{
  checkWifiConnection();
  DHT11::Dht11_data_type sensorData = dht11.readSensor();
  logData(&sensorData);
  if (DHT11::ERROR_NONE == sensorData.error) {
     sendDataToThingSpeak(&sensorData);
  }
  delay(120000); // Wait 120 seconds to update the channel again
}

检查WIFI连接

/*
 * Check if wifi is connected
 * if not reconnect
 * 
 * @params void
 * @retun void
 */
void checkWifiConnection(void) {
  // Connect or reconnect to WiFi
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while (WiFi.status() != WL_CONNECTED) {
      WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network.
      Serial.print(".");
      int counter = 0;
      // wait for connection established
      while ((WiFi.status() != WL_CONNECTED ) && (counter < 10)) {
        delay(1000);
        counter++;
      }
    }
    Serial.println("\nConnected.");
  }
}

向 ThingSpeak 发送数据:

/*
 * Sends sensor data to Thing speak
 * 
 * @params sensor data record reference
 * @retun void
 */
void sendDataToThingSpeak(DHT11::Dht11_data_type *sensorData) {
  // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
  // pieces of information in a channel.  Here, we write to field 1.
  ThingSpeak.setField(1, sensorData->temperature);
  ThingSpeak.setField(2, sensorData->humidity);
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if (x == 200) {
    Serial.println("Temp Channel update successful.");
  }
  else {
    Serial.println("Problem updating temp channel. HTTP error code " + String(x));
  }
}

日志记录

pYYBAGN6XjWAERYxAAGKoJzQql8676.png
 
poYBAGN6XjiAcOOhAAK4o1Da6ho776.png
 

 


下载该资料的人也在下载 下载该资料的人还在阅读
更多 >

评论

查看更多

下载排行

本周

  1. 1山景DSP芯片AP8248A2数据手册
  2. 1.06 MB  |  532次下载  |  免费
  3. 2RK3399完整板原理图(支持平板,盒子VR)
  4. 3.28 MB  |  339次下载  |  免费
  5. 3TC358743XBG评估板参考手册
  6. 1.36 MB  |  330次下载  |  免费
  7. 4DFM软件使用教程
  8. 0.84 MB  |  295次下载  |  免费
  9. 5元宇宙深度解析—未来的未来-风口还是泡沫
  10. 6.40 MB  |  227次下载  |  免费
  11. 6迪文DGUS开发指南
  12. 31.67 MB  |  194次下载  |  免费
  13. 7元宇宙底层硬件系列报告
  14. 13.42 MB  |  182次下载  |  免费
  15. 8FP5207XR-G1中文应用手册
  16. 1.09 MB  |  178次下载  |  免费

本月

  1. 1OrCAD10.5下载OrCAD10.5中文版软件
  2. 0.00 MB  |  234315次下载  |  免费
  3. 2555集成电路应用800例(新编版)
  4. 0.00 MB  |  33566次下载  |  免费
  5. 3接口电路图大全
  6. 未知  |  30323次下载  |  免费
  7. 4开关电源设计实例指南
  8. 未知  |  21549次下载  |  免费
  9. 5电气工程师手册免费下载(新编第二版pdf电子书)
  10. 0.00 MB  |  15349次下载  |  免费
  11. 6数字电路基础pdf(下载)
  12. 未知  |  13750次下载  |  免费
  13. 7电子制作实例集锦 下载
  14. 未知  |  8113次下载  |  免费
  15. 8《LED驱动电路设计》 温德尔著
  16. 0.00 MB  |  6656次下载  |  免费

总榜

  1. 1matlab软件下载入口
  2. 未知  |  935054次下载  |  免费
  3. 2protel99se软件下载(可英文版转中文版)
  4. 78.1 MB  |  537798次下载  |  免费
  5. 3MATLAB 7.1 下载 (含软件介绍)
  6. 未知  |  420027次下载  |  免费
  7. 4OrCAD10.5下载OrCAD10.5中文版软件
  8. 0.00 MB  |  234315次下载  |  免费
  9. 5Altium DXP2002下载入口
  10. 未知  |  233046次下载  |  免费
  11. 6电路仿真软件multisim 10.0免费下载
  12. 340992  |  191187次下载  |  免费
  13. 7十天学会AVR单片机与C语言视频教程 下载
  14. 158M  |  183279次下载  |  免费
  15. 8proe5.0野火版下载(中文版免费下载)
  16. 未知  |  138040次下载  |  免费