mirror of
https://github.com/esphome/esphome.git
synced 2025-01-07 13:21:44 +01:00
model checks and extra config
This commit is contained in:
parent
2dad225f35
commit
9c24d199e5
3 changed files with 148 additions and 54 deletions
|
@ -4,8 +4,10 @@ from esphome.components import i2c
|
|||
from esphome import automation
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ADDRESS,
|
||||
CONF_MODEL,
|
||||
CONF_RANGE,
|
||||
CONF_RESOLUTION,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
@ -34,20 +36,42 @@ MSA_MODELS = {
|
|||
}
|
||||
|
||||
MSARange = msa3xx_ns.enum("Range", True)
|
||||
MSA_RANGE = {
|
||||
MSA_RANGES = {
|
||||
"2G": MSARange.RANGE_2G,
|
||||
"4G": MSARange.RANGE_4G,
|
||||
"8G": MSARange.RANGE_8G,
|
||||
"16G": MSARange.RANGE_16G,
|
||||
}
|
||||
|
||||
# MSABandwidth = msa3xx_ns.enum("Bandwidth", True)
|
||||
# MSA_BANDWIDTHS = {
|
||||
# "1.95HZ": MSABandwidth.BW_1_95HZ,
|
||||
# "3.9HZ": MSABandwidth.BW_3_9HZ,
|
||||
# "7.81HZ": MSABandwidth.BW_7_81HZ,
|
||||
# "15.63HZ": MSABandwidth.BW_15_63HZ,
|
||||
# "31.25HZ": MSABandwidth.BW_31_25HZ,
|
||||
# "62.5HZ": MSABandwidth.BW_62_5HZ,
|
||||
# "125HZ": MSABandwidth.BW_125HZ,
|
||||
# "250HZ": MSABandwidth.BW_250HZ,
|
||||
# "500HZ": MSABandwidth.BW_500HZ,
|
||||
# }
|
||||
|
||||
MSAResolution = msa3xx_ns.enum("Resolution", True)
|
||||
MSA_RESOLUTIONS = {
|
||||
14: MSAResolution.RES_14BIT,
|
||||
12: MSAResolution.RES_12BIT,
|
||||
10: MSAResolution.RES_10BIT,
|
||||
8: MSAResolution.RES_8BIT,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MSA3xxComponent),
|
||||
cv.Required(CONF_MODEL): cv.enum(MSA_MODELS, upper=True),
|
||||
cv.Optional(CONF_RANGE, default="2G"): cv.enum(MSA_RANGE, upper=True),
|
||||
cv.Optional(CONF_RANGE, default="2G"): cv.enum(MSA_RANGES, upper=True),
|
||||
# cv.Optional(CONF_BANDWIDTH, default="250HZ"): cv.enum(MSA_BANDWIDTHS, upper=True),
|
||||
cv.Optional(CONF_RESOLUTION): cv.enum(MSA_RESOLUTIONS),
|
||||
cv.Optional(CONF_OFFSET_X, default=0): cv.float_range(min=-4.5, max=4.5),
|
||||
cv.Optional(CONF_OFFSET_Y, default=0): cv.float_range(min=-4.5, max=4.5),
|
||||
cv.Optional(CONF_OFFSET_Z, default=0): cv.float_range(min=-4.5, max=4.5),
|
||||
|
@ -62,15 +86,48 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("10s"))
|
||||
.extend(i2c.i2c_device_schema(0x62))
|
||||
.extend(i2c.i2c_device_schema(0x00))
|
||||
)
|
||||
|
||||
|
||||
# def validate_model(config):
|
||||
# model = config[CONF_MODEL]
|
||||
def validate_i2c_address(config):
|
||||
if config[CONF_ADDRESS] == 0x00:
|
||||
if config[CONF_MODEL] == "MSA301":
|
||||
config[CONF_ADDRESS] = 0x26
|
||||
elif config[CONF_MODEL] == "MSA311":
|
||||
config[CONF_ADDRESS] = 0x62
|
||||
return config
|
||||
|
||||
if (config[CONF_MODEL] == "MSA301" and config[CONF_ADDRESS] == 0x26) or (
|
||||
config[CONF_MODEL] == "MSA311" and config[CONF_ADDRESS] == 0x62
|
||||
):
|
||||
return config
|
||||
|
||||
raise cv.Invalid(
|
||||
"Wrong I2C Address ("
|
||||
+ hex(config[CONF_ADDRESS])
|
||||
+ "). MSA301 shall be 0x26, MSA311 shall be 0x62."
|
||||
)
|
||||
|
||||
|
||||
# FINAL_VALIDATE_SCHEMA = validate_model
|
||||
def validate_resolution(config):
|
||||
if CONF_RESOLUTION not in config:
|
||||
if config[CONF_MODEL] == "MSA301":
|
||||
config[CONF_RESOLUTION] = 14
|
||||
elif config[CONF_MODEL] == "MSA311":
|
||||
config[CONF_RESOLUTION] = 12
|
||||
return config
|
||||
|
||||
if config[CONF_MODEL] == "MSA311" and config[CONF_RESOLUTION] != 12:
|
||||
raise cv.Invalid("Check resolution. MSA311 only supports 12-bit")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = cv.All(
|
||||
validate_i2c_address,
|
||||
validate_resolution,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
|
@ -84,11 +141,20 @@ async def to_code(config):
|
|||
config[CONF_OFFSET_X], config[CONF_OFFSET_Y], config[CONF_OFFSET_Z]
|
||||
)
|
||||
)
|
||||
cg.add(var.set_range(config[CONF_RANGE]))
|
||||
cg.add(var.set_range(MSA_RANGES[config[CONF_RANGE]]))
|
||||
cg.add(var.set_resolution(MSA_RESOLUTIONS[config[CONF_RESOLUTION]]))
|
||||
|
||||
irq_set_0 = 0
|
||||
irq_set_1 = 0
|
||||
|
||||
if CONF_ON_ORIENTATION in config:
|
||||
await automation.build_automation(
|
||||
var.get_orientation_trigger(),
|
||||
[],
|
||||
config[CONF_ON_ORIENTATION],
|
||||
)
|
||||
irq_set_0 |= 1 << 6
|
||||
|
||||
if CONF_ON_TAP in config:
|
||||
await automation.build_automation(
|
||||
var.get_tap_trigger(),
|
||||
|
@ -105,14 +171,6 @@ async def to_code(config):
|
|||
)
|
||||
irq_set_0 |= 1 << 4
|
||||
|
||||
if CONF_ON_ORIENTATION in config:
|
||||
await automation.build_automation(
|
||||
var.get_orientation_trigger(),
|
||||
[],
|
||||
config[CONF_ON_ORIENTATION],
|
||||
)
|
||||
irq_set_0 |= 1 << 6
|
||||
|
||||
if CONF_ON_FREEFALL in config:
|
||||
await automation.build_automation(
|
||||
var.get_freefall_trigger(),
|
||||
|
|
|
@ -108,11 +108,11 @@ void MSA3xxComponent::setup() {
|
|||
// S8g : 256 (2^8) : 1024 (2^10)
|
||||
// S16g : 128 (2^7) : 512 (2^9)
|
||||
if (this->model_ == Model::MSA301) {
|
||||
this->params_.accel_data_width = 14;
|
||||
this->params_.scale_factor_exp = static_cast<uint8_t>(this->range_) - 12;
|
||||
this->device_params_.accel_data_width = 14;
|
||||
this->device_params_.scale_factor_exp = static_cast<uint8_t>(this->range_) - 12;
|
||||
} else if (this->model_ == Model::MSA311) {
|
||||
this->params_.accel_data_width = 12;
|
||||
this->params_.scale_factor_exp = static_cast<uint8_t>(this->range_) - 10;
|
||||
this->device_params_.accel_data_width = 12;
|
||||
this->device_params_.scale_factor_exp = static_cast<uint8_t>(this->range_) - 10;
|
||||
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown model");
|
||||
|
@ -120,7 +120,7 @@ void MSA3xxComponent::setup() {
|
|||
return;
|
||||
}
|
||||
|
||||
this->setup_odr_();
|
||||
this->setup_odr_(this->data_rate_);
|
||||
this->setup_power_mode_bandwidth_(this->power_mode_, this->bandwidth_);
|
||||
this->setup_range_resolution_(this->range_, this->resolution_);
|
||||
this->setup_offset_(this->offset_x_, this->offset_y_, this->offset_z_);
|
||||
|
@ -164,16 +164,19 @@ bool MSA3xxComponent::read_data_() {
|
|||
return alpha * new_value + (1.0f - alpha) * old_value;
|
||||
};
|
||||
|
||||
this->data_.lsb_x = this->two_complement_to_normal_(
|
||||
raw_to_x_bit(accel_data[0], accel_data[1], this->params_.accel_data_width), this->params_.accel_data_width);
|
||||
this->data_.lsb_y = this->two_complement_to_normal_(
|
||||
raw_to_x_bit(accel_data[2], accel_data[3], this->params_.accel_data_width), this->params_.accel_data_width);
|
||||
this->data_.lsb_z = this->two_complement_to_normal_(
|
||||
raw_to_x_bit(accel_data[4], accel_data[5], this->params_.accel_data_width), this->params_.accel_data_width);
|
||||
this->data_.lsb_x =
|
||||
this->two_complement_to_normal_(raw_to_x_bit(accel_data[0], accel_data[1], this->device_params_.accel_data_width),
|
||||
this->device_params_.accel_data_width);
|
||||
this->data_.lsb_y =
|
||||
this->two_complement_to_normal_(raw_to_x_bit(accel_data[2], accel_data[3], this->device_params_.accel_data_width),
|
||||
this->device_params_.accel_data_width);
|
||||
this->data_.lsb_z =
|
||||
this->two_complement_to_normal_(raw_to_x_bit(accel_data[4], accel_data[5], this->device_params_.accel_data_width),
|
||||
this->device_params_.accel_data_width);
|
||||
|
||||
this->data_.x = lpf(ldexp(this->data_.lsb_x, this->params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.x);
|
||||
this->data_.y = lpf(ldexp(this->data_.lsb_y, this->params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.y);
|
||||
this->data_.z = lpf(ldexp(this->data_.lsb_z, this->params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.z);
|
||||
this->data_.x = lpf(ldexp(this->data_.lsb_x, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.x);
|
||||
this->data_.y = lpf(ldexp(this->data_.lsb_y, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.y);
|
||||
this->data_.z = lpf(ldexp(this->data_.lsb_z, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.z);
|
||||
|
||||
// ESP_LOGVV(TAG, "Got raw data {x=%5d, y=%5d, z=%5d}, accel={x=%+1.3f m/s², y=%+1.3f m/s², z=%+1.3f m/s²}",
|
||||
// this->data_.lsb_x, this->data_.lsb_y, this->data_.lsb_z, this->data_.x, this->data_.y, this->data_.z);
|
||||
|
@ -182,7 +185,11 @@ bool MSA3xxComponent::read_data_() {
|
|||
}
|
||||
|
||||
bool MSA3xxComponent::read_motion_status_() {
|
||||
if (!this->read_byte(static_cast<uint8_t>(RegisterMap::MOTION_INTERRUPT), &this->status_.mi.raw)) {
|
||||
if (!this->read_byte(static_cast<uint8_t>(RegisterMap::MOTION_INTERRUPT), &this->status_.motion_int.raw)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->read_byte(static_cast<uint8_t>(RegisterMap::ORIENTATION_STATUS), &this->status_.orientation.raw)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -231,20 +238,21 @@ void MSA3xxComponent::set_offset(float offset_x, float offset_y, float offset_z)
|
|||
this->offset_z_ = offset_z;
|
||||
}
|
||||
|
||||
void MSA3xxComponent::setup_odr_() {
|
||||
RegODR odr;
|
||||
void MSA3xxComponent::setup_odr_(DataRate rate) {
|
||||
RegOutputDataRate reg_odr;
|
||||
auto reg = this->read_byte(static_cast<uint8_t>(RegisterMap::ODR));
|
||||
if (reg.has_value()) {
|
||||
odr.raw = reg.value();
|
||||
reg_odr.raw = reg.value();
|
||||
} else {
|
||||
odr.raw = 0x0F; // defaut from datasheet
|
||||
reg_odr.raw = 0x0F; // defaut from datasheet
|
||||
}
|
||||
|
||||
odr.x_axis_disable = 0;
|
||||
odr.y_axis_disable = 0;
|
||||
odr.z_axis_disable = 0;
|
||||
reg_odr.x_axis_disable = 0;
|
||||
reg_odr.y_axis_disable = 0;
|
||||
reg_odr.z_axis_disable = 0;
|
||||
reg_odr.odr = rate;
|
||||
|
||||
this->write_byte(static_cast<uint8_t>(RegisterMap::ODR), odr.raw);
|
||||
this->write_byte(static_cast<uint8_t>(RegisterMap::ODR), reg_odr.raw);
|
||||
}
|
||||
|
||||
void MSA3xxComponent::setup_power_mode_bandwidth_(PowerMode power_mode, Bandwidth bandwidth) {
|
||||
|
@ -259,7 +267,7 @@ void MSA3xxComponent::setup_power_mode_bandwidth_(PowerMode power_mode, Bandwidt
|
|||
}
|
||||
|
||||
power_mode_bandwidth.power_mode = power_mode;
|
||||
power_mode_bandwidth.low_power_bw = bandwidth;
|
||||
power_mode_bandwidth.low_power_bandwidth = bandwidth;
|
||||
|
||||
this->write_byte(static_cast<uint8_t>(RegisterMap::POWER_MODE_BANDWIDTH), power_mode_bandwidth.raw);
|
||||
}
|
||||
|
@ -300,21 +308,21 @@ int64_t MSA3xxComponent::two_complement_to_normal_(uint64_t value, uint8_t bits)
|
|||
}
|
||||
|
||||
void MSA3xxComponent::process_interrupts_() {
|
||||
if (this->status_.mi.raw == 0) {
|
||||
if (this->status_.motion_int.raw == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->status_.mi.single_tap_interrupt) {
|
||||
if (this->status_.motion_int.single_tap_interrupt) {
|
||||
ESP_LOGW(TAG, "Single Tap detected");
|
||||
this->tap_trigger_.trigger();
|
||||
}
|
||||
|
||||
if (this->status_.mi.double_tap_interrupt) {
|
||||
if (this->status_.motion_int.double_tap_interrupt) {
|
||||
ESP_LOGW(TAG, "Double Tap detected");
|
||||
this->double_tap_trigger_.trigger();
|
||||
}
|
||||
|
||||
if (this->status_.mi.orientation_interrupt) {
|
||||
if (this->status_.motion_int.orientation_interrupt) {
|
||||
ESP_LOGW(TAG, "Orientation changed");
|
||||
this->orientation_trigger_.trigger();
|
||||
}
|
||||
|
|
|
@ -91,6 +91,20 @@ enum class Bandwidth : uint8_t {
|
|||
BW_500HZ = 0b1010,
|
||||
};
|
||||
|
||||
enum class DataRate : uint8_t {
|
||||
ODR_1HZ = 0b0000, // not available in normal mode
|
||||
ODR_1_95HZ = 0b0001, // not available in normal mode
|
||||
ODR_3_9HZ = 0b0010,
|
||||
ODR_7_81HZ = 0b0011,
|
||||
ODR_15_63HZ = 0b0100,
|
||||
ODR_31_25HZ = 0b0101,
|
||||
ODR_62_5HZ = 0b0110,
|
||||
ODR_125HZ = 0b0111,
|
||||
ODR_250HZ = 0b1000,
|
||||
ODR_500HZ = 0b1001, // not available in low power mode
|
||||
ODR_1000HZ = 0b1010, // not available in low power mode
|
||||
};
|
||||
|
||||
// 0x09
|
||||
union RegMotionInterrupt {
|
||||
struct {
|
||||
|
@ -106,21 +120,31 @@ union RegMotionInterrupt {
|
|||
uint8_t raw;
|
||||
};
|
||||
|
||||
// 0x0C
|
||||
union RegOrientationStatus {
|
||||
struct {
|
||||
uint8_t reserved_0_3 : 4;
|
||||
uint8_t orient : 3;
|
||||
uint8_t reserved_7 : 1;
|
||||
};
|
||||
uint8_t raw{0x00};
|
||||
};
|
||||
|
||||
// 0x0f
|
||||
union RegRangeResolution {
|
||||
struct {
|
||||
Range range : 2;
|
||||
Resolution resolution : 2;
|
||||
bool reserved_2 : 4;
|
||||
uint8_t reserved_2 : 4;
|
||||
};
|
||||
uint8_t raw{0x00};
|
||||
};
|
||||
|
||||
// 0x10
|
||||
union RegODR {
|
||||
union RegOutputDataRate {
|
||||
struct {
|
||||
uint8_t odr : 4;
|
||||
bool reserved_4 : 1;
|
||||
DataRate odr : 4;
|
||||
uint8_t reserved_4 : 1;
|
||||
bool z_axis_disable : 1;
|
||||
bool y_axis_disable : 1;
|
||||
bool x_axis_disable : 1;
|
||||
|
@ -131,9 +155,9 @@ union RegODR {
|
|||
// 0x11
|
||||
union RegPowerModeBandwidth {
|
||||
struct {
|
||||
bool reserved_0 : 1;
|
||||
Bandwidth low_power_bw : 4;
|
||||
bool reserved_5 : 1;
|
||||
uint8_t reserved_0 : 1;
|
||||
Bandwidth low_power_bandwidth : 4;
|
||||
uint8_t reserved_5 : 1;
|
||||
PowerMode power_mode : 2;
|
||||
};
|
||||
uint8_t raw{0xde};
|
||||
|
@ -143,7 +167,7 @@ union RegPowerModeBandwidth {
|
|||
union RegTapDuration {
|
||||
struct {
|
||||
uint8_t duration : 3;
|
||||
bool reserved_3 : 3;
|
||||
uint8_t reserved : 3;
|
||||
bool tap_shock : 1;
|
||||
bool tap_quiet : 1;
|
||||
};
|
||||
|
@ -163,6 +187,8 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
void set_model(Model model) { this->model_ = model; }
|
||||
void set_offset(float offset_x, float offset_y, float offset_z);
|
||||
void set_range(Range range) { this->range_ = range; }
|
||||
void set_bandwidth(Bandwidth bandwidth) { this->bandwidth_ = bandwidth; }
|
||||
void set_resolution(Resolution resolution) { this->resolution_ = resolution; }
|
||||
void set_interrupts(uint8_t set0, uint8_t set1) {
|
||||
this->int_set_0_ = set0;
|
||||
this->int_set_1_ = set1;
|
||||
|
@ -183,6 +209,7 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
Model model_{Model::MSA311};
|
||||
|
||||
PowerMode power_mode_{PowerMode::NORMAL};
|
||||
DataRate data_rate_{DataRate::ODR_250HZ};
|
||||
Bandwidth bandwidth_{Bandwidth::BW_250HZ};
|
||||
Range range_{Range::RANGE_2G};
|
||||
Resolution resolution_{Resolution::RES_14BIT};
|
||||
|
@ -195,7 +222,7 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
struct {
|
||||
int scale_factor_exp;
|
||||
uint8_t accel_data_width;
|
||||
} params_{};
|
||||
} device_params_{};
|
||||
|
||||
struct {
|
||||
int16_t lsb_x, lsb_y, lsb_z;
|
||||
|
@ -203,10 +230,11 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
} data_{};
|
||||
|
||||
struct {
|
||||
RegMotionInterrupt mi;
|
||||
RegMotionInterrupt motion_int;
|
||||
RegOrientationStatus orientation;
|
||||
} status_{};
|
||||
|
||||
void setup_odr_();
|
||||
void setup_odr_(DataRate rate);
|
||||
void setup_power_mode_bandwidth_(PowerMode power_mode, Bandwidth bandwidth);
|
||||
void setup_range_resolution_(Range range, Resolution resolution);
|
||||
void setup_offset_(float offset_x, float offset_y, float offset_z);
|
||||
|
|
Loading…
Reference in a new issue