arduino esp32 讀福申甲醛傳感器
-
- 想法
- 源代碼
想法
arduino庫豐富,幾行代碼即可完成需求描述。
缺點是不能Debug。
想持續監測甲醛變化。
使用杜邦線連接配接,需要将傳感器的輸出線焊接杜邦線做轉換。
杜邦線是一公一母。
源代碼
可以開啟軟AP,也可以連到無線路由器。
買到的UNO D1 R32 ,無線性能不好,距離路由器2米,信号強度都到-90多了。
這裡,将網絡改為AP。
#include <HTTPServer.hpp>
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
#include <WebsocketHandler.hpp>
#include <WiFi.h>
#define ESP_getChipId() ((uint32_t)ESP.getEfuseMac())
#define MAX_CLIENTS 4
// http
using namespace httpsserver;
HTTPServer secureServer = HTTPServer();
void handleRoot(HTTPRequest * req, HTTPResponse * res);
char crc(String s);
int data = 0;
float value = 0;
String buffer = "";
String buffer2 = "";
String result;
class ChatHandler : public WebsocketHandler {
public:
static WebsocketHandler* create();
void onClose();
};
ChatHandler* activeClients[MAX_CLIENTS];
void setup() {
// Initialize the slots
for (int i = 0; i < MAX_CLIENTS; i++) activeClients[i] = nullptr;
Serial.begin(9600);
Serial2.begin(9600);
// wifi
IPAddress ip(192, 168, 3, 1);
IPAddress gw(192, 168, 3, 1);
IPAddress mask(255, 255, 255, 0);
WiFi.softAPConfig(ip, gw, mask);
String chip_id = "ESP_" + String(ESP_getChipId());
const char *ssid = chip_id.c_str();
WiFi.softAP(ssid);
// http
ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot);
secureServer.registerNode(nodeRoot);
// chat register
WebsocketNode * chatNode = new WebsocketNode("/chat", &ChatHandler::create);
secureServer.registerNode(chatNode);
secureServer.start();
//
}
void loop() {
// 讀甲醛傳感器
while (Serial2.available() > 0) {
data = Serial2.read();
Serial.println(data);
buffer += (char)data;
buffer2 += String(data, HEX) + " ";
} // while 0
if (buffer.charAt(0) == 0xff && buffer.length() == 9) {
// 驗證crc
char crcValue = crc(buffer);
if (crcValue == buffer.charAt(8))
value = (float)(buffer.charAt(4) * 256 + buffer.charAt(5)) / 1000.0;
else
Serial.println("crc not equal");
buffer = "";
result = "結果:" + String(value) + ",資料:" + buffer2;
buffer2 = "";
} // if 1
if (buffer.length() >= 9)
buffer = "";
Serial2.flush();
// web
secureServer.loop();
// 發送資料
for (int i = 0; i < MAX_CLIENTS; i++) {
if (activeClients[i] != nullptr) {
activeClients[i]->send(result.c_str(), WebsocketHandler::SEND_TYPE_TEXT);
}
}
// delay
delay(100);
// loop
}
void handleRoot(HTTPRequest * req, HTTPResponse * res) {
// Status code is 200 OK by default.
// We want to deliver a simple HTML page, so we send a corresponding content type:
res->setHeader("Content-Type", "text/html");
// The response implements the Print interface, so you can use it just like
// you would write to Serial etc.
res->println("<!DOCTYPE html>");
res->println("<html en\">");
res->println("<head><meta charset=\"UTF-8\"><title>Hello World!</title></head>");
res->println("<body>");
res->println("<h3>甲醛讀數</h3>");
res->print("<p>伺服器已運作 ");
res->print((int)(millis() / 1000 / 60), DEC);
res->println(" 分.</p>");
res->println("<p>數值(毫克/立方米.): </p>");
res->print("<div id=\"id_value\">");
res->print(value, DEC);
res->println("</div>");
res->println("</body>");
res->println("</html>");
res->print(
" <script type=\"text/javascript\">\n"
" const divOut = document.getElementById(\"id_value\");\n"
"\n"
" class Chat {\n"
" constructor() {\n"
" this.connecting = false;\n"
" this.connected = false;\n"
" this.ws = null;\n"
" };\n"
" connect() {\n"
" if (this.ws === null) {\n"
" this.connecting = true;\n"
" this.ws = new WebSocket(\"ws://\" + document.location.host + \"/chat\");\n"
" this.ws.onopen = e => {\n"
" this.connecting = false;\n"
" this.connected = true;\n"
" };\n"
" this.ws.onmessage = e => {\n"
" divOut.innerHTML =\"<p>\"+e.data+\"</p>\";\n"
" //console.log(e.data);\n"
" }\n"
" this.ws.onclose = e => {\n"
" this.disconnect();\n"
" }\n"
" }\n"
" };\n"
" disconnect() {\n"
" if (this.ws !== null) {\n"
" this.ws.close();\n"
" this.ws = null;\n"
" }\n"
" if (this.connected) {\n"
" this.connected = false;\n"
" }\n"
" }};\n"
" let chat = new Chat();\n"
" if (!chat.connected && !chat.connecting) {\n"
" chat.connect();\n"
" }\n"
" </script>\n"
);
}
WebsocketHandler * ChatHandler::create() {
Serial.println("Creating new chat client!");
ChatHandler * handler = new ChatHandler();
for (int i = 0; i < MAX_CLIENTS; i++) {
if (activeClients[i] == nullptr) {
activeClients[i] = handler;
break;
}
}
return handler;
}
// When the websocket is closing, we remove the client from the array
void ChatHandler::onClose() {
for (int i = 0; i < MAX_CLIENTS; i++) {
if (activeClients[i] == this) {
activeClients[i] = nullptr;
}
}
}
// CRC計算
char crc(String s) {
int sum = 0;
for (int i = 1; i < s.length() - 1; i++)
sum += s[i];
int value = ~sum + 1;
return value & 0xff;
}