ESP32(Arduino)+SGP30+ThingsPanel实现远程CO2+TVOC监测 最近学习单片机,发现一个开源的物联网平台,虽然功能不是很完善,但完全够用。把自己目前做的记录一下。实现效果如下图(数据看板以及设备定位,坐标是我随便写的):
主要参考官网给的8266的例子,将代码略微改动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 StaticJsonDocument<200> doc; Adafruit_SGP30 sgp; // WiFi和MQTT设置 const char *ssid = "要连接的wifi名" ; const char *password = "WiFi密码" ; const char* mqtt_server = "参考官网" ; const char* mqtt_user = "参考官网" ; const char* mqtt_password = "" ; // 密码为空 const char* mqtt_topic = "参考官网" ; WiFiClient espClient; PubSubClient client(espClient); void setup () { Serial.begin(9600); // 连接WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("连接WiFi..." ); } Serial.println("已连接到WiFi" ); client.setServer(mqtt_server, 1883); if (!sgp.begin()){ Serial.println("Failed to initialize SGP30 sensor." ); while (1); } sgp.begin(); Serial.println("SGP30 sensor initialized." ); } void loop () { if (!client.connected()) { reconnect(); } client.loop(); if (!sgp.IAQmeasure()) { Serial.println("Measurement failed." ); return ; } Serial.print ("eCO2: " ); Serial.print (sgp.eCO2); Serial.print (" ppm\t" ); Serial.print ("TVOC: " ); Serial.print (sgp.TVOC); Serial.println(" ppb" ); // 使用ArduinoJson生成MQTT消息 StaticJsonDocument<100> doc; doc["eco2" ] = sgp.eCO2; doc["tvoc" ] = sgp.TVOC; char payload[100]; serializeJson(doc, payload); client.publish(mqtt_topic, payload); delay(1000 * 5); // 1秒 } void reconnect () { while (!client.connected()) { Serial.print ("尝试MQTT连接..." ); if (client.connect("ESP32Client" , mqtt_user, mqtt_password)) { Serial.println("已连接" ); } else { Serial.print ("失败, rc=" ); Serial.print (client.state()); Serial.println(" 5秒后再试" ); delay(5000); } } }
上述代码中关于WiFi和MQTT设置大家参考官网文章:
ThingsPanel官网文章
硬件连接部分:准备一个ESP32,一个SGP30传感器,四根杜邦线。
可以监测任何网络覆盖区域的CO2与TVOC值,所有数据实时传输到本地平台。下面是我用Python写的一个串口监视,用于本机监控(用了非常笨拙的方法)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import time import serial import re import datetime import sys import matplotlib.pyplot as plt import keyboard from matplotlib.animation import FuncAnimation plt.rcParams['font.sans-serif' ] = ['SimHei' ] arduino = serial.Serial("COM5" ) CO2 = [] TVOC = [] time1 = [] count = 0while True: bytes_data = arduino.readline() string_data = bytes_data.decode('gbk' ) print (str(string_data)) count = count + 1 if count >= 5: try: values = re.finditer(r'\d+' , string_data) s1 = [] for match in values: s1.append(match.group())#将获取的数字加入临时列表 CO2.append(int(s1[1])) TVOC.append(int(s1[2])) plt.clf() plt.subplot(2, 1, 1) plt.plot(CO2) plt.ylabel("CO2浓度 / ppm" ) plt.subplot(2, 1, 2) plt.plot(TVOC) plt.ylabel("TVOC浓度 / ppb" ) plt.ioff() plt.pause(0.01) except : break
效果:知乎原文