mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Add support for SHT4X (#1512)
This commit is contained in:
parent
cc43e01e34
commit
7fb116d87d
6 changed files with 234 additions and 0 deletions
|
@ -80,6 +80,7 @@ esphome/components/rtttl/* @glmnet
|
|||
esphome/components/script/* @esphome/core
|
||||
esphome/components/sensor/* @esphome/core
|
||||
esphome/components/sgp40/* @SenexCrenshaw
|
||||
esphome/components/sht4x/* @sjtrny
|
||||
esphome/components/shutdown/* @esphome/core
|
||||
esphome/components/sim800l/* @glmnet
|
||||
esphome/components/spi/* @esphome/core
|
||||
|
|
0
esphome/components/sht4x/__init__.py
Normal file
0
esphome/components/sht4x/__init__.py
Normal file
92
esphome/components/sht4x/sensor.py
Normal file
92
esphome/components/sht4x/sensor.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_HUMIDITY,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_PERCENT,
|
||||
ICON_THERMOMETER,
|
||||
ICON_WATER_PERCENT,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@sjtrny"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
sht4x_ns = cg.esphome_ns.namespace("sht4x")
|
||||
|
||||
SHT4XComponent = sht4x_ns.class_("SHT4XComponent", cg.PollingComponent, i2c.I2CDevice)
|
||||
|
||||
CONF_PRECISION = "precision"
|
||||
SHT4XPRECISION = sht4x_ns.enum("SHT4XPRECISION")
|
||||
PRECISION_OPTIONS = {
|
||||
"High": SHT4XPRECISION.SHT4X_PRECISION_HIGH,
|
||||
"Med": SHT4XPRECISION.SHT4X_PRECISION_MED,
|
||||
"Low": SHT4XPRECISION.SHT4X_PRECISION_LOW,
|
||||
}
|
||||
|
||||
CONF_HEATER_POWER = "heater_power"
|
||||
SHT4XHEATERPOWER = sht4x_ns.enum("SHT4XHEATERPOWER")
|
||||
HEATER_POWER_OPTIONS = {
|
||||
"High": SHT4XHEATERPOWER.SHT4X_HEATERPOWER_HIGH,
|
||||
"Med": SHT4XHEATERPOWER.SHT4X_HEATERPOWER_MED,
|
||||
"Low": SHT4XHEATERPOWER.SHT4X_HEATERPOWER_LOW,
|
||||
}
|
||||
|
||||
CONF_HEATER_TIME = "heater_time"
|
||||
SHT4XHEATERTIME = sht4x_ns.enum("SHT4XHEATERTIME")
|
||||
HEATER_TIME_OPTIONS = {
|
||||
"Long": SHT4XHEATERTIME.SHT4X_HEATERTIME_LONG,
|
||||
"Short": SHT4XHEATERTIME.SHT4X_HEATERTIME_SHORT,
|
||||
}
|
||||
|
||||
CONF_HEATER_MAX_DUTY = "heater_max_duty"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SHT4XComponent),
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
UNIT_CELSIUS, ICON_THERMOMETER, 2, DEVICE_CLASS_TEMPERATURE
|
||||
),
|
||||
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||
UNIT_PERCENT, ICON_WATER_PERCENT, 2, DEVICE_CLASS_HUMIDITY
|
||||
),
|
||||
cv.Optional(CONF_PRECISION, default="High"): cv.enum(PRECISION_OPTIONS),
|
||||
cv.Optional(CONF_HEATER_POWER, default="High"): cv.enum(
|
||||
HEATER_POWER_OPTIONS
|
||||
),
|
||||
cv.Optional(CONF_HEATER_TIME, default="Long"): cv.enum(HEATER_TIME_OPTIONS),
|
||||
cv.Optional(CONF_HEATER_MAX_DUTY, default=0.0): cv.float_range(
|
||||
min=0.0, max=0.05
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x44))
|
||||
)
|
||||
|
||||
TYPES = {
|
||||
CONF_TEMPERATURE: "set_temp_sensor",
|
||||
CONF_HUMIDITY: "set_humidity_sensor",
|
||||
}
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield i2c.register_i2c_device(var, config)
|
||||
|
||||
cg.add(var.set_precision_value(config[CONF_PRECISION]))
|
||||
cg.add(var.set_heater_power_value(config[CONF_HEATER_POWER]))
|
||||
cg.add(var.set_heater_time_value(config[CONF_HEATER_TIME]))
|
||||
cg.add(var.set_heater_duty_value(config[CONF_HEATER_MAX_DUTY]))
|
||||
|
||||
for key, funcName in TYPES.items():
|
||||
|
||||
if key in config:
|
||||
sens = yield sensor.new_sensor(config[key])
|
||||
cg.add(getattr(var, funcName)(sens))
|
89
esphome/components/sht4x/sht4x.cpp
Normal file
89
esphome/components/sht4x/sht4x.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "sht4x.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sht4x {
|
||||
|
||||
static const char *TAG = "sht4x";
|
||||
|
||||
static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0};
|
||||
|
||||
void SHT4XComponent::start_heater_() {
|
||||
uint8_t cmd[] = {MEASURECOMMANDS[this->heater_command_]};
|
||||
|
||||
ESP_LOGD(TAG, "Heater turning on");
|
||||
this->write_bytes_raw(cmd, 1);
|
||||
}
|
||||
|
||||
void SHT4XComponent::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up sht4x...");
|
||||
|
||||
if (this->duty_cycle_ > 0.0) {
|
||||
uint32_t heater_interval = (uint32_t)(this->heater_time_ / this->duty_cycle_);
|
||||
ESP_LOGD(TAG, "Heater interval: %i", heater_interval);
|
||||
|
||||
if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) {
|
||||
if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
|
||||
this->heater_command_ = 0x39;
|
||||
} else {
|
||||
this->heater_command_ = 0x32;
|
||||
}
|
||||
} else if (this->heater_power_ == SHT4X_HEATERPOWER_MED) {
|
||||
if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
|
||||
this->heater_command_ = 0x2F;
|
||||
} else {
|
||||
this->heater_command_ = 0x24;
|
||||
}
|
||||
} else {
|
||||
if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
|
||||
this->heater_command_ = 0x1E;
|
||||
} else {
|
||||
this->heater_command_ = 0x15;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "Heater command: %x", this->heater_command_);
|
||||
|
||||
this->set_interval(heater_interval, std::bind(&SHT4XComponent::start_heater_, this));
|
||||
}
|
||||
}
|
||||
|
||||
void SHT4XComponent::dump_config() { LOG_I2C_DEVICE(this); }
|
||||
|
||||
void SHT4XComponent::update() {
|
||||
uint8_t cmd[] = {MEASURECOMMANDS[this->precision_]};
|
||||
|
||||
// Send command
|
||||
this->write_bytes_raw(cmd, 1);
|
||||
|
||||
this->set_timeout(10, [this]() {
|
||||
const uint8_t num_bytes = 6;
|
||||
uint8_t buffer[num_bytes];
|
||||
|
||||
// Read measurement
|
||||
bool read_status = this->read_bytes_raw(buffer, num_bytes);
|
||||
|
||||
if (read_status) {
|
||||
// Evaluate and publish measurements
|
||||
if (this->temp_sensor_ != nullptr) {
|
||||
// Temp is contained in the first 16 bits
|
||||
float sensor_value_temp = (buffer[0] << 8) + buffer[1];
|
||||
float temp = -45 + 175 * sensor_value_temp / 65535;
|
||||
|
||||
this->temp_sensor_->publish_state(temp);
|
||||
}
|
||||
|
||||
if (this->humidity_sensor_ != nullptr) {
|
||||
// Relative humidity is in the last 16 bits
|
||||
float sensor_value_rh = (buffer[3] << 8) + buffer[4];
|
||||
float rh = -6 + 125 * sensor_value_rh / 65535;
|
||||
|
||||
this->humidity_sensor_->publish_state(rh);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Sensor read failed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace sht4x
|
||||
} // namespace esphome
|
45
esphome/components/sht4x/sht4x.h
Normal file
45
esphome/components/sht4x/sht4x.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sht4x {
|
||||
|
||||
enum SHT4XPRECISION { SHT4X_PRECISION_HIGH = 0, SHT4X_PRECISION_MED, SHT4X_PRECISION_LOW };
|
||||
|
||||
enum SHT4XHEATERPOWER { SHT4X_HEATERPOWER_HIGH, SHT4X_HEATERPOWER_MED, SHT4X_HEATERPOWER_LOW };
|
||||
|
||||
enum SHT4XHEATERTIME { SHT4X_HEATERTIME_LONG = 1100, SHT4X_HEATERTIME_SHORT = 110 };
|
||||
|
||||
class SHT4XComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void update() override;
|
||||
|
||||
void set_precision_value(SHT4XPRECISION precision) { this->precision_ = precision; };
|
||||
void set_heater_power_value(SHT4XHEATERPOWER heater_power) { this->heater_power_ = heater_power; };
|
||||
void set_heater_time_value(SHT4XHEATERTIME heater_time) { this->heater_time_ = heater_time; };
|
||||
void set_heater_duty_value(float duty_cycle) { this->duty_cycle_ = duty_cycle; };
|
||||
|
||||
void set_temp_sensor(sensor::Sensor *temp_sensor) { this->temp_sensor_ = temp_sensor; }
|
||||
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
|
||||
|
||||
protected:
|
||||
SHT4XPRECISION precision_;
|
||||
SHT4XHEATERPOWER heater_power_;
|
||||
SHT4XHEATERTIME heater_time_;
|
||||
float duty_cycle_;
|
||||
|
||||
void start_heater_();
|
||||
uint8_t heater_command_;
|
||||
|
||||
sensor::Sensor *temp_sensor_{nullptr};
|
||||
sensor::Sensor *humidity_sensor_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace sht4x
|
||||
} // namespace esphome
|
|
@ -741,6 +741,13 @@ sensor:
|
|||
id: 'workshop_PMC_10_0'
|
||||
address: 0x69
|
||||
update_interval: 10s
|
||||
- platform: sht4x
|
||||
temperature:
|
||||
name: 'SHT4X Temperature'
|
||||
humidity:
|
||||
name: 'SHT4X Humidity'
|
||||
address: 0x44
|
||||
update_interval: 15s
|
||||
- platform: shtcx
|
||||
temperature:
|
||||
name: 'Living Room Temperature 10'
|
||||
|
|
Loading…
Reference in a new issue