Context
goal
My final goal is to perform an fft on acceleration signals with specs at least:
- band between ~10 and ~1000 Hz
- spectral resolution ~1Hz
on a portable, cheap, low-power device.
hardware
I'd like to do this with cheap portable low power hardware so I opted for an adxl345 as accelerometer connected via i2c (but also spi would be viable) to an esp32-wrover as micro-controller, powered by a 18650 lipo battery. Of course there is no problem, if necessary, to opt for more expensive hardware staying around ~100 euros/dollars.
software
I know and like python more than I know and like C, so I decided to use micropython on the microcontroller to acquire data from the sensor and push it via wifi to a computer that will actually perform the fft.
Question
My question is very focused on how to pass acceleration signals from the accelerometer to the micro-controller via I2C: I have implemented a loop that lasts for the desired acquisition time (say 1 second) and on each iteration tests how much time has passed since the beginning and if it's a multiple of the desired frequency it read a value from the accelerometer via i2c
start = ticks_ns()
while ticks_ns() - start < acquisition_time * 1000000000:
curr_time = ticks_ns()
if curr_time - start < (n_act_meas * 999999999. / sampling_rate):
continue
buf[n_act_meas * 6:n_act_meas * 6 + 6] = i2c_read_bytes(address, regAddress, length=6) # 6bytes = 2bytes * 3 signals (xyz)
T[n_act_meas] = ticks_ns()
n_act_meas += 1
but this approach is not very precise on the interval between measures (~10% relative error) and has a top frequency of 2kHz in my implementation (below the max frequency of the accelerometer).
I feel like I'm doing something wrong: is it possible to read via i2c the last n measures from the accelerometer (where n~1000 in my case) so that the problem of the timing is relegated to the accelerometer that should have a system that is precise enough to guarantee the nominal max sampling frequency, and a precise distancing between measures?