Hi, I'm using a Nordic nrf52832 in a custom board. Zephyr is working OK, but i have a strange issue. I have a ADXL345 accelerometer connected with i2c, I can read the sensor OK but has a high power consume, like 600uA when i start reading it and i can't put it to sleep.
Definition of device:
&pinctrl {
i2c1_default: i2c1_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 16)>,
<NRF_PSEL(TWIM_SCL, 0, 15)>;
};
};
i2c1_sleep: i2c1_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 16)>,
<NRF_PSEL(TWIM_SCL, 0, 15)>;
low-power-enable;
};
};
}
&i2c1 {
status = "okay";
pinctrl-0 = <&i2c1_default>;
pinctrl-1 = <&i2c1_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <I2C_BITRATE_STANDARD>;
accel0: adxl345@53 {
compatible = "adi,adxl345";
reg = < 0x53 >;
label = "ADX1345";
interrupts = < 27 26 >;
};
};
If I never access to the i2c then never get that high power consume, for example if in my device init function i put this:
i2c_dt_spec _accel = {
.bus = DEVICE_DT_GET(DT_BUS(DT_NODELABEL(accel0))),
.addr = DT_REG_ADDR(DT_NODELABEL(accel0))
}
if (!device_is_ready(_accel.bus)) {
__ASSERT(false, "Accel device is not ready");
}
Then the power usage of my device maintain a base of ~200-300 uA, but if i only read the ADXL345 ID registry:
enum class ACCEL_REGISTERS {
ADXL345_DEVICE_ID_REG = 0x00,
ADXL345_RATE_REG = 0x2c,
ADXL345_POWER_CTL_REG = 0x2d,
ADXL345_DATA_FORMAT_REG = 0x31,
ADXL345_X_AXIS_DATA_0_REG = 0x32,
ADXL345_FIFO_CTL_REG = 0x38,
ADXL345_FIFO_STATUS_REG = 0x39,
ADXL345_INT_ENABLE_REG = 0x2e,
};
auto dev_id = reg_read_byte(ACCEL_REGISTERS::ADXL345_DEVICE_ID_REG);
if (dev_id != ACCEL_DEVICE_ID)
{
LOG_ERR("Read PART ID failed: 0x%x", dev_id);
}
Then power usage rise up to ~600uA. I tried to use PM on i2c and not work:
pm_device_action_run(_accel.bus, PM_DEVICE_ACTION_SUSPEND);
or using the SLEEP registry of the ADX:
enum ACCEL_REGISTERS_VALUES {
ADXL345_FIFO_STREAM_MODE = (1 << 7),
ADXL345_RANGE_16G = 0x3,
//ADXL345_RATE_25HZ = 0x8,
ADXL345_RATE_0_78HZ = 0x3,
ADXL345_ENABLE_SLEEP_BIT = (1 << 2),
ADXL345_ENABLE_MEASURE_BIT = (1 << 3),
AXL345_POWER_CTL_SLEEP = 0b00110111,
}
reg_write_byte(ACCEL_REGISTERS::ADXL345_POWER_CTL_REG, AXL345_POWER_CTL_SLEEP);
My functions to read and write i2c:
enum class ACCEL_CMDS {
ADXL345_READ_CMD = 0x80,
ADXL345_WRITE_CMD = 0x00
};
void Accel::access_i2c(ACCEL_CMDS cmd, ACCEL_REGISTERS reg, std::span<std::uint8_t> data) const
{
int ret;
if (cmd == ACCEL_CMDS::ADXL345_READ_CMD) {
ret = i2c_burst_read_dt(&_accel, static_cast<std::uint8_t>(reg), data.data(), data.size());
} else {
ret = i2c_burst_write_dt(&_accel, static_cast<std::uint8_t>(reg), data.data(), data.size());
}
if (ret != 0) {
LOG_WRN("Error trying to access to i2c bus for accel: %d", ret);
}
}
std::vector<std::uint8_t> Accel::reg_read(ACCEL_REGISTERS address, std::size_t to_read) const
{
std::vector<std::uint8_t> ret(to_read, 0);
access_i2c(ACCEL_CMDS::ADXL345_READ_CMD, address, std::span{ret});
return ret;
}
void Accel::reg_write(ACCEL_REGISTERS address, std::span<std::uint8_t> data)
{
return access_i2c(ACCEL_CMDS::ADXL345_WRITE_CMD, address, data);
}
std::uint8_t Accel::reg_read_byte(ACCEL_REGISTERS address) {
return reg_read(address, 1)[0];
}
void Accel::reg_write_byte(ACCEL_REGISTERS address, std::uint8_t data)
{
std::array<std::uint8_t, 1> data_send = {data};
return reg_write(address, std::span{data_send});
}
Maybe I missing something, but i think that I2C activate on first sensor read and never sleep again, can you help me to find out the problem?
Power Usage of full device without ADXL345 reading:
When use ADXL345 reading: