花了周日一个下午把这个环境监测仪项目做完了,遇到不少坑,但这里没时间细谈,只能是把关键的正确部分信息记录下来。
硬件连接
注册部署免费MQTT服务器
部署后,注意获取 mqtt_broker 地址,端口号(8883)并下载CA证书文件(后面要把证书内容复制到代码中)。
然后添加用户:
这里添加的用户名密码都是后面代码中,包括手机客户端中需要使用的。
编译上传代码
注意包含的库,如果缺失就在 arduino 库中寻找。例如 pubsubclient 就是 mqtt 通信需要的库。
完整代码如下,DIY的话注意自行修改配置:
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <Wire.h>
#include <Adafruit_SGP30.h>
// 初始化 DHT 对象
#define DHTPIN 14
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// 定义SGP30实例
#define I2C_SDA 21 // 根据ESP32实际的SDA引脚定义
#define I2C_SCL 23 // 根据ESP32实际的SCL引脚定义
Adafruit_SGP30 sgp;
// WiFi settings
const char *ssid = "CMCC-abc"; // Replace with your WiFi name
const char *password = "abcd1234"; // Replace with your WiFi password
// MQTT Broker settings
const char *mqtt_broker = "fefe.ala.cn-hangzhou.emqxsl.cn"; // EMQX broker endpoint
const char *mqtt_topic = "env/sensor"; // MQTT topic 此为主题, 其它客户端订阅请使用 "env/#"
const char *topic_temp = "env/temperature";
const char *topic_humid = "env/humidity";
const char *topic_co2 = "env/CO2";
const char *topic_voc = "env/TVOC";
const char *mqtt_username = "test"; // MQTT username for authentication
const char *mqtt_password = "654321"; // MQTT password for authentication
const int mqtt_port = 8883; // MQTT port (TLS)
// WiFi and MQTT client initialization
WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);
// SSL certificate for MQTT broker
static const char ca_cert[]
PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqXXDv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";
// Function declarations
void connectToWiFi();
void connectToMQTT();
void syncTime();
void mqttCallback(char *topic, byte *payload, unsigned int length);
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
return absoluteHumidityScaled;
}
void setup() {
Serial.begin(115200);
connectToWiFi();
mqtt_client.setServer(mqtt_broker, mqtt_port);
mqtt_client.setCallback(mqttCallback);
connectToMQTT();
// DHT
Serial.println(F("DHT22 connected successfully!"));
dht.begin();
// 开始I2C通信
Wire.begin(I2C_SDA, I2C_SCL);
if (!sgp.begin(&Wire)) {
Serial.println("Failed to connect SGP30");
while (true); // 停在这里,直到连接成功
}
Serial.println("SGP30 connected successfully!");
}
void connectToWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
void connectToMQTT() {
espClient.setCACert(ca_cert);
while (!mqtt_client.connected()) {
String client_id = "esp32-client-" + String(WiFi.macAddress());
Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT broker");
mqtt_client.subscribe(mqtt_topic);
// Publish message upon successful connection
mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");
} else {
// espClient.getLastSSLError(err_buf, sizeof(err_buf));
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.println(mqtt_client.state());
delay(5000);
}
}
}
void mqttCallback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message received on topic: ");
Serial.print(topic);
Serial.print("]: ");
for (int i = 0; i < length; i++) {
Serial.print((char) payload[i]);
}
Serial.println();
}
void loop() {
if (!mqtt_client.connected()) {
connectToMQTT();
}
mqtt_client.loop();
// 读取湿度
float humid = dht.readHumidity();
// 读取温度
float temp = dht.readTemperature();
// 根据温湿度校正
sgp.setHumidity(getAbsoluteHumidity(temp, humid));
sgp.IAQmeasure();
// 读取和更新CO2与VOC值
float eCO2 = sgp.eCO2;
float TVOC = sgp.TVOC;
// 显示内容
Serial.print("湿度: ");
Serial.print(humid);
Serial.print("%, 温度: ");
Serial.print(temp);
Serial.print("°C,");
Serial.print(" eCO2: ");
Serial.print(eCO2);
Serial.print(" ppm,");
Serial.print(" TVOC: ");
Serial.print(TVOC);
Serial.println(" ppb,");
// 发布内容
char tempString[8];
dtostrf(temp, 5, 1, tempString); // 将温度转换为字符串,保留一位小数
String msg1 = String(tempString) + " °C"; // 整合数字和单位
mqtt_client.publish(topic_temp, msg1.c_str());
char humidString[8];
dtostrf(humid, 5, 1, humidString);
String msg2 = String(humidString) + " %";
mqtt_client.publish(topic_humid, msg2.c_str());
char co2String[9];
dtostrf(eCO2, 7, 1, co2String);
String msg3 = String(co2String) + " ppm";
mqtt_client.publish(topic_co2, msg3.c_str());
char vocString[9];
dtostrf(TVOC, 7, 1, vocString);
String msg4 = String(vocString) + " ppb";
mqtt_client.publish(topic_voc, msg4.c_str());
delay(5000); //时间太长会掉线
}
下载手机客户端
到网上找了一个安卓 MQTT 客户端,简单进行配置,注意填写准确 broker 地址,端口号,加密选择 SSL,以及输入正确的用户名密码,就可以订阅这个环境监测传感器设备每隔 5 秒报送的数据主题了。注意MQTT订阅主题可以使用准确的 env/temperature
之类的,也可以使用通配符如 env/#
。
此处评论已关闭