如何使用ESP8266和DHT11实现室内温度和湿度的采集并通过WIFI发送到服务端程序


你是否曾经想过要实现一个自己的室内温度和湿度检测系统?利用周末的时间完成了这个小目标,我使用了ESP8266和DHT11,并将收集的数据通过WIFI发送到服务端程序,并存储到SQLite数据库中。在后面的介绍中,我将与你分享如何完成这个任务。

首先,我想解释一下我为什么选择了ESP8266和DHT11。ESP8266是一款低成本的Wi-Fi微芯片,具有全栈TCP/IP协议。借助于这款芯片,我们可以轻松的将任何微控制器连接到Wi-Fi网络。DHT11则是一款具有已校准数字输出的温湿度传感器。它的主要优点是精度高、响应速度快、抗干扰能力强,且价格低廉。

在硬件连接方面,ESP8266的3V3和GND分别连接到DHT11的VCC和GND,ESP8266的D4则连接到DHT11的数据端。这样,我们就可以通过ESP8266从DHT11读取温湿度数据了。

接下来是编程部分。首先,我们需要在ESP8266上运行一个程序,这个程序会定期从DHT11读取温度和湿度数据,并通过Wi-Fi将这些数据发送到我们的服务端程序。在这个程序中,我们使用了DHT库和ESP8266WiFi库。DHT库使我们能够方便地从DHT11读取数据,而ESP8266WiFi库则让ESP8266能够连接到Wi-Fi。

服务端程序是运行在服务器上的一个简单的Python脚本,它会监听来自ESP8266的连接,并将接收到的温湿度数据写入SQLite数据库。在这个脚本中,我们使用了WebAPI库来处理网络连接,用sqlite3库来操作SQLite数据库。

完成这个项目后,我不仅可以随时查看室内的温度和湿度,还可以通过分析SQLite数据库中的数据,了解室内温湿度的变化趋势、告警等等。

最后,我想强调的是,虽然我详细介绍了如何使用ESP8266和DHT11实现室内温度和湿度的采集并通过WIFI发送到服务端程序,但这只是其中一种方法。你完全可以根据自己的需求和条件,选择不同的硬件和软件,实现自己的小目标。我希望我的经验能为你提供一些启示。

开发工具:Arduino IDE 2.2.1 

硬件:ESP8266 开发板、DHT12 温湿度模块、ST7735 TFT 屏幕

程序首次使用屏幕会显示二维码,支持微信扫码配WIFI

// ##################################################################################
//
//  温、湿度采集客户端
//
//  版本:1.0.01
//
//  Create by linjifan 2023-11-11
// ##################################################################################
// 室内适宜 温度:19-26 度 、湿度:20-85 RH%
// 


//图片解码库
#include <TJpg_Decoder.h>
//json库,用于网页解析
#include <ArduinoJson.h>
//时间库,用于时钟部分
#include <TimeLib.h>
//wifi库
#include <ESP8266WiFi.h>
//http请求库
#include <ESP8266HTTPClient.h>
//创建wifi的udp服务的库
#include <WiFiUdp.h>
//静态存储区,用于存储一些固定参数
#include <EEPROM.h>
//安信可配网二维码
#include "qr.h"
#include <DHT.h>
#include <SPI.h>
#include "libraries\TFT_eSPI\TFT_eSPI.h"

//配置ESP8266 GPI1口
#define DHTPIN 5
//官方适配有:DHT11,DHT12,DHT21,DHT22,AM2301
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// 引脚请自行配置tft_espi库中的 User_Setup.h文件
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite clk = TFT_eSprite(&tft);

WiFiClient wificlient;
uint32_t targetTime = 0;
byte loadNum = 6;

//上传采集间隔等待时间
const uint32_t sleepTime = 1000 * 60;
//节点名称
const char node[] = "DataCenter";
//---------------修改此处""内的信息,配网无效才需要修改,一般不用动--
//WIFI名称
const char ssid[] = "";
//WIFI密码
const char pass[] = "";

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {
  if (y >= tft.height()) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  // Return 1 to decode next block
  return 1;
}

