Skip to content

Commit 02aeaf5

Browse files
committed
doc: Some ecosystem notes
1 parent 91eca8b commit 02aeaf5

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

doc/fifo_imu.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
# Implementing an IMU/accelerometer/gyro driver? Use the FIFO!
3+
4+
Hi everyone,
5+
my name is Jon and I work on machine learning for sensor systems,
6+
including condition monitoring of machines (at [Soundsensing](https://www.soundsensing.no/)),
7+
and an open-source TinyML library called [emlearn](https://github.com/emlearn/emlearn-micropython).
8+
9+
The usecases we care about often require high quality data and low-power.
10+
While trying to use MicroPython in this area, I have noticed one limitation in the ecosystem:
11+
The lack of FIFO support in IMU drivers.
12+
13+
So here is my attempt at raising this concern, and how we could address it :)
14+
15+
## Current state of IMU drivers
16+
17+
Most of the IMU drivers out there today have functions to read the current values
18+
of the accelerometer/gyro/magnetometer data.
19+
20+
EXAMPLE CODE
21+
22+
When one only does a single readings of the data, this works rather OK.
23+
For example to check the current orientation of a rarely moving object, say for asset tracking.
24+
25+
However when doing continious sampling, doing this by looping over.
26+
27+
Such continious sampling is needed for example when one tracks a moving object,
28+
detect gestures, implement a regulation loop (PID), measure vibrations etc.
29+
30+
## Problems with continious sampling using repeated polling
31+
32+
This is less-than-ideal for several reasons:
33+
34+
1. Any variation/delay in time of reading causes uneven sampling of data. Jitter/noise.
35+
2. Application processor must be constantly running. High power consumption.
36+
3. Hard for the program to do other work concurrently, while ensuring 1)
37+
38+
These problems become particualy painful at high samplerates,
39+
or in low-power / battery-powered scenarios,
40+
or when trying to do multiple things at the same time (concurrency).
41+
42+
These concerns are generally independent of the programming language (more of a system design issue).
43+
However - there are a couple of reasons why it can easily be more problematic in MicroPython:
44+
45+
1. Variable delays in execution time due to **garbage collection**.
46+
When MicroPython code executes, there will at some point be a need to do some garbage collection.
47+
The likelihood increases with how much allocations the code does,
48+
but can generally happen at any point in time.
49+
One garbage collection run may take many milliseconds, and will cause the data to be sampled at the wrong time.
50+
This can mess up the results of most types of analysis,
51+
be it Digital Signal Processing, control theory, or Machine Learning - because they rely on regularly sampled data.
52+
53+
2. Execution time might be too slow for high samplerates.
54+
To read at 1kHz+, code would need to spend under 1 ms per iteration,
55+
which can be hard to achieve in MicroPython.
56+
57+
## The solution: Use the FIFO buffer of the sensor
58+
59+
Any recent digital MEMS IMU will have a buffer that it can collect measurements into.
60+
Typically this is referred to as a FIFO, since it is a First In First Out type of buffer/queue.
61+
62+
For example the LIS2dh/LIS3dh acceleometers have a 32 samples deep FIFO for its 3 axes.
63+
The BMA421 can store up to 1024 bytes, allowing to store 170 samples.
64+
65+
When enabling FIFO mode, the sensor itself is responsible for timing the sampling.
66+
This means that.
67+
And our application code can then .
68+
As long as one reads the FIFO before it overflows, one gets perfectly sampled data - with minimum effort.
69+
70+
## How to implement
71+
72+
To support this kind of usage, the IMU driver should have:
73+
74+
- A function to enable FIFO sampling mode
75+
- A function to read the FIFO fill level
76+
- A function to read data from the FIFO. A)
77+
- Optionally: A function to enable interrupts. B)
78+
79+
A) I recommend that the data reading returns the raw bytes.
80+
This enables the application to decide when/if to convert to a physical unit such as gravity.
81+
82+
B) Most IMUs also support triggering an interrupt
83+
when the FIFO fill level has reached a certain threshold (watermark).
84+
This can be useful to get absolutely the most out of, but is not critical.
85+
One can still get most of the benefits still by polling the FIFO level
86+
and triggering readout based on that.
87+
It might also be that the interrupt pin is not connected, only I2C/SPI pins,
88+
so one should still support usage without interrupts.
89+
90+
## Application pseudo code
91+
92+
Here is some illustrative code for how such a driver could be used
93+
to implement low-power continious data analysis of short time-windows of IMU data.
94+
This could for example be human activity detection on a smartwatch,
95+
gesture detection for a "magic wand",
96+
animal activity detection on a LoRa tracker, et.c.
97+
98+
```
99+
SAMPLERATE = 25
100+
THRESHOLD = 25
101+
imu = SuperIMU2k(i2c=machine.I2C(...), odr=SAMPLERATE)
102+
103+
while True:
104+
level = imu.get_fifo_level()
105+
if level < THRESHOLD:
106+
samples = imu.read_fifo_data(THRESHOLD)
107+
108+
# should take 100 ms or less. Otherwise compensate the sleep time
109+
process_samples(samples)
110+
111+
machine.lightsleep(900)
112+
```
113+
114+
## Call to Action: Use the FIFO!
115+
116+
So next time you are implementing a driver for an IMU, please consider supporting using the FIFO!
117+
It will make the driver much more powerful and useable for a wider range of scenarios,
118+
enabling people to get higher data quality and lower power consumption.
119+
120+
121+
## Drivers with FIFO support
122+
123+
Here is an initial start of divers that support FIFO.
124+
Please let us know if you have made, or found more, and we can link them here!
125+
126+
- [BMA423](https://github.com/antirez/bma423-pure-mp/pull/5)
127+
- [LIS2DH/LIS3DH](). FIXME: publish a gist
128+
129+

doc/micropython-tinyml-status.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
How ready is MicroPython for use in a TinyML setting.
33

4+
##
5+
6+
47
## Efficient data processing
58

69
Good! Integer only code can be made quite fast with @micropython.native/viper
@@ -12,16 +15,21 @@ Floating point code cannot be optimized with @micropython.native
1215

1316
## Interoperability
1417

15-
No interoperable datastructure for multi-dimensional arrays
18+
No interoperable datastructure for multi-dimensional arrays.
19+
Ref notes on [multi_dimensional_arrays](multi_dimensional_arrays.md).
1620

1721
## Drivers
1822

1923
Almost no accelerometer/IMU drivers implement FIFO based-readout.
2024
Causes poor sampling accuracy / high jitter.
2125

22-
PDM microphones are not supported.
23-
ESP32
24-
RP2040
26+
PDM microphones are not supported, on any port?
27+
ESP32, RP2040, STM32, NRF52.
28+
29+
## Connectivity
30+
31+
Good support for WiFi based commmunication on ESP32.
32+
2533

2634
## Preprocessing
2735

0 commit comments

Comments
 (0)