一、前言
在电子森林举办的Funpack第五期活动中,我有幸选择并学习了Arduino UNO R4 WiFi板。这款板卡不仅拥有强大的计算能力和丰富的连接选项,还集成了ESP32模块,实现了Wi-Fi与蓝牙的无缝连接,为物联网项目提供了极大的便利。在本次活动中,我选择了“任务2:搭配传感器,并通过网络连接到智能云端,从远程获取传感器的信息”作为我的目标任务,并决定使用SGP30传感器来完成这一任务。
二、硬件介绍
2.1 Arduino UNO R4 WiFi板
Arduino UNO R4 WiFi板搭载了32位Arm® Cortex®-M4 Renesas RA4M1微控制器,并配备了先进的USB-C接口和高达24V的电源供应电压。其板载的ESP32模块使得Wi-Fi和蓝牙连接变得轻而易举,而32kB的SRAM和256kB的闪存则为其提供了卓越的性能。此外,板载的Qwiic连接器使得项目创建更加轻松快捷,用户只需通过即插即用的方式即可连接各种传感器和模块。
2.2 SGP30传感器模块
SGP30传感器模块是一款用于室内空气质量监测的数字传感器,它能够同时测量空气中的二氧化碳(CO₂)浓度和挥发性有机化合物(VOC)的浓度。该传感器通过I²C接口进行通信,并提供了高精度的测量结果。其低功耗设计使得它非常适合在电池供电的系统中使用,而小巧的体积则使得它易于集成到各种项目和设备中。通过SGP30传感器,我们可以实时了解室内空气质量,为人们的健康和生活质量提供保障。
三、传感器连接与测试
3.1 传感器连接
首先,我们需要将SGP30传感器模块连接到Arduino UNO R4 WiFi板上。由于SGP30传感器模块的I²C接口通信电平为3.3V,而供电电压为5V,因此我们需要通过杜邦线选择合适的引脚进行连接,并确保接口电平匹配。
连接完成后,我们可以开始编写代码进行测试。
3.2 接口测试
为了测试SGP30传感器模块的工作状态,我们编写了以下Arduino代码:
#include <Wire.h>
#include "Adafruit_SGP30.h"
Adafruit_SGP30 sgp;
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() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) { delay(10); } // Wait for serial console to open!
Serial.println("SGP30 test");
if (! sgp.begin()){
Serial.println("Sensor not found :(");
while (1);
}
Serial.print("Found SGP30 serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);
}
int counter = 0;
void loop() {
// put your main code here, to run repeatedly:
if (! sgp.IAQmeasure()) {
Serial.println("Measurement failed");
return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
delay(1000);
counter++;
if (counter == 30) {
counter = 0;
uint16_t TVOC_base, eCO2_base;
if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
Serial.println("Failed to get baseline readings");
return;
}
Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
}
}
将上述代码上传到Arduino板卡后,我们可以打开串口监视器,观察SGP30传感器模块发送的CO₂和VOC浓度数据。如果一切正常,我们将看到串口监视器上不断显示更新的浓度数据:
四、WiFi与MQTT配置
为了实现将传感器数据上传到云端的功能,我们需要配置WiFi和MQTT。以下是配置过程的代码示例:
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
char ssid[] = "your_SSID"; // 替换为你的WiFi名称
char pass[] = "your_PASSWORD"; // 替换为你的WiFi密码
const char broker[] = "your_MQTT_broker"; // 替换为你的MQTT broker地址
int port = 1883;
const char state_topic[] = "homeassistant/sensor/RoomSGP30/state";
JSONVar JSONdata;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("connect to WPA SSID: ");
Serial.println(ssid);
// attempt to connect to WiFi network:
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
Serial.print("......");
delay(5000);
}
Serial.println(WiFi.localIP());
mqttClient.setId("clientId");
mqttClient.setUsernamePassword("admin", "admin");
Serial.print("connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("connected to the MQTT succeed!");
Serial.println();
}
在setup()函数中,我们首先等待串口连接,然后尝试连接到WiFi网络。一旦连接成功,我们打印出本地IP地址,并配置MQTT客户端的ID和用户名/密码。最后,我们尝试连接到MQTT broker,并在连接成功后进入loop()函数。
五、数据上传与整合
在loop()函数中,我们需要周期性地读取SGP30传感器的数据,并将其上传到MQTT broker。以下是完整的代码示例:
int counter = 0;
void loop() {
// put your main code here, to run repeatedly:
if (! sgp.IAQmeasure()) {
Serial.println("Measurement failed");
return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
JSONdata["eCO2"] = round(sgp.eCO2);
JSONdata["TVOC"] = round(sgp.TVOC);
String jsonString = JSON.stringify(JSONdata);
mqttClient.beginMessage(state_topic);
mqttClient.print(jsonString);
mqttClient.endMessage();
delay(1000);
counter++;
if (counter == 30) {
counter = 0;
uint16_t TVOC_base, eCO2_base;
if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
Serial.println("Failed to get baseline readings");
return;
}
Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
}
}
在loop()函数中,我们首先调用mqttClient.poll()来处理MQTT消息队列中的任何待处理消息。然后,我们读取SGP30传感器的数据,并将其存储到变量sgp.eCO2和sgp.TVOC中。接着,我们使用Arduino_JSON库将数据转换为JSON格式,并通过MQTT客户端将其发送到指定的主题上。最后,我们设置一个1秒的延时,以便在下一次循环中重复此过程。
云端显示如下:
六、总结与展望
通过本次Funpack活动,我真的学到了很多关于Arduino UNO R4 WiFi板和SGP30传感器的知识。我希望未来能够继续在物联网领域深耕,探索更多新技术和新应用,为人们的生活带来更多便利和惊喜。也希望论坛可以多多组织这样的学习活动。