9 static const char *
const TAG =
"msa3xx";
14 const float LSB_COEFF = 1000.0f / (GRAVITY_EARTH * 3.9);
104 switch (orientation) {
106 return "Portrait Upright";
108 return "Portrait Upside Down";
110 return "Landscape Left";
112 return "Landscape Right";
121 ESP_LOGCONFIG(TAG,
"Setting up MSA3xx...");
123 uint8_t part_id{0xff};
125 ESP_LOGE(TAG,
"Part ID is wrong or missing. Got 0x%02X", part_id);
143 ESP_LOGE(TAG,
"Unknown model");
159 ESP_LOGCONFIG(TAG,
"MSA3xx:");
160 LOG_I2C_DEVICE(
this);
162 ESP_LOGE(TAG,
"Communication with MSA3xx failed!");
170 ESP_LOGCONFIG(TAG,
" Transform: {mirror_x=%s, mirror_y=%s, mirror_z=%s, swap_xy=%s}", YESNO(this->
swap_.
x_polarity),
172 LOG_UPDATE_INTERVAL(
this);
174 #ifdef USE_BINARY_SENSOR 175 LOG_BINARY_SENSOR(
" ",
"Tap", this->tap_binary_sensor_);
176 LOG_BINARY_SENSOR(
" ",
"Double Tap", this->double_tap_binary_sensor_);
177 LOG_BINARY_SENSOR(
" ",
"Active", this->active_binary_sensor_);
181 LOG_SENSOR(
" ",
"Acceleration X", this->acceleration_x_sensor_);
182 LOG_SENSOR(
" ",
"Acceleration Y", this->acceleration_y_sensor_);
183 LOG_SENSOR(
" ",
"Acceleration Z", this->acceleration_z_sensor_);
186 #ifdef USE_TEXT_SENSOR 187 LOG_TEXT_SENSOR(
" ",
"Orientation XY", this->orientation_xy_text_sensor_);
188 LOG_TEXT_SENSOR(
" ",
"Orientation Z", this->orientation_z_text_sensor_);
193 uint8_t accel_data[6];
198 auto raw_to_x_bit = [](uint16_t lsb, uint16_t msb, uint8_t data_bits) -> uint16_t {
199 return ((msb << 8) | lsb) >> (16 - data_bits);
202 auto lpf = [](
float new_value,
float old_value,
float alpha = 0.5f) {
203 return alpha * new_value + (1.0f - alpha) * old_value;
208 this->device_params_.accel_data_width);
211 this->device_params_.accel_data_width);
214 this->device_params_.accel_data_width);
216 this->
data_.x = lpf(ldexp(this->
data_.lsb_x, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.x);
217 this->
data_.y = lpf(ldexp(this->
data_.lsb_y, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.y);
218 this->
data_.z = lpf(ldexp(this->
data_.lsb_z, this->device_params_.scale_factor_exp) * GRAVITY_EARTH, this->data_.z);
251 ESP_LOGV(TAG,
"Updating MSA3xx...");
254 ESP_LOGV(TAG,
"Component MSA3xx not ready for update");
257 ESP_LOGV(TAG,
"Acceleration: {x = %+1.3f m/s², y = %+1.3f m/s², z = %+1.3f m/s²}; ", this->
data_.x, this->data_.y,
264 if (this->acceleration_x_sensor_ !=
nullptr)
265 this->acceleration_x_sensor_->publish_state(this->
data_.x);
266 if (this->acceleration_y_sensor_ !=
nullptr)
267 this->acceleration_y_sensor_->publish_state(this->
data_.y);
268 if (this->acceleration_z_sensor_ !=
nullptr)
269 this->acceleration_z_sensor_->publish_state(this->
data_.z);
272 #ifdef USE_TEXT_SENSOR 273 if (this->orientation_xy_text_sensor_ !=
nullptr &&
274 (this->
status_.orientation.orient_xy != this->status_.orientation_old.orient_xy ||
275 this->status_.never_published)) {
278 if (this->orientation_z_text_sensor_ !=
nullptr &&
279 (this->
status_.orientation.orient_z != this->status_.orientation_old.orient_z || this->status_.never_published)) {
285 this->
status_.never_published =
false;
306 if (
reg.has_value()) {
307 reg_odr.
raw =
reg.value();
325 if (
reg.has_value()) {
326 power_mode_bandwidth.
raw =
reg.value();
328 power_mode_bandwidth.
raw = 0xde;
350 auto offset_g_to_lsb = [](
float accel) -> int8_t {
351 float acccel_clamped =
clamp(accel, G_OFFSET_MIN, G_OFFSET_MAX);
352 return static_cast<int8_t
>(acccel_clamped *
LSB_COEFF);
355 offset[0] = offset_g_to_lsb(offset_x);
356 offset[1] = offset_g_to_lsb(offset_y);
357 offset[2] = offset_g_to_lsb(offset_z);
359 ESP_LOGV(TAG,
"Offset (%.3f, %.3f, %.3f)=>LSB(%d, %d, %d)", offset_x, offset_y, offset_z, offset[0], offset[1],
366 if (value > (1ULL << (bits - 1))) {
367 return (int64_t) (value - (1ULL << bits));
369 return (int64_t) value;
374 uint32_t cooldown_ms,
void *bs,
const char *desc) {
375 if (state && now - last_ms > cooldown_ms) {
376 ESP_LOGV(TAG,
"%s detected", desc);
379 #ifdef USE_BINARY_SENSOR 384 }
else if (!state && now - last_ms > cooldown_ms && bs !=
nullptr) {
385 #ifdef USE_BINARY_SENSOR 391 #ifdef USE_BINARY_SENSOR 392 #define BS_OPTIONAL_PTR(x) ((void *) (x)) 394 #define BS_OPTIONAL_PTR(x) (nullptr) 401 this->status_.last_tap_ms, this->tap_trigger_, TAP_COOLDOWN_MS,
402 BS_OPTIONAL_PTR(this->tap_binary_sensor_),
"Tap");
404 this->status_.last_double_tap_ms, this->double_tap_trigger_, DOUBLE_TAP_COOLDOWN_MS,
405 BS_OPTIONAL_PTR(this->double_tap_binary_sensor_),
"Double Tap");
407 this->status_.last_action_ms, this->active_trigger_, ACTIVITY_COOLDOWN_MS,
408 BS_OPTIONAL_PTR(this->active_binary_sensor_),
"Activity");
410 if (this->
status_.motion_int.orientation_interrupt) {
411 ESP_LOGVV(TAG,
"Orientation changed");
const char * model_to_string(Model model)
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
void set_offset(float offset_x, float offset_y, float offset_z)
const float DATA
For components that import data from directly connected sensors like DHT.
const uint32_t DOUBLE_TAP_COOLDOWN_MS
void status_set_warning(const char *message="unspecified")
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
void setup_range_resolution_(Range range, Resolution resolution)
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
bool read_motion_status_()
void dump_config() override
const char * bandwidth_to_string(Bandwidth bandwidth)
struct esphome::msa3xx::MSA3xxComponent::@135 data_
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
uint32_t IRAM_ATTR HOT millis()
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
int64_t twos_complement_(uint64_t value, uint8_t bits)
Bandwidth low_power_bandwidth
const char * range_to_string(Range range)
struct esphome::msa3xx::MSA3xxComponent::@134 device_params_
const char * orientation_z_to_string(bool orientation)
const uint32_t TAP_COOLDOWN_MS
void set_transform(bool mirror_x, bool mirror_y, bool mirror_z, bool swap_xy)
void status_clear_warning()
const char * res_to_string(Resolution resolution)
void process_motions_(RegMotionInterrupt old)
const char * power_mode_to_string(PowerMode power_mode)
void setup_odr_(DataRate rate)
bool double_tap_interrupt
const char * orientation_xy_to_string(OrientationXY orientation)
const uint8_t RESOLUTION[]
void binary_event_debounce(bool state, bool old_state, uint32_t now, uint32_t &last_ms, Trigger<> &trigger, uint32_t cooldown_ms, void *bs, const char *desc)
void setup_power_mode_bandwidth_(PowerMode power_mode, Bandwidth bandwidth)
struct esphome::msa3xx::MSA3xxComponent::@136 status_
const uint8_t MSA_3XX_PART_ID
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
float get_setup_priority() const override
virtual void mark_failed()
Mark this component as failed.
const float GRAVITY_EARTH
void setup_offset_(float offset_x, float offset_y, float offset_z)
Implementation of SPI Controller mode.
Base class for all binary_sensor-type classes.
bool single_tap_interrupt
Trigger orientation_trigger_
const uint32_t ACTIVITY_COOLDOWN_MS
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)