168 lines
5.1 KiB
C++
168 lines
5.1 KiB
C++
#include "lsm6ds_base.h"
|
|
#include "esphome/core/log.h"
|
|
#include "esphome/core/helpers.h"
|
|
#include "esphome/core/hal.h"
|
|
|
|
namespace esphome {
|
|
namespace lsm6ds_base {
|
|
|
|
static const char *const TAG = "lsm6ds";
|
|
|
|
void LSM6DSComponent::setup() {
|
|
uint8_t who_am_i;
|
|
if (!this->read_register(0x0F, &who_am_i, 1)) {
|
|
this->mark_failed();
|
|
ESP_LOGE(TAG, "Communication failed");
|
|
return;
|
|
}
|
|
|
|
if (who_am_i == 0x6C) {
|
|
ESP_LOGI(TAG, "Detected LSM6DSOX");
|
|
} else if (who_am_i == 0x6A) {
|
|
ESP_LOGI(TAG, "Detected LSM6DS3TR-C/LSM6DSM");
|
|
} else if (who_am_i == 0x69) {
|
|
ESP_LOGI(TAG, "Detected LSM6DSO32TR");
|
|
} else {
|
|
this->mark_failed();
|
|
ESP_LOGE(TAG, "Unknown chip ID: 0x%02X", who_am_i);
|
|
return;
|
|
}
|
|
|
|
// SW Reset
|
|
this->write_register(0x12, 0x01);
|
|
uint8_t ctrl3;
|
|
|
|
// Use esphome:: namespace for framework compatibility
|
|
uint32_t start = esphome::millis();
|
|
do {
|
|
esphome::delay(10);
|
|
this->read_register(0x12, &ctrl3, 1);
|
|
} while ((ctrl3 & 0x01) && (esphome::millis() - start < 100));
|
|
|
|
if (ctrl3 & 0x01) {
|
|
ESP_LOGW(TAG, "SW Reset timed out");
|
|
}
|
|
|
|
// Enable BDU (Block Data Update)
|
|
this->write_register(0x12, 0x40 | 0x04); // BDU=1, IF_INC=1
|
|
|
|
// Configure Accel
|
|
uint8_t ctrl1_xl = (this->accel_odr_ << 4) | (this->accel_range_ << 2);
|
|
this->write_register(0x10, ctrl1_xl);
|
|
|
|
switch (this->accel_range_) {
|
|
case LSM6DS_ACCEL_RANGE_2G:
|
|
this->accel_sensitivity_ = 0.061e-3f;
|
|
break;
|
|
case LSM6DS_ACCEL_RANGE_4G:
|
|
this->accel_sensitivity_ = 0.122e-3f;
|
|
break;
|
|
case LSM6DS_ACCEL_RANGE_8G:
|
|
this->accel_sensitivity_ = 0.244e-3f;
|
|
break;
|
|
case LSM6DS_ACCEL_RANGE_16G:
|
|
this->accel_sensitivity_ = 0.488e-3f;
|
|
break;
|
|
default:
|
|
this->accel_sensitivity_ = 0;
|
|
break;
|
|
}
|
|
|
|
// Configure Gyro
|
|
uint8_t ctrl2_g = (this->gyro_odr_ << 4);
|
|
if (this->gyro_range_ == LSM6DS_GYRO_RANGE_125DPS) {
|
|
ctrl2_g |= 0x02; // FS_125 = 1
|
|
this->gyro_sensitivity_ = 4.375e-3f;
|
|
} else {
|
|
ctrl2_g |= (this->gyro_range_ << 2);
|
|
switch (this->gyro_range_) {
|
|
case LSM6DS_GYRO_RANGE_250DPS:
|
|
this->gyro_sensitivity_ = 8.75e-3f;
|
|
break;
|
|
case LSM6DS_GYRO_RANGE_500DPS:
|
|
this->gyro_sensitivity_ = 17.50e-3f;
|
|
break;
|
|
case LSM6DS_GYRO_RANGE_1000DPS:
|
|
this->gyro_sensitivity_ = 35.0e-3f;
|
|
break;
|
|
case LSM6DS_GYRO_RANGE_2000DPS:
|
|
this->gyro_sensitivity_ = 70.0e-3f;
|
|
break;
|
|
default:
|
|
this->gyro_sensitivity_ = 0;
|
|
break;
|
|
}
|
|
}
|
|
this->write_register(0x11, ctrl2_g);
|
|
}
|
|
|
|
void LSM6DSComponent::update() {
|
|
uint8_t status;
|
|
if (!this->read_register(0x1E, &status, 1))
|
|
return;
|
|
|
|
ESP_LOGW(TAG, "STATUS=0x%02X accel_odr=0x%02X gyro_odr=0x%02X",
|
|
status,
|
|
static_cast<uint8_t>(this->accel_odr_),
|
|
static_cast<uint8_t>(this->gyro_odr_));
|
|
|
|
if (this->gyro_odr_ != LSM6DS_ODR_OFF && (status & 0x01)) { // GDA - Gyroscope data available
|
|
uint8_t data[6];
|
|
if (this->read_register(0x22, data, 6)) {
|
|
int16_t gx = encode_uint16(data[1], data[0]);
|
|
int16_t gy = encode_uint16(data[3], data[2]);
|
|
int16_t gz = encode_uint16(data[5], data[4]);
|
|
if (this->gyro_x_sensor_)
|
|
this->gyro_x_sensor_->publish_state(gx * this->gyro_sensitivity_);
|
|
if (this->gyro_y_sensor_)
|
|
this->gyro_y_sensor_->publish_state(gy * this->gyro_sensitivity_);
|
|
if (this->gyro_z_sensor_)
|
|
this->gyro_z_sensor_->publish_state(gz * this->gyro_sensitivity_);
|
|
}
|
|
}
|
|
|
|
if (this->accel_odr_ != LSM6DS_ODR_OFF && (status & 0x02)) { // XLDA - Accelerometer data available
|
|
uint8_t data[6];
|
|
if (this->read_register(0x28, data, 6)) {
|
|
int16_t ax = encode_uint16(data[1], data[0]);
|
|
int16_t ay = encode_uint16(data[3], data[2]);
|
|
int16_t az = encode_uint16(data[5], data[4]);
|
|
float grav = 9.80665f;
|
|
if (this->accel_x_sensor_)
|
|
this->accel_x_sensor_->publish_state(ax * this->accel_sensitivity_ * grav);
|
|
if (this->accel_y_sensor_)
|
|
this->accel_y_sensor_->publish_state(ay * this->accel_sensitivity_ * grav);
|
|
if (this->accel_z_sensor_)
|
|
this->accel_z_sensor_->publish_state(az * this->accel_sensitivity_ * grav);
|
|
}
|
|
}
|
|
|
|
if (status & 0x04) { // TDA - Temperature data available
|
|
uint8_t data[2];
|
|
if (this->read_register(0x20, data, 2)) {
|
|
int16_t temp = encode_uint16(data[1], data[0]);
|
|
if (this->temperature_sensor_)
|
|
this->temperature_sensor_->publish_state(25.0f + (temp / 256.0f));
|
|
}
|
|
}
|
|
}
|
|
|
|
void LSM6DSComponent::dump_config() {
|
|
ESP_LOGCONFIG(TAG, "LSM6DS (LSM6DSOX/LSM6DS3TR-C/LSM6DSO32TR):");
|
|
LOG_UPDATE_INTERVAL(this);
|
|
if (this->is_failed()) {
|
|
ESP_LOGCONFIG(TAG, " Connection failed!");
|
|
return;
|
|
}
|
|
LOG_SENSOR(" ", "Accel X", this->accel_x_sensor_);
|
|
LOG_SENSOR(" ", "Accel Y", this->accel_y_sensor_);
|
|
LOG_SENSOR(" ", "Accel Z", this->accel_z_sensor_);
|
|
LOG_SENSOR(" ", "Gyro X", this->gyro_x_sensor_);
|
|
LOG_SENSOR(" ", "Gyro Y", this->gyro_y_sensor_);
|
|
LOG_SENSOR(" ", "Gyro Z", this->gyro_z_sensor_);
|
|
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
|
}
|
|
|
|
} // namespace lsm6ds_base
|
|
} // namespace esphome
|