mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add support for SHT4X (#1512)
This commit is contained in:
		
							
								
								
									
										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 | ||||
		Reference in New Issue
	
	Block a user