adafruit/Adafruit_ICM20X

Re-initialization of the sensor causing heap memory growth

gmanrc opened this issue · 8 comments

I'm using this Adafruit sensor and library for a sensor node development.
One of the requirements is for the node to have extensive battery life, and I am optimizing battery life by using watchdog.sleep on the micro-controller, as well as cutting power to the sensors.
As a result, I have to re-initialize the sensor every time it wakes up. My problem is that the initialization appears to be cause memory leak, and the heap stack is growing. Eventually, there is no more free memory available and the node crashes.
I have other sensors that do not cause loss of free memory due to re-initialization.
Is there anything that can be done in the initialization code. My code is based of adafruit_icm20948_test example code provided.

are you deleting the object? allocated memory is freed there
https://github.com/adafruit/Adafruit_ICM20X/blob/master/Adafruit_ICM20X.cpp#L54

@caternuson & @ladyada thanks for your help on that for the MS8607. Unfortunately, for the icm20948 does not appear to currently have an init() function for re-initializing the sensors. There is reset(); but calling begin() after reset; is still taking up the free memory.

calling begin() after reset; is still taking up the free memory.

Call begin only once, in setup. Call reset in the loop.

Nothing in reset should be eating memory:

void Adafruit_ICM20X::reset(void) {
_setBank(0);
Adafruit_BusIO_Register pwr_mgmt1 = Adafruit_BusIO_Register(
i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, ICM20X_B0_PWR_MGMT_1, 1);
Adafruit_BusIO_RegisterBits reset_bit =
Adafruit_BusIO_RegisterBits(&pwr_mgmt1, 1, 7);
reset_bit.write(1);
delay(20);
while (reset_bit.read()) {
delay(10);
};
delay(50);
}

calling begin() after reset; is still taking up the free memory.

Call begin only once, in setup. Call reset in the loop.

Nothing in reset should be eating memory:

void Adafruit_ICM20X::reset(void) {
_setBank(0);
Adafruit_BusIO_Register pwr_mgmt1 = Adafruit_BusIO_Register(
i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, ICM20X_B0_PWR_MGMT_1, 1);
Adafruit_BusIO_RegisterBits reset_bit =
Adafruit_BusIO_RegisterBits(&pwr_mgmt1, 1, 7);
reset_bit.write(1);
delay(20);
while (reset_bit.read()) {
delay(10);
};
delay(50);
}

Thanks for the quick reply @caternuson. Unfortunately, when I call reset() in the loop without begin(), the the data output of the sensors is only zeroes. Again, as with the other sensor, I am turning this sensor on and off each time to economize battery life.

I tried both the reset embedded with icm20x.h and the reset in icm20948.h. The first causes the device to hang. The latter causes the sensors to output zeroes.

The code in _init is likely needed to be called also, to re-establish the basic sensor config. But that's private, so not accessible in user sketch. It's also where the unchecked allocations are occurring:

temp_sensor = new Adafruit_ICM20X_Temp(this);
accel_sensor = new Adafruit_ICM20X_Accelerometer(this);
gyro_sensor = new Adafruit_ICM20X_Gyro(this);
mag_sensor = new Adafruit_ICM20X_Magnetometer(this);

So seems like like maybe this is not possible with the current state of the library.

Thanks for identifying this @caternuson. I'll monitor this space for updates to the library, as having this all in sensor is great.
But I will need to adjust my hardware for now to multiple sensors to capture the same data and be compliant with my battery saving measures.