forked from esphome/esphome
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for honeywellabp2 pressure sensor (esphome#5422)
- Loading branch information
Showing
6 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
"""Support for Honeywell ABP2""" | ||
CODEOWNERS = ["@jpfaff"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters