Files
jdillenburg-esphome/components/adxl345/adxl345.cpp
John Dillenburg 7dc846a6eb 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.
2025-09-06 15:38:59 -05:00

102 lines
3.2 KiB
C++

##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...");
// 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;
}
ESP_LOGI(TAG, "Found ADXL345 at 0x%02X", this->address_);
// Set range
uint8_t range_bits = 0;
switch (this->range_) {
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
}
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");
}
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;
case 1: range_str = "4G"; break;
case 2: range_str = "8G"; break;
case 3: range_str = "16G"; break;
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_);
}
void ADXL345Component::update() {
uint8_t buffer[6];
if (this->read_register(REG_DATAX0, buffer, 6) != i2c::ERROR_OK) {
ESP_LOGW(TAG, "Failed to read data");
return;
}
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 = 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)));
}
if (this->jitter_ != nullptr) {
float jitter = fabs(x) + fabs(y) + fabs(z);
this->jitter_->publish_state(jitter);
}
}
} // namespace adxl345
} // namespace esphome