diff --git a/README.md b/README.md index 9d201fbf..10012b8f 100644 --- a/README.md +++ b/README.md @@ -477,6 +477,7 @@ lib// - **Power methods**: `power_on()` / `power_off()`. All drivers must implement both. - **Status methods**: `_status()` returns the raw status register as an int (private), `data_ready()` returns True when all channels have new data, `_ready()` for per-channel readiness (e.g. `temperature_ready()`, `pressure_ready()`). - **Measurement methods**: bare noun without unit suffix only for `temperature()` (°C) and `humidity()` (%RH). All others include the unit: `pressure_hpa()`, `distance_mm()`, `voltage_mv()`, `acceleration_g()`, etc. `read()` for combined reading returning a tuple, `_raw()` for raw register values. +- **Mode methods**: `set_continuous(odr)` to start continuous measurements, `trigger_one_shot()` for a single conversion, `read_one_shot()` for trigger + wait + return data. ### Linting diff --git a/lib/hts221/hts221/device.py b/lib/hts221/hts221/device.py index 7b9748ab..074783f6 100644 --- a/lib/hts221/hts221/device.py +++ b/lib/hts221/hts221/device.py @@ -91,6 +91,12 @@ def set_odr(self, odr=0): t = self._read_reg(HTS221_CTRL_REG1) & 0xFC self._write_reg(HTS221_CTRL_REG1, t | odr) + def set_continuous(self, odr=1): + if odr == 0: + raise ValueError("ODR 0 is one-shot mode, use trigger_one_shot()") + self.power_on() + self.set_odr(odr) + # get/set Humidity and temperature average configuration def get_av(self): return self._read_reg(HTS221_AV_CONF) @@ -117,6 +123,19 @@ def trigger_one_shot(self): self._write_reg(HTS221_CTRL_REG2, ctrl2 | HTS221_CTRL2_ONE_SHOT) sleep_ms(15) + def read_one_shot(self): + self.trigger_one_shot() + h = self._read_reg16(HTS221_HUMIDITY_OUT_L) + t = self._read_reg16(HTS221_TEMP_OUT_L) + humidity = self.H0_rH + (self.H1_rH - self.H0_rH) * (h - self.H0_OUT) / ( + self.H1_OUT - self.H0_OUT + ) + factory = self.T0_degC + (self.T1_degC - self.T0_degC) * (t - self.T0_OUT) / ( + self.T1_OUT - self.T0_OUT + ) + temperature = self._temp_gain * factory + self._temp_offset + return humidity, temperature + def reboot(self): ctrl2 = self._read_reg(HTS221_CTRL_REG2) self._write_reg(HTS221_CTRL_REG2, ctrl2 | HTS221_CTRL2_BOOT) diff --git a/lib/lis2mdl/lis2mdl/device.py b/lib/lis2mdl/lis2mdl/device.py index 3de07ed3..259f630e 100644 --- a/lib/lis2mdl/lis2mdl/device.py +++ b/lib/lis2mdl/lis2mdl/device.py @@ -76,6 +76,21 @@ def set_odr(self, hz: int): reg = (reg & ~(0b11 << 2)) | (odr_bits << 2) self._write_reg(LIS2MDL_CFG_REG_A, reg) + def set_continuous(self, hz=10): + self.set_odr(hz) + self.set_mode("continuous") + + def trigger_one_shot(self): + self.set_mode("single") + + def read_one_shot(self): + self.trigger_one_shot() + for _ in range(50): + if self.data_ready(): + return self.magnetic_field() + sleep_ms(2) + raise OSError("LIS2MDL one-shot data ready timeout") + def set_low_power(self, enabled: bool): # LP bit (bit4) : 0=High-Res, 1=Low-Power reg = self._read_reg(LIS2MDL_CFG_REG_A) diff --git a/lib/wsen-hids/README.md b/lib/wsen-hids/README.md index 0c7b8493..fa8bcc50 100644 --- a/lib/wsen-hids/README.md +++ b/lib/wsen-hids/README.md @@ -121,7 +121,7 @@ This allows simple usage: ```python humidity, temperature = sensor.read() -Continuous measurements can be enabled with sensor.set_continuous_mode(). +Continuous measurements can be enabled with sensor.set_continuous(). # One-Shot Measurement @@ -144,7 +144,7 @@ sensor.read_one_shot(timeout_ms=500) Start continuous measurements: ```python -sensor.set_continuous_mode(WSEN_HIDS.ODR_1_HZ) +sensor.set_continuous(WSEN_HIDS.ODR_1_HZ) ``` Available output data rates: diff --git a/lib/wsen-hids/examples/continuous_mode.py b/lib/wsen-hids/examples/continuous_mode.py index 182c7365..a52f232f 100644 --- a/lib/wsen-hids/examples/continuous_mode.py +++ b/lib/wsen-hids/examples/continuous_mode.py @@ -7,7 +7,7 @@ sensor = WSEN_HIDS(i2c) -sensor.set_continuous_mode(WSEN_HIDS.ODR_1_HZ) +sensor.set_continuous(WSEN_HIDS.ODR_1_HZ) for _ in range(10): humidity, temperature = sensor.read() diff --git a/lib/wsen-hids/examples/full_test.py b/lib/wsen-hids/examples/full_test.py index a4d1d5d5..750a0e41 100644 --- a/lib/wsen-hids/examples/full_test.py +++ b/lib/wsen-hids/examples/full_test.py @@ -211,13 +211,13 @@ def test_continuous_mode(sensor, odr, label, wait_ms=1500, loops=5, delay_s=0.5) print_header("7) Continuous mode - {}".format(label)) try: - sensor.set_continuous_mode(odr=odr) + sensor.set_continuous(odr=odr) ctrl1 = read_reg(sensor, REG_CTRL_1) pd_ok = bool(ctrl1 & CTRL_1_PD) odr_ok = (ctrl1 & CTRL_1_ODR_MASK) == odr - print("CTRL_1 after set_continuous_mode = 0x{:02X}".format(ctrl1)) + print("CTRL_1 after set_continuous = 0x{:02X}".format(ctrl1)) if pd_ok: print_pass("PD bit set") @@ -283,7 +283,7 @@ def test_status_helpers(sensor): print_header("8) STATUS helpers") try: - sensor.set_continuous_mode(odr=ODR_1_HZ) + sensor.set_continuous(odr=ODR_1_HZ) sleep(1.5) h_avail = sensor.humidity_ready() @@ -312,7 +312,7 @@ def test_unitary_methods(sensor): print_header("9) humidity() and temperature()") try: - sensor.set_continuous_mode(odr=ODR_1_HZ) + sensor.set_continuous(odr=ODR_1_HZ) sleep(1.2) humidity_rh = sensor.humidity() diff --git a/lib/wsen-hids/wsen_hids/device.py b/lib/wsen-hids/wsen_hids/device.py index 5816b0bd..2a689acd 100644 --- a/lib/wsen-hids/wsen_hids/device.py +++ b/lib/wsen-hids/wsen_hids/device.py @@ -18,7 +18,7 @@ class WSEN_HIDS(object): - humidity() - temperature() - read_one_shot() - - set_continuous_mode() + - set_continuous() - set_one_shot_mode() - enable_bdu() - enable_heater() @@ -182,7 +182,7 @@ def set_one_shot_mode(self): ctrl1 &= ~CTRL_1_ODR_MASK # ODR = 00 => one-shot self._write_reg(REG_CTRL_1, ctrl1) - def set_continuous_mode(self, odr=ODR_1_HZ): + def set_continuous(self, odr=ODR_1_HZ): if odr not in (ODR_1_HZ, ODR_7_HZ, ODR_12_5_HZ): raise ValueError("Invalid ODR for continuous mode") diff --git a/tests/scenarios/hts221.yaml b/tests/scenarios/hts221.yaml index 8483ee22..8af1782e 100644 --- a/tests/scenarios/hts221.yaml +++ b/tests/scenarios/hts221.yaml @@ -108,6 +108,24 @@ tests: expect_not_none: true mode: [mock] + - name: "set_continuous enables sensor" + action: script + script: | + dev.power_off() + dev.set_continuous(1) + ctrl1 = i2c.readfrom_mem(dev.address, 0x20, 1)[0] + result = (ctrl1 & 0x80) != 0 and (ctrl1 & 0x03) != 0 + expect_true: true + mode: [mock] + + - name: "read_one_shot returns tuple" + action: script + script: | + h, t = dev.read_one_shot() + result = isinstance(h, float) and isinstance(t, float) + expect_true: true + mode: [mock] + - name: "Auto-trigger humidity after power_off" action: call setup: diff --git a/tests/scenarios/lis2mdl.yaml b/tests/scenarios/lis2mdl.yaml index e2eeabb8..30f1311a 100644 --- a/tests/scenarios/lis2mdl.yaml +++ b/tests/scenarios/lis2mdl.yaml @@ -86,6 +86,36 @@ tests: expect_range: [19.0, 21.0] mode: [mock] + # ----- Continuous / one-shot ----- + + - name: "set_continuous writes CFG_REG_A" + action: script + script: | + i2c.clear_write_log() + dev.set_continuous(10) + log = i2c.get_write_log() + wrote_cfg = any(reg == 0x60 for reg, data in log) + result = wrote_cfg + expect_true: true + mode: [mock] + + - name: "trigger_one_shot sets single mode" + action: script + script: | + dev.trigger_one_shot() + mode = dev.get_mode() + result = mode == "single" + expect_true: true + mode: [mock] + + - name: "read_one_shot returns tuple of 3 ints" + action: script + script: | + x, y, z = dev.read_one_shot() + result = isinstance(x, int) and isinstance(y, int) and isinstance(z, int) + expect_true: true + mode: [mock] + # ----- Auto-trigger ----- - name: "Magnetic field readable after power down" diff --git a/tests/scenarios/wsen_hids.yaml b/tests/scenarios/wsen_hids.yaml index 53e582a8..3748f195 100644 --- a/tests/scenarios/wsen_hids.yaml +++ b/tests/scenarios/wsen_hids.yaml @@ -77,6 +77,16 @@ tests: expect_range: [24.0, 26.0] mode: [mock] + - name: "set_continuous activates sensor" + action: script + script: | + dev.power_off() + dev.set_continuous() + ctrl1 = i2c.readfrom_mem(dev.address, 0x20, 1)[0] + result = (ctrl1 & 0x80) != 0 + expect_true: true + mode: [mock] + - name: "Power off clears PD bit" action: script script: |