这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取逻辑分析仪】+ESP32S3获取环境温湿度、网络时间,以WebServer

共1条 1/1 1 跳转至

【换取逻辑分析仪】+ESP32S3获取环境温湿度、网络时间,以WebServer方式发布数据

专家
2024-09-17 18:08:58   被打赏 48 分(兑奖)     打赏

ESP32S3是一块性能强悍的芯片,这次以搭配ESP32S3的ESP32-S3-DevKitC-1的评估板,开发一个能获取网络时间以及环境温湿度,并以WebSerVer形式发布的测试。

ESP32-S3-DevKitC-1评估板

图片3.png

温湿度传感器GXHT30

因为GXHT30是使用IIC方式访问的,所以要引入wire.h。而为了建立异步方式的WebServer,需要引入ESPAsyncWebSrv.h。

图片4.png

以下是程序

/**
 * 说明要点
 * 1、修改代码中的YOUR_SSID和YOUR_PASSWORD,将其替换为您的Wi-Fi网络凭据。
 * 2、连接GXHT30温湿度传感器,使用GPIO4(SDA)和GPIO5(SCL)
 * 3、编译代码,上传成功后,打开串行监视器。在串行监视器,您应该会看到ESP32连接到Wi-Fi网络的消息。一旦连接成功,它将显示“IP Address:xxx.xxx.xxx.xxx”。
 * 4,在浏览器中输入ESP32的IP地址
 *    可用看到如下输入框,在POST Input中输入需要提交的数据,按「Submit」后,即可在串口监视器中ESP32返回刚才提交的数据。
 * 
 *  post方式:页面上输入数据,点击submit,
 */
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebSrv.h>
#include <Wire.h>
#include <NTPClient.h>
//#include <ArduinoJson.h>  // 为了解析来自心知天气预报的信息
#include "time.h"         // 为了使用tm结构体
// SHT30 IIC 7位地址为0x44
#define Addr_SHT30 0x44
// SHT30引脚连接
#define SDA_PIN 4   //引脚接法在这里    SDA引脚
#define SCL_PIN 5   // SCL引脚
// 登录Wifi的网络名称和密码
const char *ssid     = "YOUR_SSID";
const char *password = "YOUR_PASSWORD";
// 发布网站用变量
AsyncWebServer server(80);
// WIFI是否正常
bool flagWifiOk = false;
float cTemp = 100;      // 环境温度
float humidity = 100;   // 环境湿度
// 存储日期时间信息 
struct tm timeinfo;
int tyear=0;
int tmon=0;
int tmday=0;
int thour=0;
int tmin=0;
int tsec=0;
// 访问网站时的网页,为了实现Post方式,加入了form和submit元素
// 如果不希望显示form,以js方法实现post,可以隐藏form,<div style="display:none">
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head><meta charset="UTF-8">
  <title>ESP Input Form</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  </head><body>
  <div style="display:block">
  <form action="/post" method="POST">
    温度: <input type="text" name="sttime">
    湿度: <input type="text" name="wftime">
    <input type="submit" value="Submit">
  </form>
  </div>
