mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add support for honeywellabp2 pressure sensor (#5422)
This commit is contained in:
		| @@ -122,6 +122,7 @@ esphome/components/hitachi_ac424/* @sourabhjaiswal | |||||||
| esphome/components/hm3301/* @freekode | esphome/components/hm3301/* @freekode | ||||||
| esphome/components/homeassistant/* @OttoWinter | esphome/components/homeassistant/* @OttoWinter | ||||||
| esphome/components/honeywellabp/* @RubyBailey | esphome/components/honeywellabp/* @RubyBailey | ||||||
|  | esphome/components/honeywellabp2_i2c/* @jpfaff | ||||||
| esphome/components/host/* @esphome/core | esphome/components/host/* @esphome/core | ||||||
| esphome/components/hrxl_maxsonar_wr/* @netmikey | esphome/components/hrxl_maxsonar_wr/* @netmikey | ||||||
| esphome/components/hte501/* @Stock-M | esphome/components/hte501/* @Stock-M | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								esphome/components/honeywellabp2_i2c/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								esphome/components/honeywellabp2_i2c/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | """Support for Honeywell ABP2""" | ||||||
|  | CODEOWNERS = ["@jpfaff"] | ||||||
							
								
								
									
										108
									
								
								esphome/components/honeywellabp2_i2c/honeywellabp2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								esphome/components/honeywellabp2_i2c/honeywellabp2.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | #include "honeywellabp2.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace honeywellabp2_i2c { | ||||||
|  |  | ||||||
|  | static const uint8_t STATUS_BIT_POWER = 6; | ||||||
|  | static const uint8_t STATUS_BIT_BUSY = 5; | ||||||
|  | static const uint8_t STATUS_BIT_ERROR = 2; | ||||||
|  | static const uint8_t STATUS_MATH_SAT = 0; | ||||||
|  |  | ||||||
|  | static const char *const TAG = "honeywellabp2"; | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::read_sensor_data() { | ||||||
|  |   if (this->read(raw_data_, 7) != i2c::ERROR_OK) { | ||||||
|  |     ESP_LOGE(TAG, "Communication with ABP2 failed!"); | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   float press_counts = encode_uint24(raw_data_[1], raw_data_[2], raw_data_[3]);  // calculate digital pressure counts | ||||||
|  |   float temp_counts = encode_uint24(raw_data_[4], raw_data_[5], raw_data_[6]);   // calculate digital temperature counts | ||||||
|  |  | ||||||
|  |   this->last_pressure_ = (((press_counts - this->min_count_) / (this->max_count_ - this->min_count_)) * | ||||||
|  |                           (this->max_pressure_ - this->min_pressure_)) + | ||||||
|  |                          this->min_pressure_; | ||||||
|  |   this->last_temperature_ = (temp_counts * 200 / 16777215) - 50; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::start_measurement() { | ||||||
|  |   if (this->write(i2c_cmd_, 3) != i2c::ERROR_OK) { | ||||||
|  |     ESP_LOGE(TAG, "Communication with ABP2 failed!"); | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   this->measurement_running_ = true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool HONEYWELLABP2Sensor::is_measurement_ready() { | ||||||
|  |   if (this->read(raw_data_, 1) != i2c::ERROR_OK) { | ||||||
|  |     ESP_LOGE(TAG, "Communication with ABP2 failed!"); | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   if ((raw_data_[0] & (0x1 << STATUS_BIT_BUSY)) > 0) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   this->measurement_running_ = false; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::measurement_timeout() { | ||||||
|  |   ESP_LOGE(TAG, "Timeout!"); | ||||||
|  |   this->measurement_running_ = false; | ||||||
|  |   this->mark_failed(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float HONEYWELLABP2Sensor::get_pressure() { return this->last_pressure_; } | ||||||
|  |  | ||||||
|  | float HONEYWELLABP2Sensor::get_temperature() { return this->last_temperature_; } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::loop() { | ||||||
|  |   if (this->measurement_running_) { | ||||||
|  |     if (this->is_measurement_ready()) { | ||||||
|  |       this->cancel_timeout("meas_timeout"); | ||||||
|  |  | ||||||
|  |       this->read_sensor_data(); | ||||||
|  |       if (pressure_sensor_ != nullptr) { | ||||||
|  |         this->pressure_sensor_->publish_state(this->get_pressure()); | ||||||
|  |       } | ||||||
|  |       if (temperature_sensor_ != nullptr) { | ||||||
|  |         this->temperature_sensor_->publish_state(this->get_temperature()); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::update() { | ||||||
|  |   ESP_LOGV(TAG, "Update Honeywell ABP2 Sensor"); | ||||||
|  |  | ||||||
|  |   this->start_measurement(); | ||||||
|  |   this->set_timeout("meas_timeout", 50, [this] { this->measurement_timeout(); }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Min Pressure Range: %0.1f", this->min_pressure_); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Max Pressure Range: %0.1f", this->max_pressure_); | ||||||
|  |   if (this->transfer_function_ == ABP2_TRANS_FUNC_A) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Transfer function A"); | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Transfer function B"); | ||||||
|  |   } | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HONEYWELLABP2Sensor::set_transfer_function(ABP2TRANFERFUNCTION transfer_function) { | ||||||
|  |   this->transfer_function_ = transfer_function; | ||||||
|  |   if (this->transfer_function_ == ABP2_TRANS_FUNC_B) { | ||||||
|  |     this->max_count_ = this->max_count_b_; | ||||||
|  |     this->min_count_ = this->min_count_b_; | ||||||
|  |   } else { | ||||||
|  |     this->max_count_ = this->max_count_a_; | ||||||
|  |     this->min_count_ = this->min_count_a_; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace honeywellabp2_i2c | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										60
									
								
								esphome/components/honeywellabp2_i2c/honeywellabp2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								esphome/components/honeywellabp2_i2c/honeywellabp2.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // for Honeywell ABP sensor | ||||||
|  | // adapting code from https://github.com/vwls/Honeywell_pressure_sensors | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/sensor/sensor.h" | ||||||
|  | #include "esphome/components/i2c/i2c.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace honeywellabp2_i2c { | ||||||
|  |  | ||||||
|  | enum ABP2TRANFERFUNCTION { ABP2_TRANS_FUNC_A = 0, ABP2_TRANS_FUNC_B = 1 }; | ||||||
|  |  | ||||||
|  | class HONEYWELLABP2Sensor : public PollingComponent, public i2c::I2CDevice { | ||||||
|  |  public: | ||||||
|  |   void set_pressure_sensor(sensor::Sensor *pressure_sensor) { this->pressure_sensor_ = pressure_sensor; }; | ||||||
|  |   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; }; | ||||||
|  |   void loop() override; | ||||||
|  |   void update() override; | ||||||
|  |   float get_setup_priority() const override { return setup_priority::DATA; }; | ||||||
|  |   void dump_config() override; | ||||||
|  |  | ||||||
|  |   void read_sensor_data(); | ||||||
|  |   void start_measurement(); | ||||||
|  |   bool is_measurement_ready(); | ||||||
|  |   void measurement_timeout(); | ||||||
|  |  | ||||||
|  |   float get_pressure(); | ||||||
|  |   float get_temperature(); | ||||||
|  |  | ||||||
|  |   void set_min_pressure(float min_pressure) { this->min_pressure_ = min_pressure; }; | ||||||
|  |   void set_max_pressure(float max_pressure) { this->max_pressure_ = max_pressure; }; | ||||||
|  |   void set_transfer_function(ABP2TRANFERFUNCTION transfer_function); | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   float min_pressure_ = 0.0; | ||||||
|  |   float max_pressure_ = 0.0; | ||||||
|  |   ABP2TRANFERFUNCTION transfer_function_ = ABP2_TRANS_FUNC_A; | ||||||
|  |  | ||||||
|  |   sensor::Sensor *pressure_sensor_{nullptr}; | ||||||
|  |   sensor::Sensor *temperature_sensor_{nullptr}; | ||||||
|  |  | ||||||
|  |   const float max_count_a_ = 15099494.4;  // (90% of 2^24 counts or 0xE66666) | ||||||
|  |   const float min_count_a_ = 1677721.6;   // (10% of 2^24 counts or 0x19999A) | ||||||
|  |   const float max_count_b_ = 11744051.2;  // (70% of 2^24 counts or 0xB33333) | ||||||
|  |   const float min_count_b_ = 5033164.8;   // (30% of 2^24 counts or 0x4CCCCC) | ||||||
|  |  | ||||||
|  |   float max_count_; | ||||||
|  |   float min_count_; | ||||||
|  |   bool measurement_running_ = false; | ||||||
|  |  | ||||||
|  |   uint8_t raw_data_[7];                      // holds output data | ||||||
|  |   uint8_t i2c_cmd_[3] = {0xAA, 0x00, 0x00};  // command to be sent | ||||||
|  |   float last_pressure_; | ||||||
|  |   float last_temperature_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace honeywellabp2_i2c | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										75
									
								
								esphome/components/honeywellabp2_i2c/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								esphome/components/honeywellabp2_i2c/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.components import sensor | ||||||
|  | from esphome.components import i2c | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_PRESSURE, | ||||||
|  |     CONF_TEMPERATURE, | ||||||
|  |     DEVICE_CLASS_PRESSURE, | ||||||
|  |     DEVICE_CLASS_TEMPERATURE, | ||||||
|  |     STATE_CLASS_MEASUREMENT, | ||||||
|  |     UNIT_CELSIUS, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["i2c"] | ||||||
|  |  | ||||||
|  | honeywellabp2_ns = cg.esphome_ns.namespace("honeywellabp2_i2c") | ||||||
|  |  | ||||||
|  | CONF_MIN_PRESSURE = "min_pressure" | ||||||
|  | CONF_MAX_PRESSURE = "max_pressure" | ||||||
|  | TRANSFER_FUNCTION = "transfer_function" | ||||||
|  | ABP2TRANFERFUNCTION = honeywellabp2_ns.enum("ABP2TRANFERFUNCTION") | ||||||
|  | TRANS_FUNC_OPTIONS = { | ||||||
|  |     "A": ABP2TRANFERFUNCTION.ABP2_TRANS_FUNC_A, | ||||||
|  |     "B": ABP2TRANFERFUNCTION.ABP2_TRANS_FUNC_B, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | HONEYWELLABP2Sensor = honeywellabp2_ns.class_( | ||||||
|  |     "HONEYWELLABP2Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = ( | ||||||
|  |     cv.Schema( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.declare_id(HONEYWELLABP2Sensor), | ||||||
|  |             cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||||
|  |                 unit_of_measurement="Pa", | ||||||
|  |                 accuracy_decimals=1, | ||||||
|  |                 device_class=DEVICE_CLASS_PRESSURE, | ||||||
|  |                 state_class=STATE_CLASS_MEASUREMENT, | ||||||
|  |             ).extend( | ||||||
|  |                 { | ||||||
|  |                     cv.Required(CONF_MIN_PRESSURE): cv.float_, | ||||||
|  |                     cv.Required(CONF_MAX_PRESSURE): cv.float_, | ||||||
|  |                     cv.Required(TRANSFER_FUNCTION): cv.enum(TRANS_FUNC_OPTIONS), | ||||||
|  |                 } | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||||
|  |                 unit_of_measurement=UNIT_CELSIUS, | ||||||
|  |                 accuracy_decimals=1, | ||||||
|  |                 device_class=DEVICE_CLASS_TEMPERATURE, | ||||||
|  |                 state_class=STATE_CLASS_MEASUREMENT, | ||||||
|  |             ), | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(cv.polling_component_schema("60s")) | ||||||
|  |     .extend(i2c.i2c_device_schema(0x28)) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|  |     if pressure_config := config.get(CONF_PRESSURE): | ||||||
|  |         sens = await sensor.new_sensor(pressure_config) | ||||||
|  |         cg.add(var.set_pressure_sensor(sens)) | ||||||
|  |         cg.add(var.set_min_pressure(pressure_config[CONF_MIN_PRESSURE])) | ||||||
|  |         cg.add(var.set_max_pressure(pressure_config[CONF_MAX_PRESSURE])) | ||||||
|  |         cg.add(var.set_transfer_function(pressure_config[TRANSFER_FUNCTION])) | ||||||
|  |  | ||||||
|  |     if temperature_config := config.get(CONF_TEMPERATURE): | ||||||
|  |         sens = await sensor.new_sensor(temperature_config) | ||||||
|  |         cg.add(var.set_temperature_sensor(sens)) | ||||||
| @@ -742,6 +742,16 @@ sensor: | |||||||
|     temperature: |     temperature: | ||||||
|       name: Honeywell temperature |       name: Honeywell temperature | ||||||
|     cs_pin: GPIO5 |     cs_pin: GPIO5 | ||||||
|  |   - platform: honeywellabp2_i2c | ||||||
|  |     pressure: | ||||||
|  |       name: Honeywell2 pressure | ||||||
|  |       min_pressure: 0 | ||||||
|  |       max_pressure: 16000 | ||||||
|  |       transfer_function: A | ||||||
|  |     temperature: | ||||||
|  |       name: Honeywell temperature | ||||||
|  |     i2c_id: i2c_bus | ||||||
|  |     address: 0x28 | ||||||
|   - platform: hte501 |   - platform: hte501 | ||||||
|     temperature: |     temperature: | ||||||
|       name: Office Temperature 2 |       name: Office Temperature 2 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user