Files
esphome-lsm6ds/esphome/components/xgzp68xx/xgzp68xx.cpp
T

123 lines
3.8 KiB
C++

#include "xgzp68xx.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/components/i2c/i2c.h"
#include <cinttypes>
namespace esphome {
namespace xgzp68xx {
static const char *const TAG = "xgzp68xx.sensor";
static const uint8_t CMD_ADDRESS = 0x30;
static const uint8_t SYSCONFIG_ADDRESS = 0xA5;
static const uint8_t PCONFIG_ADDRESS = 0xA6;
static const uint8_t READ_COMMAND = 0x0A;
[[maybe_unused]] static const char *oversampling_to_str(XGZP68XXOversampling oversampling) {
switch (oversampling) {
case XGZP68XX_OVERSAMPLING_256X:
return "256x";
case XGZP68XX_OVERSAMPLING_512X:
return "512x";
case XGZP68XX_OVERSAMPLING_1024X:
return "1024x";
case XGZP68XX_OVERSAMPLING_2048X:
return "2048x";
case XGZP68XX_OVERSAMPLING_4096X:
return "4096x";
case XGZP68XX_OVERSAMPLING_8192X:
return "8192x";
case XGZP68XX_OVERSAMPLING_16384X:
return "16384x";
case XGZP68XX_OVERSAMPLING_32768X:
return "32768x";
default:
return "UNKNOWN";
}
}
void XGZP68XXComponent::update() {
// Do we need to change oversampling?
if (this->last_pressure_oversampling_ != this->pressure_oversampling_) {
uint8_t oldconfig = 0;
this->read_register(PCONFIG_ADDRESS, &oldconfig, 1);
uint8_t newconfig = (oldconfig & 0xf8) | (this->pressure_oversampling_ & 0x7);
this->write_register(PCONFIG_ADDRESS, &newconfig, 1);
ESP_LOGD(TAG, "oversampling to %s: oldconfig = 0x%x newconfig = 0x%x",
oversampling_to_str(this->pressure_oversampling_), oldconfig, newconfig);
this->last_pressure_oversampling_ = this->pressure_oversampling_;
}
// Request temp + pressure acquisition
this->write_register(0x30, &READ_COMMAND, 1);
// Wait 20mS per datasheet
this->set_timeout("measurement", 20, [this]() {
uint8_t data[5] = {};
uint32_t pressure_raw = 0;
uint16_t temperature_raw = 0;
int success;
// Read the sensor data
success = this->read_register(0x06, data, 5);
if (success != 0) {
ESP_LOGE(TAG, "Failed to read sensor data! Error code: %i", success);
return;
}
pressure_raw = encode_uint24(data[0], data[1], data[2]);
temperature_raw = encode_uint16(data[3], data[4]);
// Convert the pressure data to hPa
ESP_LOGV(TAG, "Got raw pressure=%" PRIu32 ", raw temperature=%u, K value=%u", pressure_raw, temperature_raw,
this->k_value_);
// Sign extend the pressure
float pressure_in_pa = (float) (((int32_t) pressure_raw << 8) >> 8);
pressure_in_pa /= (float) (this->k_value_);
float temperature = ((float) (int16_t) temperature_raw) / 256.0f;
if (this->pressure_sensor_ != nullptr)
this->pressure_sensor_->publish_state(pressure_in_pa);
if (this->temperature_sensor_ != nullptr)
this->temperature_sensor_->publish_state(temperature);
}); // end of set_timeout
}
void XGZP68XXComponent::setup() {
uint8_t config1 = 0, config2 = 0;
// Display some sample bits to confirm we are talking to the sensor
if (i2c::ErrorCode::ERROR_OK != this->read_register(SYSCONFIG_ADDRESS, &config1, 1)) {
this->mark_failed();
return;
}
if (i2c::ErrorCode::ERROR_OK != this->read_register(PCONFIG_ADDRESS, &config2, 1)) {
this->mark_failed();
return;
}
ESP_LOGD(TAG, "sys_config 0x%x, p_config 0x%x", config1, config2);
}
void XGZP68XXComponent::dump_config() {
ESP_LOGCONFIG(TAG, "XGZP68xx:");
LOG_SENSOR(" ", "Temperature: ", this->temperature_sensor_);
LOG_SENSOR(" ", "Pressure: ", this->pressure_sensor_);
if (this->pressure_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " Oversampling: %s", oversampling_to_str(this->pressure_oversampling_));
}
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, " Connection failed");
}
LOG_UPDATE_INTERVAL(this);
}
} // namespace xgzp68xx
} // namespace esphome