diff --git a/lib/ism330dl/ism330dl/device.py b/lib/ism330dl/ism330dl/device.py index 1863c807..abb7c24b 100644 --- a/lib/ism330dl/ism330dl/device.py +++ b/lib/ism330dl/ism330dl/device.py @@ -14,7 +14,9 @@ def __init__(self, i2c, address=ISM330DL_I2C_DEFAULT_ADDR): self._buffer_1 = bytearray(1) self._accel_scale = ACCEL_FS_2G + self._accel_odr = ACCEL_ODR_104HZ self._gyro_scale = GYRO_FS_250DPS + self._gyro_odr = GYRO_ODR_104HZ self._temp_gain = 1.0 self._temp_offset = 0.0 @@ -101,6 +103,8 @@ def configure_accel(self, odr, scale): if scale not in ACCEL_FS_BITS: raise ISM330DLConfigError("Invalid accel scale") self._accel_scale = scale + if odr != ACCEL_ODR_POWER_DOWN: + self._accel_odr = odr value = (odr << 4) | (ACCEL_FS_BITS[scale] << 2) self._write_u8(REG_CTRL1_XL, value) @@ -114,19 +118,41 @@ def configure_gyro(self, odr, scale): raise ISM330DLConfigError("Invalid gyro scale") value = (odr << 4) | (GYRO_FS_BITS[scale] << 2) self._gyro_scale = scale + if odr != GYRO_ODR_POWER_DOWN: + self._gyro_odr = odr self._write_u8(REG_CTRL2_G, value) + # -------------------------------------------------- + # Auto-trigger + # -------------------------------------------------- + + def _is_power_down(self): + """Return True if both accel and gyro ODR are 0 (power-down).""" + ctrl1 = self._read_u8(REG_CTRL1_XL) + ctrl2 = self._read_u8(REG_CTRL2_G) + return (ctrl1 & 0xF0) == 0 and (ctrl2 & 0xF0) == 0 + + def _ensure_data(self): + """Restore previous ODR and wait for data if in power-down mode.""" + if self._is_power_down(): + self.configure_accel(self._accel_odr, self._accel_scale) + self.configure_gyro(self._gyro_odr, self._gyro_scale) + sleep_ms(100) + # -------------------------------------------------- # Raw readings # -------------------------------------------------- def acceleration_raw(self): + self._ensure_data() return self._read_vector(REG_OUTX_L_XL) def gyroscope_raw(self): + self._ensure_data() return self._read_vector(REG_OUTX_L_G) def temperature_raw(self): + self._ensure_data() return self._read_i16(REG_OUT_TEMP_L) # -------------------------------------------------- diff --git a/tests/scenarios/ism330dl.yaml b/tests/scenarios/ism330dl.yaml index 01976160..935f1ab7 100644 --- a/tests/scenarios/ism330dl.yaml +++ b/tests/scenarios/ism330dl.yaml @@ -297,6 +297,103 @@ tests: expect_true: true mode: [mock] + # ----- Auto-trigger ----- + + - name: "Acceleration readable after power down" + action: script + script: | + dev.power_down() + ax, ay, az = dev.acceleration_g() + result = isinstance(ax, float) and isinstance(ay, float) and isinstance(az, float) + expect_true: true + mode: [mock] + + - name: "Gyroscope readable after power down" + action: script + script: | + dev.power_down() + gx, gy, gz = dev.gyroscope_dps() + result = isinstance(gx, float) and isinstance(gy, float) and isinstance(gz, float) + expect_true: true + mode: [mock] + + - name: "Temperature readable after power down" + action: script + script: | + dev.power_down() + t = dev.temperature_c() + result = isinstance(t, float) + expect_true: true + mode: [mock] + + - name: "Auto-trigger restores ODR after power down" + action: script + script: | + dev.power_down() + dev.acceleration_raw() + ctrl1 = i2c.readfrom_mem(dev.address, 0x10, 1)[0] + ctrl2 = i2c.readfrom_mem(dev.address, 0x11, 1)[0] + result = (ctrl1 & 0xF0) != 0 and (ctrl2 & 0xF0) != 0 + expect_true: true + mode: [mock] + + - name: "Auto-trigger preserves custom ODR" + action: script + script: | + from ism330dl.const import ACCEL_ODR_26HZ, ACCEL_FS_2G, GYRO_ODR_52HZ, GYRO_FS_250DPS + dev.configure_accel(ACCEL_ODR_26HZ, ACCEL_FS_2G) + dev.configure_gyro(GYRO_ODR_52HZ, GYRO_FS_250DPS) + dev.power_down() + dev.acceleration_raw() + ctrl1 = i2c.readfrom_mem(dev.address, 0x10, 1)[0] + ctrl2 = i2c.readfrom_mem(dev.address, 0x11, 1)[0] + accel_odr = (ctrl1 >> 4) & 0x0F + gyro_odr = (ctrl2 >> 4) & 0x0F + result = accel_odr == ACCEL_ODR_26HZ and gyro_odr == GYRO_ODR_52HZ + expect_true: true + mode: [mock] + + - name: "Repeated power down and read cycle" + action: script + script: | + dev.power_down() + a1 = dev.acceleration_g() + dev.power_down() + a2 = dev.acceleration_g() + result = len(a1) == 3 and len(a2) == 3 + expect_true: true + mode: [mock] + + - name: "No register write when already active" + action: script + script: | + dev.acceleration_raw() + i2c.clear_write_log() + dev.acceleration_raw() + log = i2c.get_write_log() + result = len(log) == 0 + expect_true: true + mode: [mock] + + - name: "Fresh acceleration after power down" + action: script + script: | + dev.power_down() + ax, ay, az = dev.acceleration_g() + mag = (ax**2 + ay**2 + az**2) ** 0.5 + result = 0.8 < mag < 1.2 + expect_true: true + mode: [hardware] + + - name: "Fresh temperature after power down" + action: script + script: | + dev.power_down() + t = dev.temperature_c() + result = 10.0 < t < 50.0 + expect_true: true + mode: [hardware] + # ----- Hardware manual ----- - name: "Sensor readings feel correct"