From 663c1c028d53123ee457cc710c321f7494ed78a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Sat, 14 Mar 2026 22:06:04 +0100 Subject: [PATCH 1/2] lis2mdl: Auto-trigger single conversion in idle mode. --- lib/lis2mdl/lis2mdl/device.py | 11 ++++++++ tests/scenarios/lis2mdl.yaml | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/lib/lis2mdl/lis2mdl/device.py b/lib/lis2mdl/lis2mdl/device.py index a1d91aa3..c20d2c3d 100644 --- a/lib/lis2mdl/lis2mdl/device.py +++ b/lib/lis2mdl/lis2mdl/device.py @@ -168,6 +168,15 @@ def set_hw_offsets(self, x: int, y: int, z: int): # --- READ functions --- ## + def _ensure_data(self): + """Trigger a single conversion if the sensor is in idle mode.""" + if self.is_idle(): + self.set_mode("single") + for _ in range(50): + if self.data_ready(): + return + sleep_ms(2) + def read_magnet_raw(self): """Reads the raw magnetic field (LSB). Same as read_magnet(), but more explicit.""" return self.read_magnet() # (x,y,z) int16 LSB @@ -222,6 +231,7 @@ def _to_int16(v): def read_magnet(self): # Read the raw magnetic field data (X, Y, Z) from the sensor. + self._ensure_data() buf = self.i2c.readfrom_mem(self.address, LIS2MDL_OUTX_L_REG | 0x80, 6) x = self._to_int16((buf[1] << 8) | buf[0]) y = self._to_int16((buf[3] << 8) | buf[2]) @@ -232,6 +242,7 @@ def read_magnet(self): def read_temperature_raw(self) -> int: """Reads the raw temperature (LSB), 8 LSB/°C, absolute offset not guaranteed.""" + self._ensure_data() lo = self._read_reg(LIS2MDL_TEMP_OUT_L_REG) hi = self._read_reg(LIS2MDL_TEMP_OUT_H_REG) v = (hi << 8) | lo diff --git a/tests/scenarios/lis2mdl.yaml b/tests/scenarios/lis2mdl.yaml index 54e0b9f3..85979017 100644 --- a/tests/scenarios/lis2mdl.yaml +++ b/tests/scenarios/lis2mdl.yaml @@ -86,6 +86,57 @@ tests: expect_range: [19.0, 21.0] mode: [mock] + # ----- Auto-trigger ----- + + - name: "Magnetic field readable after power down" + action: script + script: | + dev.power_down() + x, y, z = dev.read_magnet() + result = isinstance(x, int) and isinstance(y, int) and isinstance(z, int) + expect_true: true + mode: [mock] + + - name: "Temperature readable after power down" + action: script + script: | + dev.power_down() + t = dev.read_temperature_c() + result = isinstance(t, float) + expect_true: true + mode: [mock] + + - name: "No auto-trigger when already active" + action: script + script: | + dev.read_magnet() + i2c.clear_write_log() + dev.read_magnet() + log = i2c.get_write_log() + result = len(log) == 0 + expect_true: true + mode: [mock] + + - name: "Fresh magnitude after power down" + action: script + script: | + dev.power_down() + mag = dev.magnitude_uT() + result = 10.0 < mag < 300.0 + expect_true: true + mode: [hardware] + + - name: "Fresh temperature after power down" + action: script + script: | + dev.power_down() + t = dev.read_temperature_c() + result = 10.0 < t < 45.0 + expect_true: true + mode: [hardware] + + # ----- Hardware ----- + - name: "Magnitude in plausible range" action: call method: magnitude_uT From 47568de4b75b8d9d28af764caf2948853115fbc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Sat, 14 Mar 2026 22:31:32 +0100 Subject: [PATCH 2/2] lis2mdl: Address Copilot review on auto-trigger PR. --- lib/lis2mdl/lis2mdl/device.py | 1 + tests/scenarios/lis2mdl.yaml | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/lis2mdl/lis2mdl/device.py b/lib/lis2mdl/lis2mdl/device.py index c20d2c3d..8f97be0c 100644 --- a/lib/lis2mdl/lis2mdl/device.py +++ b/lib/lis2mdl/lis2mdl/device.py @@ -176,6 +176,7 @@ def _ensure_data(self): if self.data_ready(): return sleep_ms(2) + raise OSError("LIS2MDL data ready timeout") def read_magnet_raw(self): """Reads the raw magnetic field (LSB). Same as read_magnet(), but more explicit.""" diff --git a/tests/scenarios/lis2mdl.yaml b/tests/scenarios/lis2mdl.yaml index 85979017..5a546a1b 100644 --- a/tests/scenarios/lis2mdl.yaml +++ b/tests/scenarios/lis2mdl.yaml @@ -106,6 +106,18 @@ tests: expect_true: true mode: [mock] + - name: "Auto-trigger writes single mode to CFG_REG_A" + action: script + script: | + dev.power_down() + i2c.clear_write_log() + dev.read_magnet() + log = i2c.get_write_log() + wrote_cfg_a = any(reg == 0x60 for reg, data in log) + result = wrote_cfg_a + expect_true: true + mode: [mock] + - name: "No auto-trigger when already active" action: script script: |