开始做扩展任务
我选择使用3块传感器,分别是SHT40,温湿度传感器、SGP30空气质量传感器、LTR-329 环境光传感器做出来了一块多功能ha传感器,上传数据到HA,通过HA面板显示数据.
SHT40,温湿度传感器
SHT40-Temp
SHT40-humidity
SGP30是一款用于检测室内空气质量的传感器,它能够测量总挥发性有机化合物(TVOC)和等效二氧化碳(eCO2)的浓度,氢气(H2)的原始值,乙醇(Ethanol)的原始值
SGP30-TVOC *.ppb
SGP30-eCO2 *.ppm
SGP30-Raw H2
SGP30-Raw Ethanol
LTR329是一款环境光传感器,能够测量可见光和红外光。该传感器有两个通道,CH0和CH1,它们分别代表:
CH0 (Channel 0):可见光 + 红外光(Visible + IR)
CH1 (Channel 1):红外光(Infrared)
LTR-329-Visible + IR
LTR-329-Infrared
定义一下mqtt主题名称
const char topic1[] = "UNO/arduino/SHT40-Temp/stat_t"; // SHT40温度
const char topic2[] = "UNO/arduino/SHT40-humidity/stat_t"; // SHT40湿度
const char topic3[] = "UNO/arduino/SGP30-TVOC/stat_t"; // SGP30 TVOC
const char topic4[] = "UNO/arduino/SGP30-eCO2/stat_t"; // SGP30 eCO2
const char topic5[] = "UNO/arduino/SGP30-RawH2/stat_t"; // SGP30 原始H2
const char topic6[] = "UNO/arduino/SGP30-RawEthanol/stat_t";// SGP30 原始乙醇
const char topic7[] = "UNO/arduino/LTR329-VisibleIR/stat_t"; // LTR329 可见光+红外光
const char topic8[] = "UNO/arduino/LTR329-Infrared/stat_t"; // LTR329 红外光
const char topic10[] = "UNO/arduino/myAnalogInput/stat_t"; //发布的主题
改一下ha面板中的实体配置
mqtt:
- sensor:
- unique_id: arduino_uno_SHT40_Temp
name: "SHT40 Temp"
state_topic: "UNO/arduino/SHT40-Temp/stat_t"
suggested_display_precision: 1
unit_of_measurement: "°C"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_SHT40_humidity
name: "SHT40 Humidity"
state_topic: "UNO/arduino/SHT40-humidity/stat_t"
suggested_display_precision: 1
unit_of_measurement: "%"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_SGP30_TVOC
name: "SGP30 TVOC"
state_topic: "UNO/arduino/SGP30-TVOC/stat_t"
suggested_display_precision: 0
unit_of_measurement: "ppb"
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_eCO2
name: "SGP30 eCO2"
state_topic: "UNO/arduino/SGP30-eCO2/stat_t"
suggested_display_precision: 0
unit_of_measurement: "ppm"
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_RawH2
name: "SGP30 Raw H2"
state_topic: "UNO/arduino/SGP30-RawH2/stat_t"
suggested_display_precision: 0
unit_of_measurement: ""
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_RawEthanol
name: "SGP30 Raw Ethanol"
state_topic: "UNO/arduino/SGP30-RawEthanol/stat_t"
suggested_display_precision: 0
unit_of_measurement: ""
value_template: "{{ value | int }}"
- unique_id: arduino_uno_LTR329_VisibleIR
name: "LTR329 Visible + IR"
state_topic: "UNO/arduino/LTR329-VisibleIR/stat_t"
suggested_display_precision: 0
unit_of_measurement: "lx"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_LTR329_Infrared
name: "LTR329 Infrared"
state_topic: "UNO/arduino/LTR329-Infrared/stat_t"
suggested_display_precision: 0
unit_of_measurement: "lx"
value_template: "{{ value | float }}"
- unique_id: arduino uno Voltage
name: "arduino Volt"
state_topic: "UNO/arduino/myAnalogInput/stat_t"
suggested_display_precision: 3
unit_of_measurement: "V"
value_template: "{{ value }}"
value_template: "{{ value }}"
- unique_id: arduino uno SGP30-brightness
name: "SGP30-brightness"
state_topic: "UNO/arduino/SGP30-brightness/stat_t"
suggested_display_precision: 1
unit_of_measurement: ".nit"
value_template: "{{ value }}"
- unique_id: arduino uno Voltage
name: "arduino Volt"
state_topic: "UNO/arduino/myAnalogInput/stat_t"
suggested_display_precision: 3
unit_of_measurement: "V"
value_template: "{{ value }}"
下面是arduino的功能实现代码
#include <Wire.h>
#include "Adafruit_SGP30.h"
#include "Adafruit_LTR329_LTR303.h"
#include "Adafruit_SHT4x.h"
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include "arduino_secrets.h"
#include "analogWave.h" // 包含波形输出的模拟文件
Adafruit_SGP30 sgp;
Adafruit_LTR329 ltr = Adafruit_LTR329();
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
//wifi
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "quest2"; // your network SSID (name)
char pass[] = "meiyijia"; // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
analogWave wave(DAC); //实例化一个对象
const char broker[] = "210.38.161.158"; //MQTT服务器地址
int port = 1883; //MQTT服务器端口
const char topic1[] = "UNO/arduino/SHT40-Temp/stat_t"; // SHT40温度
const char topic2[] = "UNO/arduino/SHT40-humidity/stat_t"; // SHT40湿度
const char topic3[] = "UNO/arduino/SGP30-TVOC/stat_t"; // SGP30 TVOC
const char topic4[] = "UNO/arduino/SGP30-eCO2/stat_t"; // SGP30 eCO2
const char topic5[] = "UNO/arduino/SGP30-RawH2/stat_t"; // SGP30 原始H2
const char topic6[] = "UNO/arduino/SGP30-RawEthanol/stat_t";// SGP30 原始乙醇
const char topic7[] = "UNO/arduino/LTR329-VisibleIR/stat_t"; // LTR329 可见光+红外光
const char topic8[] = "UNO/arduino/LTR329-Infrared/stat_t"; // LTR329 红外光
const char topic10[] = "UNO/arduino/myAnalogInput/stat_t"; //发布的主题
const char mqttuser[] = "admin"; //MQTT服务器的用户名
const char mqttpassword[] = "jyu123456"; //MQTT服务器密码
//set interval for sending messages (milliseconds)
const long interval = 8000;
unsigned long previousMillis = 0;
int count = 0;
/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
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);
while (!Serial) { delay(10); } // Wait for serial console to open!
////A0 DAC 输出一个波形
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
// 设置ADC的分辨率
analogReadResolution(14); //change to 14-bit resolution
//wifi
// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// failed, retry
Serial.print(".");
delay(5000);
}
Serial.println("You're connected to the network");
Serial.println();
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
mqttClient.setUsernamePassword(mqttuser, mqttpassword);
while (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
delay(1000);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
//SHT40
Wire1.begin(); //Join I2C bus
if (! sht4.begin(&Wire1)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
//SGP30
Serial.println("SGP30 test");
if (sgp.begin(&Wire1) == false){
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);
// If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
//sgp.setIAQBaseline(0x8E68, 0x8F41); // Will vary for each sensor!
//LTR329
Serial.println("Adafruit LTR-329 advanced test");
if ( ! ltr.begin(&Wire1) ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
Serial.println("Found LTR sensor!");
ltr.setGain(LTR3XX_GAIN_2);
Serial.println("Gain : 2");
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
Serial.println("Integration Time (ms):100 ");
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);
Serial.println("Measurement Rate (ms): 200");
}
int counter = 0;
void loop() {
//ADC
// call poll() regularly to allow the library to send MQTT keep alive which
// avoids being disconnected by the broker
mqttClient.poll();
//通过ADC采集 A0上输出的sin波形
float Rvalue = analogRead(A3) * 4.7/16383; //读取A0引脚的值 A3和 A0连接 14bit ADC采样
mqttClient.beginMessage(topic10);
mqttClient.print(Rvalue); //把读取的值进行上传到MQTT服务器
Serial.println(Rvalue);
mqttClient.endMessage();
//SHT40
sensors_event_t humidity, temp;
uint32_t timestamp = millis();
timestamp = millis() - timestamp;//看循环时间的
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
// Publish SHT40 Temperature-MQTT
mqttClient.beginMessage(topic1);
mqttClient.print(temp.temperature);
mqttClient.endMessage();
// Publish SHT40 Humidity-MQTT
mqttClient.beginMessage(topic2);
mqttClient.print(humidity.relative_humidity);
mqttClient.endMessage();
//温度与湿度
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
//SGP30
// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
//float temperature = 22.1; // [°C]
//float humidity = 45.2; // [%RH]
//sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
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");
// Publish SGP30 TVOC-MQTT
mqttClient.beginMessage(topic3);
mqttClient.print(sgp.TVOC);
mqttClient.endMessage();
// Publish SGP30 eCO2-MQTT
mqttClient.beginMessage(topic4);
mqttClient.print(sgp.eCO2);
mqttClient.endMessage();
if (! sgp.IAQmeasureRaw()) {
Serial.println("Raw Measurement failed");
return;
}
Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");
// Publish SGP30 Raw H2
mqttClient.beginMessage(topic5);
mqttClient.print(sgp.rawH2);
mqttClient.endMessage();
// Publish SGP30 Raw Ethanol
mqttClient.beginMessage(topic6);
mqttClient.print(sgp.rawEthanol);
mqttClient.endMessage();
//看代码循环时间的
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
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);
}
//LTR329
bool valid;
uint16_t visible_plus_ir, infrared;
if (ltr.newDataAvailable()) {
valid = ltr.readBothChannels(visible_plus_ir, infrared);
if (valid) {
Serial.print("CH0 Visible + IR: ");
Serial.print(visible_plus_ir);
Serial.print("\t\tCH1 Infrared: ");
Serial.println(infrared);
// Publish LTR329 Visible + IR
mqttClient.beginMessage(topic7);
mqttClient.print(visible_plus_ir);
mqttClient.endMessage();
// Publish LTR329 Infrared
mqttClient.beginMessage(topic8);
mqttClient.print(infrared);
mqttClient.endMessage();
}
}
//delay(100);
//delay(1000);
}
演示成果:
以下是踩坑
我想使用arduino的Qwiic接口来连接设备的时候怎么都检测不到i2C设备,找了半天发现是
这个实际使用要在begin(&wir1)要加上&才能正常跑通使用板子上的Qwiic接口
我接了三个传感器,分别对应三个库,我把例程缝缝补补出来了一个可以用的代码,在把上一个任务的代码缝合得出上面的那份代码,实现本次功能要求
下面是展示部分
终于接进去了,小小添加几个卡片来展现我的数据
多功能传感器系统
感谢这次follow me的机会,让我成功学习到了U4的功能使用与HA智能家居系统的使用安装,更让我这个网络小白学习并使用了mqtt,谢谢得捷平台提供的机会