Skip to content

Commit 338338f

Browse files
sebromerodpgeorge
authored andcommitted
lsm6dsox: Add pedometer support.
This commit adds basic support for the LSM6DSOX IMU's built-in pedometer feature in the MicroPython driver, including new register definitions, and helper methods. The main changes enable step counting, step detection interrupts, and configuration of debounce steps. Signed-off-by: Sebastian Romero <s.romero@arduino.cc>
1 parent d0511a4 commit 338338f

2 files changed

Lines changed: 95 additions & 9 deletions

File tree

micropython/drivers/imu/lsm6dsox/lsm6dsox.py

Lines changed: 94 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@
6060
_OUTX_L_G = const(0x22)
6161
_OUTX_L_XL = const(0x28)
6262
_MLC_STATUS = const(0x38)
63+
_MD1_CFG = const(0x5E)
64+
_MD2_CFG = const(0x5F)
65+
66+
_PAGE_SEL = const(0x02)
67+
_PAGE_ADDRESS = const(0x08)
68+
_PAGE_VALUE = const(0x09)
69+
_PAGE_RW = const(0x17)
6370

6471
_DEFAULT_ADDR = const(0x6A)
6572
_WHO_AM_I_REG = const(0x0F)
@@ -75,6 +82,17 @@
7582

7683
_EMB_FUNC_EN_A = const(0x04)
7784
_EMB_FUNC_EN_B = const(0x05)
85+
_EMB_FUNC_INT1 = const(0x0A)
86+
_EMB_FUNC_INT2 = const(0x0E)
87+
_EMB_FUNC_SRC = const(0x64)
88+
_STEP_COUNTER_L = const(0x62)
89+
90+
_PEDO_DEB_STEPS_CONF = const(0x0184)
91+
92+
_PEDO_EN_MASK = const(0x08)
93+
_PEDO_RST_STEP_MASK = const(0x80)
94+
_PEDO_INT_MASK = const(0x08)
95+
_INT_EMB_FUNC_MASK = const(0x02)
7896

7997

