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


ESP32-S3-DevKitC-1评估板

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

以下是程序
/**
* 说明要点
* 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服务器,非常方便。
我要赚赏金
