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服务器,非常方便。