mirror of
https://github.com/esphome/esphome.git
synced 2026-10-17 11:42:51 +00:00
[components] Use sign_extend for raw sensor readings (#20934)
This commit is contained in:
@@ -11,12 +11,6 @@
|
||||
|
||||
namespace esphome::ade7880 {
|
||||
|
||||
// adapted from https://stackoverflow.com/a/55912127/1886371
|
||||
template<size_t Bits, typename T> inline T sign_extend(const T &v) noexcept {
|
||||
using S = struct { signed Val : Bits; };
|
||||
return reinterpret_cast<const S *>(&v)->Val;
|
||||
}
|
||||
|
||||
// Register types
|
||||
// unsigned 8-bit (uint8_t)
|
||||
// signed 10-bit - 16-bit ZP on wire (int16_t, needs sign extension)
|
||||
@@ -49,7 +43,7 @@ uint16_t ADE7880::read_u16_register16_(uint16_t a_register) {
|
||||
|
||||
int32_t ADE7880::read_s24zp_register16_(uint16_t a_register) {
|
||||
// s24zp means 24 bit signed value in the lower 24 bits of a 32-bit register
|
||||
int32_t in;
|
||||
uint32_t in;
|
||||
this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
|
||||
return sign_extend<24>(convert_big_endian(in));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "bme280_base.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <esphome/components/sensor/sensor.h>
|
||||
#include <esphome/core/component.h>
|
||||
@@ -144,11 +145,10 @@ void BME280Component::setup() {
|
||||
this->calibration_.h1 = read_u8_(BME280_REGISTER_DIG_H1);
|
||||
this->calibration_.h2 = read_s16_le_(BME280_REGISTER_DIG_H2);
|
||||
this->calibration_.h3 = read_u8_(BME280_REGISTER_DIG_H3);
|
||||
// h4 and h5 are signed 12-bit values; shift left then arithmetic right shift to sign-extend
|
||||
int16_t h4_raw = read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F);
|
||||
this->calibration_.h4 = static_cast<int16_t>(h4_raw << 4) >> 4;
|
||||
int16_t h5_raw = read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4);
|
||||
this->calibration_.h5 = static_cast<int16_t>(h5_raw << 4) >> 4;
|
||||
this->calibration_.h4 =
|
||||
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F));
|
||||
this->calibration_.h5 =
|
||||
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4));
|
||||
this->calibration_.h6 = read_u8_(BME280_REGISTER_DIG_H6);
|
||||
|
||||
uint8_t humid_control_val = 0;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "cs5460a.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::cs5460a {
|
||||
@@ -304,7 +305,7 @@ bool CS5460AComponent::check_status_() {
|
||||
voltage_sensor_->publish_state(raw_voltage * voltage_multiplier_);
|
||||
|
||||
if (power_sensor_ != nullptr && raw_energy != prev_raw_energy_) {
|
||||
int32_t raw = (int32_t) (raw_energy << 8) >> 8; /* Sign-extend */
|
||||
int32_t raw = sign_extend<24>(raw_energy);
|
||||
power_sensor_->publish_state(raw * power_multiplier_);
|
||||
prev_raw_energy_ = raw_energy;
|
||||
}
|
||||
|
||||
@@ -67,9 +67,7 @@ bool HX711Sensor::read_sensor_(uint32_t *result) {
|
||||
|
||||
this->status_clear_warning();
|
||||
|
||||
if (data & 0x800000ULL) {
|
||||
data |= 0xFF000000ULL;
|
||||
}
|
||||
data = static_cast<uint32_t>(sign_extend<24>(data));
|
||||
|
||||
if (result != nullptr)
|
||||
*result = data;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "max31856.h"
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <cmath>
|
||||
|
||||
@@ -53,12 +54,8 @@ void MAX31856Sensor::read_thermocouple_temperature_() {
|
||||
// Faults have been logged, clear it for next loop
|
||||
this->clear_fault_();
|
||||
} else {
|
||||
int32_t temp24 = this->read_register24_(MAX31856_LTCBH_REG);
|
||||
if (temp24 & 0x800000) {
|
||||
temp24 |= 0xFF000000; // fix sign
|
||||
}
|
||||
|
||||
temp24 >>= 5; // bottom 5 bits are unused
|
||||
// bottom 5 bits are unused
|
||||
const int32_t temp24 = sign_extend<24>(this->read_register24_(MAX31856_LTCBH_REG)) >> 5;
|
||||
|
||||
float temp_c = temp24;
|
||||
temp_c *= 0.0078125;
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
#include "max9611.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/i2c/i2c_bus.h"
|
||||
|
||||
namespace esphome::max9611 {
|
||||
using namespace esphome::i2c;
|
||||
// Sign extend
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
|
||||
template<typename T, unsigned B> inline T signextend(const T x) {
|
||||
struct {
|
||||
T x : B;
|
||||
} s;
|
||||
return s.x = x;
|
||||
}
|
||||
// Map the gain register to in uV/LSB
|
||||
float gain_to_lsb(MAX9611Multiplexer gain) {
|
||||
float lsb = 0.0;
|
||||
@@ -72,7 +65,7 @@ void MAX9611Component::update() {
|
||||
uint16_t t_register = ((register_map_[TEMP_DATA_BYTE_MSB_ADRR] << 8) | (register_map_[TEMP_DATA_BYTE_LSB_ADRR])) >> 7;
|
||||
float voltage = rs_register * VOUT_LSB;
|
||||
float shunt_voltage = (csa_register * gain_to_lsb(gain_)) / MICRO_VOLTS_PER_VOLT;
|
||||
float temp = signextend<signed int, 9>(t_register) * TEMP_LSB;
|
||||
float temp = sign_extend<9>(t_register) * TEMP_LSB;
|
||||
float amps = shunt_voltage / current_resistor_;
|
||||
float watts = amps * voltage;
|
||||
|
||||
|
||||
@@ -127,8 +127,7 @@ i2c::ErrorCode XDB401Component::read_pressure_(float &pressure) {
|
||||
format_hex_pretty_to(pressure_buf, sizeof(pressure_buf), p_data, 3);
|
||||
ESP_LOGV(TAG, "Got pressure data: %s", pressure_buf);
|
||||
|
||||
// Sign-extend 24-bit big-endian pressure value to int32_t.
|
||||
int32_t raw_pressure = static_cast<int32_t>(encode_uint24(p_data[0], p_data[1], p_data[2]) << 8) >> 8;
|
||||
int32_t raw_pressure = sign_extend<24>(encode_uint24(p_data[0], p_data[1], p_data[2]));
|
||||
ESP_LOGD(TAG, "Pressure data raw %" PRId32, raw_pressure);
|
||||
|
||||
pressure = (static_cast<float>(raw_pressure) / CONVERT_PRESSURE) *
|
||||
|
||||
@@ -76,9 +76,7 @@ void XGZP68XXComponent::update() {
|
||||
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_);
|
||||
const float pressure_in_pa = static_cast<float>(sign_extend<24>(pressure_raw)) / this->k_value_;
|
||||
|
||||
float temperature = ((float) (int16_t) temperature_raw) / 256.0f;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user