</body></html>)rawliteral";
// 网站地址不匹配时返回给客户端的信息
void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}
// 初始化WenServer,建立响应用的回调函数
void initWebServer(void) {
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        // 返回有post方式的网页
        request->send(200, "text/html", index_html);
    });
    // Send a GET request to <IP>/get?属性=值&属性=值
    // 测试形式:用浏览器访问<ip地址>/get?属性=值&属性=值
    // Hello, GET: hallo
    server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
        // 向客户端发送当前信息:日期、时间、温度信息用
        char myhtml[256]={"\0"};
        const char *fmt = "<!DOCTYPE html><html><body>%04d-%02d-%02d,%02d:%02d%:%02d,%3.1f,%3.1f</body></html>";
        sprintf(myhtml, fmt, tyear, tmon, tmday, thour, tmin, tsec, cTemp, humidity);
        
        // 用于post方式的测试
        int params = request->params();
        for(int i=0;i<params;i++){
          AsyncWebParameter* p = request->getParam(i);
          Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
        }
        request->send(200, "text/html", myhtml);
    });
    // Send a POST request to <IP>/post with a form field message set to <message>
    // 测试形式:用浏览器访问<ip地址>/post?属性=值&属性=值
    // Hello, GET: hallo
    server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request) {
        // 向客户端发送当前信息:日期、时间、温度信息用
        char myhtml[256]={"\0"};
        const char *fmt = "<!DOCTYPE html><html><body>%04d-%02d-%02d,%02d:%02d%:%02d,%3.1f,%3.1f</body></html>";
        sprintf(myhtml, fmt, tyear, tmon, tmday, thour, tmin, tsec, cTemp, humidity);
        // 收取来自客户端的数据,post方式,就是系统设置,比如几点开始浇水,浇多长时间水
        int params = request->params();
        for(int i=0;i<params;i++){
          AsyncWebParameter* p = request->getParam(i);
          Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
        }
        request->send(200, "text/html", myhtml);        
    });
    server.onNotFound(notFound);
    server.begin();
}
// 初始化温湿度传感器
void initSHT30(void) {
  //初始化IIC(作为主设备)
  Wire.begin(SDA_PIN, SCL_PIN);
}
void readSHT30(void) {
  unsigned int data[6]; //存储获取到的六个数据
  //Serial.println("Start readSHT30 ... ");
  //开始IIC
  //写地址
  Wire.beginTransmission(Addr_SHT30);
  //发送测量命令 0x2C06,但是因为IIC一次只能发一个8位数据,所以得发两次
  Wire.write(0x2C);
  Wire.write(0x06);
  //停止IIC
  Wire.endTransmission();
  //等待500ms是等待SHT30器件测量数据,实际上这个时间可以很短
  delay(500);
  //请求获取6字节的数据,然后会存到8266的内存里
  Wire.requestFrom(Addr_SHT30, 6);
  //读取6字节的数据
  //这六个字节分别为:温度8位高数据,温度8位低数据,温度8位CRC校验数据
  //               湿度8位高数据,湿度8位低数据,湿度8位CRC校验数据
  if (Wire.available() == 6) {
    data[0] = Wire.read();
    data[1] = Wire.read();
    data[2] = Wire.read();
    data[3] = Wire.read();
    data[4] = Wire.read();
    data[5] = Wire.read();
  }
  //然后计算得到的数据,要转化为摄氏度、华氏度、相对湿度
  cTemp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
  float fTemp = (cTemp * 1.8) + 32;
  humidity = ((((data[3] * 256.0) + data[4]) * 100) / 65535.0);
  //在串口里输出得到的数据
  Serial.print("相对湿度:");
  Serial.print(humidity);
  Serial.println(" %RH");
  Serial.print("环境温度:");
  Serial.print(cTemp);
  Serial.println(" C");
  //Serial.print("华氏温度:");
  //Serial.print(fTemp);
  //Serial.println(" F");
  
  //Serial.print("原始数据:");
  //Serial.print(data[0],HEX);
  //Serial.print(data[1],HEX);
  //Serial.println(data[2],HEX);
  //Serial.print(data[3],HEX);
  //Serial.print(data[4],HEX);
  //Serial.println(data[5],HEX);
}
// 初始化Wifi
bool initWifi(void) {
  //WiFi.mode(WIFI_STA);   // 这个代码会影响对网络时间的读取
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      Serial.printf("WiFi Failed!\n");
      flagWifiOk = false;
      return false;
  }
  flagWifiOk = true;
  Serial.printf("WiFi Connected!\n");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  
  delay(500);
  configTime(60*60*8, 0, "ntp3.aliyun.com");    // 用的阿里云的服务器
  delay(500);
  return true;
}
void getDatetime(void) {
  //Serial.println("Start getDatetime ... ");
  if(!getLocalTime(&timeinfo))  {
    Serial.println("Failed to obtain time");
    return;
  } else {
    tyear = timeinfo.tm_year+1900;
    tmon = timeinfo.tm_mon+1;
    tmday = timeinfo.tm_mday;
    thour = timeinfo.tm_hour;
    tmin = timeinfo.tm_min;
    tsec = timeinfo.tm_sec;
  }
  //Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
  Serial.println(&timeinfo, "%Y-%m-%d %H:%M:%S");  
}
void setup() {
  Serial.begin(115200);
  if (initWifi()) {
    // 初始化WebServer
    initWebServer();
  }
  // 初始化温湿度传感器
  initSHT30();
}
void loop() {
  // 获取当前时间
  if (flagWifiOk == true) {
    // WIFI正常场合,才允许读取网络时间
    getDatetime();
  }
  // 读取环境温湿度
  if (timeinfo.tm_sec == 0 || cTemp>=100) {
    // 每间隔一分钟读取一次
    readSHT30();
  }
  //delay(60000);
  delay(1000);
}

编译、烧录成功后,可以在电脑、手机等任意可使用浏览器的设备上打开ESP32S3评估板占用的IP地址,获得测试效果。在server.on中可以设置访问网站后返回的网站信息,这个信息可以是一段文字,可以是一个网页。网页可以是动态网页,根据自己的需求建立。这需要有网页编程基础,是与单片机开发完全不同的一种编程语言。有兴趣的,可以自行深入学习。

直接访问网站

Get方式访问(注意浏览器中使用的地址以及串口终端中的输出信息)

Post方式访问(注意浏览器中使用的地址、画面中的输入信息以及串口终端中的输出信息)

点击submit按钮后,提交数据给服务器

串口终端中输出的stttime和sftime名称是网页中那两个文本输入框的name属性:

<input type="text" name="sttime">

<input type="text" name="wftime">

整个程序中除了使用WebServer处理,还有访问外部网站的处理。这个例子中访问的是阿里云网站,目的是获取网络时间。因此需要引入<NTPClient.h>。使用ESP32S3,借助于Arduino丰富的库,可以很轻易地实现网站访问以及建立Web服务器,非常方便。








关键词: ESP32S3     网络     WebServer    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]