void setup(void) {
  Serial.begin(115200);
  Serial.println(F("DHT11 test!"));

  //DHT11 模块初始化
  dht.begin();
  delay(2000);

  /* TFT init */
  tft.begin();
  // 反转所有显示颜色:1反转,0正常
  tft.invertDisplay(1);
  tft.fillScreen(0xFFFF);
  tft.setTextColor(TFT_WHITE, 0xFFFF);
  // 设置屏幕显示的旋转角度,参数为:0, 1, 2, 3
  // 分别代表 0°、90°、180°、270°
  //根据实际需要旋转
  tft.setRotation(4);

  TJpgDec.setJpgScale(1);
  TJpgDec.setSwapBytes(true);
  TJpgDec.setCallback(tft_output);

  targetTime = millis() + 1000;

  Serial.print("正在连接WIFI...");
  Serial.println(ssid);

  WiFi.begin(WiFi.SSID().c_str(), WiFi.psk().c_str());

  TJpgDec.setJpgScale(1);
  TJpgDec.setSwapBytes(true);
  TJpgDec.setCallback(tft_output);
  tft.fillScreen(0xFFFF);
  while (WiFi.status() != WL_CONNECTED) {
    loading(70);

    if (loadNum >= 94) {
      SmartConfig();
      break;
    }
  }
  delay(10);
  // while(loadNum < 94) //让动画走完
  // {
  //   loading(1);
  // }

  Serial.print("本地IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("MAC地址: ");
  Serial.println(WiFi.macAddress());

  tft.fillScreen(0xFFFF);
  // 显示检查窗口
  clk_check();

  delay(5000);
}

//绘制检查窗口
void clk_check() {
  clk.createSprite(120, 120);
  clk.fillSprite(0xFFFF);
  clk.setTextDatum(CL_DATUM);
  clk.setTextColor(TFT_GREEN, 0xFFFF);
  clk.drawString(" DHT11.....OK", 10, 20, 2);
  clk.drawString(" WiFi......OK", 10, 40, 2);
  clk.pushSprite(0, 0);
  clk.deleteSprite();
}

//绘制进度条
void loading(byte delayTime) {
  clk.setColorDepth(8);
  // 创建窗口
  clk.createSprite(100, 100);
  // 填充率
  clk.fillSprite(0xFFFF);
  // 空心圆角矩形
  clk.drawRoundRect(0, 0, 100, 16, 8, 0x0000);
  // 实心圆角矩形
  clk.fillRoundRect(3, 3, loadNum, 10, 5, 0x0000);
  // 设置文本数据
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_GREEN, 0xFFFF);
  clk.drawString("Connect WiFi...", 50, 40, 2);
  clk.drawString("Ver: 1.0.01", 50, 80, 1);
  clk.setTextColor(TFT_WHITE, 0xFFFF);
  // 窗口位置
  clk.pushSprite(14, 30);
  clk.deleteSprite();
  loadNum += 1;
  delay(delayTime);
}

//微信配网,注意连接2.4g网络
void SmartConfig(void) {
  // 设置STA模式
  WiFi.mode(WIFI_STA);
  //tft.pushImage(0, 0, 240, 240, qr);
  //tft.pushImage(0, 0, 240, 240, qr);
  TJpgDec.drawJpg(0, 0, qr, sizeof(qr));
  // 打印log信息
  Serial.println("\r\nWait for Smartconfig...");
  // 开始 SmartConfig 等待手机端发出用户名和密码
  WiFi.beginSmartConfig();
  while (1) {
    Serial.print(".");
    // wait for a second
    delay(100);
    // 配网成功,接收到SSID和密码
    if (WiFi.smartConfigDone()) {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      break;
    }
  }
  loadNum = 94;
}

//上传温、湿度等信息到服务端
void pushData(String h, String t, String i, String Node) {
  String URL = "http://172.168.0.XXX:5000/api/v1/weather/Update?h=" + h + "&t=" + t + "&i=" + i + "&time=" + String(now()) + "&node=" + Node + "&mac=" + WiFi.macAddress();

  HTTPClient httpClient;
  //配置请求地址。此处也可以不使用端口号和PATH而单纯的
  httpClient.begin(wificlient, URL);
  //设置请求头中的User-Agent
  httpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
  //httpClient.addHeader("Referer", "http://www.weather.com.cn/");
  //启动连接并发送HTTP请求
  int httpCode = httpClient.GET();
  Serial.print("Send GET request to URL: ");
  Serial.println(URL);

  //如果服务器响应OK则从服务器获取响应体信息并通过串口输出
  if (httpCode == HTTP_CODE_OK) {
    String str = httpClient.getString();
    Serial.println(str);
  } else {
    Serial.println("上报数据错误:");
    Serial.println(httpCode);
    // 显示红色失败状态
    drawIndicatorLight(120, 120, TFT_NAVY);
    delay(200);
  }
  //关闭ESP8266与服务器连接
  httpClient.end();
}


void loop() {

  // 读取温度或湿度大约需要250毫秒!
  // 传感器读数也可能高达2秒"旧"(它是一个非常慢的传感器)
  float h = dht.readHumidity();
  // 以摄氏度读取温度(默认值)
  float t = dht.readTemperature();
  // 将温度读取为华氏温度(isFahrenheit = true)
  float f = dht.readTemperature(true);

  // 检查是否有读取失败并提前退出(再试一次)。
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // 计算华氏热度指数(默认值)
  float hif = dht.computeHeatIndex(f, h);
  // 以摄氏度计算热指数(isfahrenheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  //打印数值(华氏度的注释掉了)
  //打印湿度
  Serial.print(F("Humidity: "));
  Serial.print(h);
  //打印温度
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  //Serial.print(f);
  //Serial.println(F("°F"));
  //打印热指数
  Serial.print(F("  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.println();

  clk.createSprite(120, 120);
  clk.fillSprite(0xFFFF);

  clk.setTextDatum(CL_DATUM);
  clk.setTextColor(TFT_BLACK, TFT_WHITE);
  clk.drawString("Node : " + String(node), 0, 10, 2);
  clk.drawString("Humidity : " + String(h), 0, 30, 2);
  clk.drawString("TEMP : " + String(t), 0, 50, 2);
  clk.drawString("Heat Index : " + String(hic), 0, 70, 2);
  clk.drawString(WiFi.localIP().toString().c_str(), 0, 90, 2);
  clk.drawString(WiFi.macAddress(), 0, 110, 2);
  clk.pushSprite(0, 0);
  clk.deleteSprite();
  //上报数据
  drawIndicatorLight(120, 120, TFT_BLACK);
  pushData(String(h), String(t), String(hic), node);
  drawIndicatorLight(120, 120, TFT_WHITE);
  delay(sleepTime);
}


void drawIndicatorLight(int x, int y, uint16_t color) {
  // Draw a filled circle with radius 5
  tft.fillCircle(x, y, 3, color);  
}

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值