8098
class LSM6DSOX:
@@ -108,8 +126,9 @@ def __init__(
108126
if self._read_reg(_WHO_AM_I_REG) != 108:
109127
raise OSError("No LSM6DS device was found at address 0x%x" % (self.address))
110128

111-
# allocate scratch buffer for efficient conversions and memread op's
129+
# allocate scratch buffers for efficient conversions and memread op's
112130
self.scratch_int = array.array("h", [0, 0, 0])
131+
self.scratch_2b = bytearray(2)
113132

114133
SCALE_GYRO = {250: 0, 500: 1, 1000: 2, 2000: 3}
115134
SCALE_ACCEL = {2: 0, 4: 2, 8: 3, 16: 1}
@@ -185,6 +204,9 @@ def _write_reg(self, reg, val):
185204
finally:
186205
self.cs(1)
187206

207+
def _modify_bits(self, reg, clr_mask=0, set_mask=0):
208+
self._write_reg(reg, (self._read_reg(reg) & ~clr_mask) | set_mask)
209+
188210
def _read_reg_into(self, reg, buf):
189211
if self._use_i2c:
190212
self.bus.readfrom_mem_into(self.address, reg, buf)
@@ -196,17 +218,51 @@ def _read_reg_into(self, reg, buf):
196218
finally:
197219
self.cs(1)
198220

221+
def _select_page(self, address, value=None):
222+
"""
223+
Selects the embedded function page and reads/writes the value at the given address.
224+
If value is None, it reads the value at the address. Otherwise, it writes the value to the address.
225+
"""
226+
msb = (address >> 8) & 0x0F # MSB is the page number
227+
lsb = address & 0xFF # LSB is the register address within the page
228+
229+
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
230+
231+
rw_bit = 0x20 if value is None else 0x40
232+
# Clear both read and write bits first, then set read (bit 5) or write (bit 6).
233+
self._modify_bits(_PAGE_RW, clr_mask=0x60, set_mask=rw_bit)
234+
235+
# select page
236+
self._write_reg(_PAGE_SEL, (msb << 4) | 0x01)
237+
238+
# set page addr
239+
self._write_reg(_PAGE_ADDRESS, lsb)
240+
241+
val = None
242+
if value is None:
243+
# read value
244+
val = self._read_reg(_PAGE_VALUE)
245+
else:
246+
# write value
247+
self._write_reg(_PAGE_VALUE, value)
248+
249+
# unset page write/read and page_sel
250+
self._write_reg(_PAGE_SEL, 0x01)
251+
self._modify_bits(_PAGE_RW, clr_mask=rw_bit)
252+
253+
self.set_mem_bank(_FUNC_CFG_BANK_USER)
254+
return val
255+
199256
def reset(self):
200-
self._write_reg(_CTRL3_C, self._read_reg(_CTRL3_C) | 0x1)
257+
self._modify_bits(_CTRL3_C, set_mask=0x1)
201258
for i in range(10):
202259
if (self._read_reg(_CTRL3_C) & 0x01) == 0:
203260
return
204261
time.sleep_ms(10)
205262
raise OSError("Failed to reset LSM6DS device.")
206263

207264
def set_mem_bank(self, bank):
208-
cfg = self._read_reg(_FUNC_CFG_ACCESS) & 0x3F
209-
self._write_reg(_FUNC_CFG_ACCESS, cfg | (bank << 6))
265+
self._modify_bits(_FUNC_CFG_ACCESS, clr_mask=0xC0, set_mask=(bank << 6))
210266

211267
def set_embedded_functions(self, enable, emb_ab=None):
212268
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
@@ -234,18 +290,18 @@ def load_mlc(self, ucf):
234290
emb_ab = self.set_embedded_functions(False)
235291

236292
# Disable I3C interface
237-
self._write_reg(_CTRL9_XL, self._read_reg(_CTRL9_XL) | 0x01)
293+
self._modify_bits(_CTRL9_XL, set_mask=0x01)
238294

239295
# Enable Block Data Update
240-
self._write_reg(_CTRL3_C, self._read_reg(_CTRL3_C) | 0x40)
296+
self._modify_bits(_CTRL3_C, set_mask=0x40)
241297

242298
# Route signals on interrupt pin 1
243299
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
244-
self._write_reg(_MLC_INT1, self._read_reg(_MLC_INT1) & 0x01)
300+
self._modify_bits(_MLC_INT1, clr_mask=0xFE)
245301
self.set_mem_bank(_FUNC_CFG_BANK_USER)
246302

247303
# Configure interrupt pin mode
248-
self._write_reg(_TAP_CFG0, self._read_reg(_TAP_CFG0) | 0x41)
304+
self._modify_bits(_TAP_CFG0, set_mask=0x41)
249305

250306
self.set_embedded_functions(True, emb_ab)
251307

@@ -258,6 +314,36 @@ def mlc_output(self):
258314
self.set_mem_bank(_FUNC_CFG_BANK_USER)
259315
return buf
260316

317+
def pedometer_config(self, enable=True, debounce=10, int1_enable=False, int2_enable=False):
318+
"""Configure the pedometer features."""
319+
self._select_page(_PEDO_DEB_STEPS_CONF, debounce)
320+
321+
if int1_enable:
322+
self._modify_bits(_MD1_CFG, set_mask=_INT_EMB_FUNC_MASK)
323+
if int2_enable:
324+
self._modify_bits(_MD2_CFG, set_mask=_INT_EMB_FUNC_MASK)
325+
326+
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
327+
328+
self._modify_bits(_EMB_FUNC_EN_A, _PEDO_EN_MASK, enable and _PEDO_EN_MASK)
329+
self._modify_bits(_EMB_FUNC_INT1, _PEDO_INT_MASK, int1_enable and _PEDO_INT_MASK)
330+
self._modify_bits(_EMB_FUNC_INT2, _PEDO_INT_MASK, int2_enable and _PEDO_INT_MASK)
331+
332+
self.set_mem_bank(_FUNC_CFG_BANK_USER)
333+
334+
def pedometer_reset(self):
335+
"""Reset the step counter."""
336+
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
337+
self._modify_bits(_EMB_FUNC_SRC, set_mask=_PEDO_RST_STEP_MASK)
338+
self.set_mem_bank(_FUNC_CFG_BANK_USER)
339+
340+
def steps(self):
341+
"""Return the number of detected steps."""
342+
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
343+
self._read_reg_into(_STEP_COUNTER_L, self.scratch_2b)
344+
self.set_mem_bank(_FUNC_CFG_BANK_USER)
345+
return self.scratch_2b[0] | (self.scratch_2b[1] << 8)
346+
261347
def gyro(self):
262348
"""Returns gyroscope vector in degrees/sec."""
263349
mv = memoryview(self.scratch_int)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
metadata(description="ST LSM6DSOX imu driver.", version="1.0.1")
1+
metadata(description="ST LSM6DSOX imu driver.", version="1.1.0")
22
module("lsm6dsox.py", opt=3)

0 commit comments

Comments
 (0)