Refactor Sensirion Sensors (#3374)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Martin
2022-04-13 00:19:48 +02:00
committed by GitHub
parent 99335d986e
commit d620b6dd5e
36 changed files with 484 additions and 718 deletions
+9 -4
View File
@@ -1,10 +1,13 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
from esphome.components import i2c, sensor, sensirion_common
from esphome.const import (
CONF_ID,
CONF_BASELINE,
CONF_ECO2,
CONF_STORE_BASELINE,
CONF_TEMPERATURE_SOURCE,
CONF_TVOC,
ICON_RADIATOR,
DEVICE_CLASS_CARBON_DIOXIDE,
@@ -17,17 +20,19 @@ from esphome.const import (
)
DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["sensirion_common"]
sgp30_ns = cg.esphome_ns.namespace("sgp30")
SGP30Component = sgp30_ns.class_("SGP30Component", cg.PollingComponent, i2c.I2CDevice)
SGP30Component = sgp30_ns.class_(
"SGP30Component", cg.PollingComponent, sensirion_common.SensirionI2CDevice
)
CONF_ECO2_BASELINE = "eco2_baseline"
CONF_TVOC_BASELINE = "tvoc_baseline"
CONF_STORE_BASELINE = "store_baseline"
CONF_UPTIME = "uptime"
CONF_COMPENSATION = "compensation"
CONF_HUMIDITY_SOURCE = "humidity_source"
CONF_TEMPERATURE_SOURCE = "temperature_source"
CONFIG_SCHEMA = (
cv.Schema(
+9 -70
View File
@@ -36,14 +36,8 @@ void SGP30Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up SGP30...");
// Serial Number identification
if (!this->write_command_(SGP30_CMD_GET_SERIAL_ID)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
uint16_t raw_serial_number[3];
if (!this->read_data_(raw_serial_number, 3)) {
if (!this->get_register(SGP30_CMD_GET_SERIAL_ID, raw_serial_number, 3)) {
this->mark_failed();
return;
}
@@ -52,16 +46,12 @@ void SGP30Component::setup() {
ESP_LOGD(TAG, "Serial Number: %" PRIu64, this->serial_number_);
// Featureset identification for future use
if (!this->write_command_(SGP30_CMD_GET_FEATURESET)) {
uint16_t raw_featureset;
if (!this->get_register(SGP30_CMD_GET_FEATURESET, raw_featureset)) {
this->mark_failed();
return;
}
uint16_t raw_featureset[1];
if (!this->read_data_(raw_featureset, 1)) {
this->mark_failed();
return;
}
this->featureset_ = raw_featureset[0];
this->featureset_ = raw_featureset;
if (uint16_t(this->featureset_ >> 12) != 0x0) {
if (uint16_t(this->featureset_ >> 12) == 0x1) {
// ID matching a different sensor: SGPC3
@@ -76,7 +66,7 @@ void SGP30Component::setup() {
ESP_LOGD(TAG, "Product version: 0x%0X", uint16_t(this->featureset_ & 0x1FF));
// Sensor initialization
if (!this->write_command_(SGP30_CMD_IAQ_INIT)) {
if (!this->write_command(SGP30_CMD_IAQ_INIT)) {
ESP_LOGE(TAG, "Sensor sgp30_iaq_init failed.");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->mark_failed();
@@ -119,14 +109,14 @@ bool SGP30Component::is_sensor_baseline_reliable_() {
void SGP30Component::read_iaq_baseline_() {
if (this->is_sensor_baseline_reliable_()) {
if (!this->write_command_(SGP30_CMD_GET_IAQ_BASELINE)) {
if (!this->write_command(SGP30_CMD_GET_IAQ_BASELINE)) {
ESP_LOGD(TAG, "Error getting baseline");
this->status_set_warning();
return;
}
this->set_timeout(50, [this]() {
uint16_t raw_data[2];
if (!this->read_data_(raw_data, 2)) {
if (!this->read_data(raw_data, 2)) {
this->status_set_warning();
return;
}
@@ -274,14 +264,14 @@ void SGP30Component::dump_config() {
}
void SGP30Component::update() {
if (!this->write_command_(SGP30_CMD_MEASURE_IAQ)) {
if (!this->write_command(SGP30_CMD_MEASURE_IAQ)) {
this->status_set_warning();
return;
}
this->seconds_since_last_store_ += this->update_interval_ / 1000;
this->set_timeout(50, [this]() {
uint16_t raw_data[2];
if (!this->read_data_(raw_data, 2)) {
if (!this->read_data(raw_data, 2)) {
this->status_set_warning();
return;
}
@@ -305,56 +295,5 @@ void SGP30Component::update() {
});
}
bool SGP30Component::write_command_(uint16_t command) {
// Warning ugly, trick the I2Ccomponent base by setting register to the first 8 bit.
return this->write_byte(command >> 8, command & 0xFF);
}
uint8_t SGP30Component::sht_crc_(uint8_t data1, uint8_t data2) {
uint8_t bit;
uint8_t crc = 0xFF;
crc ^= data1;
for (bit = 8; bit > 0; --bit) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x131;
} else {
crc = (crc << 1);
}
}
crc ^= data2;
for (bit = 8; bit > 0; --bit) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x131;
} else {
crc = (crc << 1);
}
}
return crc;
}
bool SGP30Component::read_data_(uint16_t *data, uint8_t len) {
const uint8_t num_bytes = len * 3;
std::vector<uint8_t> buf(num_bytes);
if (this->read(buf.data(), num_bytes) != i2c::ERROR_OK) {
return false;
}
for (uint8_t i = 0; i < len; i++) {
const uint8_t j = 3 * i;
uint8_t crc = sht_crc_(buf[j], buf[j + 1]);
if (crc != buf[j + 2]) {
ESP_LOGE(TAG, "CRC8 Checksum invalid! 0x%02X != 0x%02X", buf[j + 2], crc);
return false;
}
data[i] = (buf[j] << 8) | buf[j + 1];
}
return true;
}
} // namespace sgp30
} // namespace esphome
+2 -5
View File
@@ -2,7 +2,7 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensirion_common/i2c_sensirion.h"
#include "esphome/core/preferences.h"
#include <cmath>
@@ -15,7 +15,7 @@ struct SGP30Baselines {
} PACKED;
/// This class implements support for the Sensirion SGP30 i2c GAS (VOC and CO2eq) sensors.
class SGP30Component : public PollingComponent, public i2c::I2CDevice {
class SGP30Component : public PollingComponent, public sensirion_common::SensirionI2CDevice {
public:
void set_eco2_sensor(sensor::Sensor *eco2) { eco2_sensor_ = eco2; }
void set_tvoc_sensor(sensor::Sensor *tvoc) { tvoc_sensor_ = tvoc; }
@@ -33,13 +33,10 @@ class SGP30Component : public PollingComponent, public i2c::I2CDevice {
float get_setup_priority() const override { return setup_priority::DATA; }
protected:
bool write_command_(uint16_t command);
bool read_data_(uint16_t *data, uint8_t len);
void send_env_data_();
void read_iaq_baseline_();
bool is_sensor_baseline_reliable_();
void write_iaq_baseline_(uint16_t eco2_baseline, uint16_t tvoc_baseline);
uint8_t sht_crc_(uint8_t data1, uint8_t data2);
uint64_t serial_number_;
uint16_t featureset_;
uint32_t required_warm_up_time_;