mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add support for SHT4X (#1512)
This commit is contained in:
		| @@ -80,6 +80,7 @@ esphome/components/rtttl/* @glmnet | |||||||
| esphome/components/script/* @esphome/core | esphome/components/script/* @esphome/core | ||||||
| esphome/components/sensor/* @esphome/core | esphome/components/sensor/* @esphome/core | ||||||
| esphome/components/sgp40/* @SenexCrenshaw | esphome/components/sgp40/* @SenexCrenshaw | ||||||
|  | esphome/components/sht4x/* @sjtrny | ||||||
| esphome/components/shutdown/* @esphome/core | esphome/components/shutdown/* @esphome/core | ||||||
| esphome/components/sim800l/* @glmnet | esphome/components/sim800l/* @glmnet | ||||||
| esphome/components/spi/* @esphome/core | 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' |       id: 'workshop_PMC_10_0' | ||||||
|     address: 0x69 |     address: 0x69 | ||||||
|     update_interval: 10s |     update_interval: 10s | ||||||
|  |   - platform: sht4x | ||||||
|  |     temperature: | ||||||
|  |       name: 'SHT4X Temperature' | ||||||
|  |     humidity: | ||||||
|  |       name: 'SHT4X Humidity' | ||||||
|  |     address: 0x44 | ||||||
|  |     update_interval: 15s | ||||||
|   - platform: shtcx |   - platform: shtcx | ||||||
|     temperature: |     temperature: | ||||||
|       name: 'Living Room Temperature 10' |       name: 'Living Room Temperature 10' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user