mirror of
https://github.com/jdillenburg/esphome.git
synced 2026-01-10 07:10:39 -07:00
matthiazzz - The current adxl345 component in ESPHome relies on multiple external Adafruit libraries (Adafruit Unified Sensor, Adafruit BusIO, Adafruit ADXL345). This causes unnecessary dependencies, compilation overhead, and sometimes incompatibilities when used with tca9548a multiplexers.
I modified the component to remove all Adafruit library dependencies and instead use a lightweight, self-contained ESPHome driver for ADXL345. After these changes, multiple ADXL345 sensors can be used in combination with a TCA9548A I²C multiplexer without conflicts.
This commit is contained in:
@@ -6,7 +6,6 @@ from esphome.components import i2c, sensor
|
||||
DEPENDENCIES = ['i2c']
|
||||
AUTO_LOAD = ['sensor']
|
||||
MULTI_CONF = True
|
||||
CODEOWNERS = ["@jdillenburg"]
|
||||
|
||||
adxl345_ns = cg.esphome_ns.namespace('adxl345')
|
||||
ADXL345Component = adxl345_ns.class_('ADXL345Component', cg.PollingComponent, i2c.I2CDevice)
|
||||
@@ -61,17 +60,15 @@ CONFIG_SCHEMA = cv.Schema({
|
||||
accuracy_decimals=3,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
}).extend(cv.polling_component_schema("100ms")).extend(i2c.i2c_device_schema(0x53))
|
||||
}).extend(cv.polling_component_schema("1s")).extend(i2c.i2c_device_schema(0x53))
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
# Configure the range
|
||||
cg.add(var.set_range(config[CONF_RANGE]))
|
||||
|
||||
# Register sensors if configured
|
||||
if CONF_OFF_VERTICAL in config:
|
||||
sens = await sensor.new_sensor(config[CONF_OFF_VERTICAL])
|
||||
cg.add(var.set_off_vertical_sensor(sens))
|
||||
@@ -90,4 +87,4 @@ async def to_code(config):
|
||||
|
||||
if CONF_ACCEL_Z in config:
|
||||
sens = await sensor.new_sensor(config[CONF_ACCEL_Z])
|
||||
cg.add(var.set_accel_z_sensor(sens))
|
||||
cg.add(var.set_accel_z_sensor(sens))
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
#include "adxl345.h"
|
||||
##include "adxl345.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace esphome {
|
||||
namespace adxl345 {
|
||||
|
||||
static const char *const TAG = "adxl345";
|
||||
|
||||
// Register map
|
||||
static const uint8_t REG_DEVID = 0x00;
|
||||
static const uint8_t REG_POWER_CTL = 0x2D;
|
||||
static const uint8_t REG_DATA_FORMAT = 0x31;
|
||||
static const uint8_t REG_DATAX0 = 0x32;
|
||||
|
||||
void ADXL345Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ADXL345...");
|
||||
|
||||
if (!accel_.begin(this->address_)) {
|
||||
ESP_LOGE(TAG, "Could not find ADXL345 sensor at address 0x%02X!", this->address_);
|
||||
|
||||
// Check device ID
|
||||
uint8_t devid;
|
||||
if (this->read_register(REG_DEVID, &devid, 1) != i2c::ERROR_OK || devid != 0xE5) {
|
||||
ESP_LOGE(TAG, "ADXL345 not found at 0x%02X (id=0x%02X)", this->address_, devid);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Map our range enum values to Adafruit library constants
|
||||
range_t adafruit_range;
|
||||
ESP_LOGI(TAG, "Found ADXL345 at 0x%02X", this->address_);
|
||||
|
||||
// Set range
|
||||
uint8_t range_bits = 0;
|
||||
switch (this->range_) {
|
||||
case 0: // RANGE_2G
|
||||
adafruit_range = ADXL345_RANGE_2_G;
|
||||
break;
|
||||
case 1: // RANGE_4G
|
||||
adafruit_range = ADXL345_RANGE_4_G;
|
||||
break;
|
||||
case 2: // RANGE_8G
|
||||
adafruit_range = ADXL345_RANGE_8_G;
|
||||
break;
|
||||
case 3: // RANGE_16G
|
||||
adafruit_range = ADXL345_RANGE_16_G;
|
||||
break;
|
||||
default:
|
||||
adafruit_range = ADXL345_RANGE_2_G;
|
||||
break;
|
||||
case 0: range_bits = 0x00; break; // ±2g
|
||||
case 1: range_bits = 0x01; break; // ±4g
|
||||
case 2: range_bits = 0x02; break; // ±8g
|
||||
case 3: range_bits = 0x03; break; // ±16g
|
||||
}
|
||||
|
||||
accel_.setRange(adafruit_range);
|
||||
this->write_register(REG_DATA_FORMAT, &range_bits, 1);
|
||||
|
||||
// Enable measurement mode
|
||||
uint8_t power = 0x08;
|
||||
this->write_register(REG_POWER_CTL, &power, 1);
|
||||
|
||||
ESP_LOGD(TAG, "ADXL345 setup complete");
|
||||
}
|
||||
|
||||
@@ -43,7 +46,7 @@ void ADXL345Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ADXL345:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
|
||||
const char* range_str;
|
||||
switch (this->range_) {
|
||||
case 0: range_str = "2G"; break;
|
||||
@@ -53,57 +56,46 @@ void ADXL345Component::dump_config() {
|
||||
default: range_str = "Unknown"; break;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Range: %s", range_str);
|
||||
|
||||
if (this->off_vertical_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Off Vertical", this->off_vertical_);
|
||||
}
|
||||
if (this->jitter_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Jitter", this->jitter_);
|
||||
}
|
||||
if (this->accel_x_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Acceleration X", this->accel_x_);
|
||||
}
|
||||
if (this->accel_y_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Acceleration Y", this->accel_y_);
|
||||
}
|
||||
if (this->accel_z_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Acceleration Z", this->accel_z_);
|
||||
}
|
||||
|
||||
if (this->off_vertical_ != nullptr) LOG_SENSOR(" ", "Off Vertical", this->off_vertical_);
|
||||
if (this->jitter_ != nullptr) LOG_SENSOR(" ", "Jitter", this->jitter_);
|
||||
if (this->accel_x_ != nullptr) LOG_SENSOR(" ", "Acceleration X", this->accel_x_);
|
||||
if (this->accel_y_ != nullptr) LOG_SENSOR(" ", "Acceleration Y", this->accel_y_);
|
||||
if (this->accel_z_ != nullptr) LOG_SENSOR(" ", "Acceleration Z", this->accel_z_);
|
||||
}
|
||||
|
||||
void ADXL345Component::update() {
|
||||
sensors_event_t event;
|
||||
accel_.getEvent(&event);
|
||||
|
||||
// Publish raw accelerometer values if sensors are configured
|
||||
if (this->accel_x_ != nullptr) {
|
||||
this->accel_x_->publish_state(event.acceleration.x);
|
||||
uint8_t buffer[6];
|
||||
if (this->read_register(REG_DATAX0, buffer, 6) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Failed to read data");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->accel_y_ != nullptr) {
|
||||
this->accel_y_->publish_state(event.acceleration.y);
|
||||
}
|
||||
|
||||
if (this->accel_z_ != nullptr) {
|
||||
this->accel_z_->publish_state(event.acceleration.z);
|
||||
}
|
||||
|
||||
// Calculate and publish off_vertical if sensor is configured
|
||||
|
||||
int16_t raw_x = (int16_t)(buffer[1] << 8 | buffer[0]);
|
||||
int16_t raw_y = (int16_t)(buffer[3] << 8 | buffer[2]);
|
||||
int16_t raw_z = (int16_t)(buffer[5] << 8 | buffer[4]);
|
||||
|
||||
// Scale: 4 mg/LSB in full-res mode (0.004 g), convert to m/s²
|
||||
float scale = 0.004f * 9.80665f;
|
||||
float x = raw_x * scale;
|
||||
float y = raw_y * scale;
|
||||
float z = raw_z * scale;
|
||||
|
||||
if (this->accel_x_ != nullptr) this->accel_x_->publish_state(x);
|
||||
if (this->accel_y_ != nullptr) this->accel_y_->publish_state(y);
|
||||
if (this->accel_z_ != nullptr) this->accel_z_->publish_state(z);
|
||||
|
||||
if (this->off_vertical_ != nullptr) {
|
||||
double pitch_amount = atan(event.acceleration.y /
|
||||
sqrt(pow(event.acceleration.x, 2) + pow(event.acceleration.z, 2))) * 180 / PI;
|
||||
double roll_amount = atan(-1 * event.acceleration.x /
|
||||
sqrt(pow(event.acceleration.y, 2) + pow(event.acceleration.z, 2))) * 180 / PI;
|
||||
|
||||
this->off_vertical_->publish_state(max(abs(pitch_amount), abs(roll_amount)));
|
||||
double pitch = atan(y / sqrt(pow(x, 2) + pow(z, 2))) * 180.0 / M_PI;
|
||||
double roll = atan(-x / sqrt(pow(y, 2) + pow(z, 2))) * 180.0 / M_PI;
|
||||
this->off_vertical_->publish_state(std::max(std::abs(pitch), std::abs(roll)));
|
||||
}
|
||||
|
||||
// Calculate and publish jitter if sensor is configured
|
||||
|
||||
if (this->jitter_ != nullptr) {
|
||||
float jitter_value = abs(event.acceleration.x) + abs(event.acceleration.y) + abs(event.acceleration.z);
|
||||
this->jitter_->publish_state(jitter_value);
|
||||
float jitter = fabs(x) + fabs(y) + fabs(z);
|
||||
this->jitter_->publish_state(jitter);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace adxl345
|
||||
} // namespace esphome
|
||||
} // namespace adxl345
|
||||
} // namespace esphome
|
||||
|
||||
@@ -3,16 +3,13 @@
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <Adafruit_ADXL345_U.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace adxl345 {
|
||||
|
||||
class ADXL345Component : public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
ADXL345Component() : PollingComponent(100) {}
|
||||
ADXL345Component() : PollingComponent(1000) {}
|
||||
|
||||
void setup() override;
|
||||
void update() override;
|
||||
@@ -23,18 +20,16 @@ class ADXL345Component : public PollingComponent, public i2c::I2CDevice {
|
||||
void set_accel_x_sensor(sensor::Sensor *accel_x) { accel_x_ = accel_x; }
|
||||
void set_accel_y_sensor(sensor::Sensor *accel_y) { accel_y_ = accel_y; }
|
||||
void set_accel_z_sensor(sensor::Sensor *accel_z) { accel_z_ = accel_z; }
|
||||
|
||||
void set_range(uint8_t range) { range_ = range; }
|
||||
|
||||
protected:
|
||||
Adafruit_ADXL345_Unified accel_{12345};
|
||||
sensor::Sensor *off_vertical_{nullptr};
|
||||
sensor::Sensor *jitter_{nullptr};
|
||||
sensor::Sensor *accel_x_{nullptr};
|
||||
sensor::Sensor *accel_y_{nullptr};
|
||||
sensor::Sensor *accel_z_{nullptr};
|
||||
uint8_t range_{0}; // Default to 2G range (0)
|
||||
uint8_t range_{0}; // Default 2G
|
||||
};
|
||||
|
||||
} // namespace adxl345
|
||||
} // namespace esphome
|
||||
} // namespace adxl345
|
||||
} // namespace esphome
|
||||
|
||||
Reference in New Issue
Block a user