mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add support for TMP1075 temperature sensor (#4776)
* Add support for TMP1075 temperature sensor TMP1075 is a temperature sensor with I2C interface in industry standard LM75 form factor and pinout. https://www.ti.com/product/TMP1075 Example YAML: ```yaml sensor: - platform: tmp1075 name: TMP1075 Temperature id: radiator_temp update_interval: 10s i2c_id: i2c_bus_1 conversion_rate: 27.5ms alert: limit_low: 50 limit_high: 75 fault_count: 1 polarity: active_high ``` * Add myself as codeowner of the TMP1075 component * Include '°C' unit when logging low/high limit setting * Reformat No functional changes. * Fix logging: use %.4f for temperatures, not %d * Fix config initialisation * Use relative include for `tmp1075.h` * Apply formatting changes suggested by script/clang-tidy for ESP32 * Add YAML to test1.yaml * Fix test1.yaml by giving TMP1075 a name * Less verbose logging (debug -> verbose level) * Schema: reduce accuracy_decimals to 2 * I2C address as hexadecimal * Proper name for enum in Python The enum on the C++ side was renamed (clang-tidy) but I forgot to take that into account in the Python code. * Expose 'alert function' to the code generator/YAML params and remove 'shutdown' Shutdown mode doesn't work the way I expect it, so remove it until someone actually asks for it. Also 'alert mode' was renamed to 'alert function' for clarity. * Move simple setters to header file * Remove `load_config_();` function
This commit is contained in:
		
							
								
								
									
										1
									
								
								esphome/components/tmp1075/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								esphome/components/tmp1075/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| CODEOWNERS = ["@sybrenstuvel"] | ||||
							
								
								
									
										92
									
								
								esphome/components/tmp1075/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								esphome/components/tmp1075/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 ( | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     STATE_CLASS_MEASUREMENT, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_THERMOMETER, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| tmp1075_ns = cg.esphome_ns.namespace("tmp1075") | ||||
|  | ||||
| TMP1075Sensor = tmp1075_ns.class_( | ||||
|     "TMP1075Sensor", cg.PollingComponent, sensor.Sensor, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| EConversionRate = tmp1075_ns.enum("EConversionRate") | ||||
| CONVERSION_RATES = { | ||||
|     "27.5ms": EConversionRate.CONV_RATE_27_5_MS, | ||||
|     "55ms": EConversionRate.CONV_RATE_55_MS, | ||||
|     "110ms": EConversionRate.CONV_RATE_110_MS, | ||||
|     "220ms": EConversionRate.CONV_RATE_220_MS, | ||||
| } | ||||
|  | ||||
| POLARITY = { | ||||
|     "ACTIVE_LOW": 0, | ||||
|     "ACTIVE_HIGH": 1, | ||||
| } | ||||
|  | ||||
| EAlertFunction = tmp1075_ns.enum("EAlertFunction") | ||||
| ALERT_FUNCTION = { | ||||
|     "COMPARATOR": EAlertFunction.ALERT_COMPARATOR, | ||||
|     "INTERRUPT": EAlertFunction.ALERT_INTERRUPT, | ||||
| } | ||||
|  | ||||
| CONF_ALERT = "alert" | ||||
| CONF_LIMIT_LOW = "limit_low" | ||||
| CONF_LIMIT_HIGH = "limit_high" | ||||
| CONF_FAULT_COUNT = "fault_count" | ||||
| CONF_POLARITY = "polarity" | ||||
| CONF_CONVERSION_RATE = "conversion_rate" | ||||
| CONF_FUNCTION = "function" | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema( | ||||
|         TMP1075Sensor, | ||||
|         unit_of_measurement=UNIT_CELSIUS, | ||||
|         icon=ICON_THERMOMETER, | ||||
|         accuracy_decimals=2, | ||||
|         device_class=DEVICE_CLASS_TEMPERATURE, | ||||
|         state_class=STATE_CLASS_MEASUREMENT, | ||||
|     ) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.Optional(CONF_CONVERSION_RATE): cv.enum(CONVERSION_RATES, lower=True), | ||||
|             cv.Optional(CONF_ALERT, default={}): cv.Schema( | ||||
|                 { | ||||
|                     cv.Optional(CONF_LIMIT_LOW): cv.temperature, | ||||
|                     cv.Optional(CONF_LIMIT_HIGH): cv.temperature, | ||||
|                     cv.Optional(CONF_FAULT_COUNT): cv.int_range(min=1, max=4), | ||||
|                     cv.Optional(CONF_POLARITY): cv.enum(POLARITY, upper=True), | ||||
|                     cv.Optional(CONF_FUNCTION): cv.enum(ALERT_FUNCTION, upper=True), | ||||
|                 } | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x48)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = await sensor.new_sensor(config) | ||||
|     await cg.register_component(var, config) | ||||
|     await i2c.register_i2c_device(var, config) | ||||
|  | ||||
|     if CONF_CONVERSION_RATE in config: | ||||
|         cg.add(var.set_conversion_rate(config[CONF_CONVERSION_RATE])) | ||||
|  | ||||
|     alert = config[CONF_ALERT] | ||||
|     if CONF_LIMIT_LOW in alert: | ||||
|         cg.add(var.set_alert_limit_low(alert[CONF_LIMIT_LOW])) | ||||
|     if CONF_LIMIT_HIGH in alert: | ||||
|         cg.add(var.set_alert_limit_high(alert[CONF_LIMIT_HIGH])) | ||||
|     if CONF_FAULT_COUNT in alert: | ||||
|         cg.add(var.set_fault_count(alert[CONF_FAULT_COUNT])) | ||||
|     if CONF_POLARITY in alert: | ||||
|         cg.add(var.set_alert_polarity(alert[CONF_POLARITY])) | ||||
|     if CONF_FUNCTION in alert: | ||||
|         cg.add(var.set_alert_function(alert[CONF_FUNCTION])) | ||||
							
								
								
									
										129
									
								
								esphome/components/tmp1075/tmp1075.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								esphome/components/tmp1075/tmp1075.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| #include "esphome/core/log.h" | ||||
| #include "tmp1075.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace tmp1075 { | ||||
|  | ||||
| static const char *const TAG = "tmp1075"; | ||||
|  | ||||
| constexpr uint8_t REG_TEMP = 0x0;   // Temperature result | ||||
| constexpr uint8_t REG_CFGR = 0x1;   // Configuration | ||||
| constexpr uint8_t REG_LLIM = 0x2;   // Low limit | ||||
| constexpr uint8_t REG_HLIM = 0x3;   // High limit | ||||
| constexpr uint8_t REG_DIEID = 0xF;  // Device ID | ||||
|  | ||||
| constexpr uint16_t EXPECT_DIEID = 0x0075;  // Expected Device ID. | ||||
|  | ||||
| static uint16_t temp2regvalue(float temp); | ||||
| static float regvalue2temp(uint16_t regvalue); | ||||
|  | ||||
| void TMP1075Sensor::setup() { | ||||
|   uint8_t die_id; | ||||
|   if (!this->read_byte(REG_DIEID, &die_id)) { | ||||
|     ESP_LOGW(TAG, "'%s' - unable to read ID", this->name_.c_str()); | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } | ||||
|   if (die_id != EXPECT_DIEID) { | ||||
|     ESP_LOGW(TAG, "'%s' - unexpected ID 0x%x found, expected 0x%x", this->name_.c_str(), die_id, EXPECT_DIEID); | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   this->write_config(); | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::update() { | ||||
|   uint16_t regvalue; | ||||
|   if (!read_byte_16(REG_TEMP, ®value)) { | ||||
|     ESP_LOGW(TAG, "'%s' - unable to read temperature register", this->name_.c_str()); | ||||
|     this->status_set_warning(); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   const float temp = regvalue2temp(regvalue); | ||||
|   this->publish_state(temp); | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::dump_config() { | ||||
|   LOG_SENSOR("", "TMP1075 Sensor", this); | ||||
|   if (this->is_failed()) { | ||||
|     ESP_LOGE(TAG, "  Communication with TMP1075 failed!"); | ||||
|     return; | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  limit low  : %.4f °C", alert_limit_low_); | ||||
|   ESP_LOGCONFIG(TAG, "  limit high : %.4f °C", alert_limit_high_); | ||||
|   ESP_LOGCONFIG(TAG, "  oneshot    : %d", config_.fields.oneshot); | ||||
|   ESP_LOGCONFIG(TAG, "  rate       : %d", config_.fields.rate); | ||||
|   ESP_LOGCONFIG(TAG, "  fault_count: %d", config_.fields.faults); | ||||
|   ESP_LOGCONFIG(TAG, "  polarity   : %d", config_.fields.polarity); | ||||
|   ESP_LOGCONFIG(TAG, "  alert_mode : %d", config_.fields.alert_mode); | ||||
|   ESP_LOGCONFIG(TAG, "  shutdown   : %d", config_.fields.shutdown); | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::set_fault_count(const int faults) { | ||||
|   if (faults < 1) { | ||||
|     ESP_LOGE(TAG, "'%s' - fault_count too low: %d", this->name_.c_str(), faults); | ||||
|     return; | ||||
|   } | ||||
|   if (faults > 4) { | ||||
|     ESP_LOGE(TAG, "'%s' - fault_count too high: %d", this->name_.c_str(), faults); | ||||
|     return; | ||||
|   } | ||||
|   config_.fields.faults = faults - 1; | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::log_config_() { | ||||
|   ESP_LOGV(TAG, "  oneshot   : %d", config_.fields.oneshot); | ||||
|   ESP_LOGV(TAG, "  rate      : %d", config_.fields.rate); | ||||
|   ESP_LOGV(TAG, "  faults    : %d", config_.fields.faults); | ||||
|   ESP_LOGV(TAG, "  polarity  : %d", config_.fields.polarity); | ||||
|   ESP_LOGV(TAG, "  alert_mode: %d", config_.fields.alert_mode); | ||||
|   ESP_LOGV(TAG, "  shutdown  : %d", config_.fields.shutdown); | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::write_config() { | ||||
|   send_alert_limit_low_(); | ||||
|   send_alert_limit_high_(); | ||||
|   send_config_(); | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::send_config_() { | ||||
|   ESP_LOGV(TAG, "'%s' - sending configuration %04x", this->name_.c_str(), config_.regvalue); | ||||
|   log_config_(); | ||||
|   if (!this->write_byte_16(REG_CFGR, config_.regvalue)) { | ||||
|     ESP_LOGW(TAG, "'%s' - unable to write configuration register", this->name_.c_str()); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::send_alert_limit_low_() { | ||||
|   ESP_LOGV(TAG, "'%s' - sending alert limit low %.3f °C", this->name_.c_str(), alert_limit_low_); | ||||
|   const uint16_t regvalue = temp2regvalue(alert_limit_low_); | ||||
|   if (!this->write_byte_16(REG_LLIM, regvalue)) { | ||||
|     ESP_LOGW(TAG, "'%s' - unable to write low limit register", this->name_.c_str()); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void TMP1075Sensor::send_alert_limit_high_() { | ||||
|   ESP_LOGV(TAG, "'%s' - sending alert limit high %.3f °C", this->name_.c_str(), alert_limit_high_); | ||||
|   const uint16_t regvalue = temp2regvalue(alert_limit_high_); | ||||
|   if (!this->write_byte_16(REG_HLIM, regvalue)) { | ||||
|     ESP_LOGW(TAG, "'%s' - unable to write high limit register", this->name_.c_str()); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static uint16_t temp2regvalue(const float temp) { | ||||
|   const uint16_t regvalue = temp / 0.0625f; | ||||
|   return regvalue << 4; | ||||
| } | ||||
|  | ||||
| static float regvalue2temp(const uint16_t regvalue) { | ||||
|   const int16_t signed_value = regvalue; | ||||
|   return (signed_value >> 4) * 0.0625f; | ||||
| } | ||||
|  | ||||
| }  // namespace tmp1075 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										92
									
								
								esphome/components/tmp1075/tmp1075.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								esphome/components/tmp1075/tmp1075.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/components/i2c/i2c.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #include "esphome/core/component.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace tmp1075 { | ||||
|  | ||||
| struct TMP1075Config { | ||||
|   union { | ||||
|     struct { | ||||
|       uint8_t oneshot : 1;  // One-shot conversion mode. Writing 1, starts a single temperature | ||||
|                             // conversion. Read returns 0. | ||||
|  | ||||
|       uint8_t rate : 2;  // Conversion rate setting when device is in continuous conversion mode. | ||||
|                          // 00: 27.5 ms conversion rate | ||||
|                          // 01: 55 ms conversion rate | ||||
|                          // 10: 110 ms conversion rate | ||||
|                          // 11: 220 ms conversion rate (35 ms TMP1075N) | ||||
|  | ||||
|       uint8_t faults : 2;  // Consecutive fault measurements to trigger the alert function. | ||||
|                            // 00: 1 fault | ||||
|                            // 01: 2 faults | ||||
|                            // 10: 3 faults (4 faults TMP1075N) | ||||
|                            // 11: 4 faults (6 faults TMP1075N) | ||||
|  | ||||
|       uint8_t polarity : 1;  // Polarity of the output pin. | ||||
|                              // 0: Active low ALERT pin | ||||
|                              // 1: Active high ALERT pin | ||||
|  | ||||
|       uint8_t alert_mode : 1;  // Selects the function of the ALERT pin. | ||||
|                                // 0: ALERT pin functions in comparator mode | ||||
|                                // 1: ALERT pin functions in interrupt mode | ||||
|  | ||||
|       uint8_t shutdown : 1;  // Sets the device in shutdown mode to conserve power. | ||||
|                              // 0: Device is in continuous conversion | ||||
|                              // 1: Device is in shutdown mode | ||||
|       uint8_t unused : 8; | ||||
|     } fields; | ||||
|     uint16_t regvalue; | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| enum EConversionRate { | ||||
|   CONV_RATE_27_5_MS, | ||||
|   CONV_RATE_55_MS, | ||||
|   CONV_RATE_110_MS, | ||||
|   CONV_RATE_220_MS, | ||||
| }; | ||||
|  | ||||
| enum EAlertFunction { | ||||
|   ALERT_COMPARATOR = 0, | ||||
|   ALERT_INTERRUPT = 1, | ||||
| }; | ||||
|  | ||||
| class TMP1075Sensor : public PollingComponent, public sensor::Sensor, public i2c::I2CDevice { | ||||
|  public: | ||||
|   void setup() override; | ||||
|   void update() override; | ||||
|  | ||||
|   float get_setup_priority() const override { return setup_priority::DATA; } | ||||
|  | ||||
|   void dump_config() override; | ||||
|  | ||||
|   // Call write_config() after calling any of these to send the new config to | ||||
|   // the IC. The setup() function also does this. | ||||
|   void set_alert_limit_low(const float temp) { this->alert_limit_low_ = temp; } | ||||
|   void set_alert_limit_high(const float temp) { this->alert_limit_high_ = temp; } | ||||
|   void set_oneshot(const bool oneshot) { config_.fields.oneshot = oneshot; } | ||||
|   void set_conversion_rate(const enum EConversionRate rate) { config_.fields.rate = rate; } | ||||
|   void set_alert_polarity(const bool polarity) { config_.fields.polarity = polarity; } | ||||
|   void set_alert_function(const enum EAlertFunction function) { config_.fields.alert_mode = function; } | ||||
|   void set_fault_count(int faults); | ||||
|  | ||||
|   void write_config(); | ||||
|  | ||||
|  protected: | ||||
|   TMP1075Config config_ = {}; | ||||
|  | ||||
|   // Disable the alert pin by default. | ||||
|   float alert_limit_low_ = -128.0f; | ||||
|   float alert_limit_high_ = 127.9375f; | ||||
|  | ||||
|   void send_alert_limit_low_(); | ||||
|   void send_alert_limit_high_(); | ||||
|   void send_config_(); | ||||
|   void log_config_(); | ||||
| }; | ||||
|  | ||||
| }  // namespace tmp1075 | ||||
| }  // namespace esphome | ||||
		Reference in New Issue
	
	Block a user