diff --git a/lib/ism330dl/ism330dl/device.py b/lib/ism330dl/ism330dl/device.py index efc432c2..1863c807 100644 --- a/lib/ism330dl/ism330dl/device.py +++ b/lib/ism330dl/ism330dl/device.py @@ -16,6 +16,9 @@ def __init__(self, i2c, address=ISM330DL_I2C_DEFAULT_ADDR): self._accel_scale = ACCEL_FS_2G self._gyro_scale = GYRO_FS_250DPS + self._temp_gain = 1.0 + self._temp_offset = 0.0 + self.check_device() self.reset() self.configure_accel(ACCEL_ODR_104HZ, ACCEL_FS_2G) @@ -149,8 +152,28 @@ def gyroscope_rads(self): return tuple(v * pi / 180.0 for v in dps) def temperature_c(self): - raw = self.temperature_raw() - return TEMP_OFFSET + raw / TEMP_SENSITIVITY + factory = TEMP_OFFSET + self.temperature_raw() / TEMP_SENSITIVITY + return self._temp_gain * factory + self._temp_offset + + def set_temp_offset(self, offset_c): + """Set a temperature offset in °C (gain remains 1.0).""" + self._temp_gain = 1.0 + self._temp_offset = float(offset_c) + + def calibrate_temperature(self, ref_low, measured_low, ref_high, measured_high): + """Two-point calibration from reference measurements. + + Args: + ref_low: reference temperature at the low point (°C). + measured_low: sensor reading at the low point (°C). + ref_high: reference temperature at the high point (°C). + measured_high: sensor reading at the high point (°C). + """ + delta = float(measured_high - measured_low) + if delta == 0.0: + raise ValueError("measured_low and measured_high must differ") + self._temp_gain = float(ref_high - ref_low) / delta + self._temp_offset = float(ref_low) - self._temp_gain * float(measured_low) def orientation(self): ax, ay, az = self.acceleration_g() diff --git a/tests/scenarios/board_temperature_comparison.yaml b/tests/scenarios/board_temperature_comparison.yaml index 70627241..9484c1c3 100644 --- a/tests/scenarios/board_temperature_comparison.yaml +++ b/tests/scenarios/board_temperature_comparison.yaml @@ -10,6 +10,7 @@ drivers: - wsen-hids - wsen-pads - lis2mdl + - ism330dl tests: - name: "Read all temperature sensors" @@ -20,6 +21,7 @@ tests: sys.path.insert(0, '/remote/wsen-hids') sys.path.insert(0, '/remote/wsen-pads') sys.path.insert(0, '/remote/lis2mdl') + sys.path.insert(0, '/remote/ism330dl') from machine import I2C from time import sleep_ms @@ -52,6 +54,12 @@ tests: mag = LIS2MDL(i2c) temps['LIS2MDL'] = mag.read_temperature_c() + # ISM330DL (auxiliary, offset not guaranteed by datasheet) + from ism330dl.device import ISM330DL + imu = ISM330DL(i2c) + sleep_ms(200) # stabilize after reset + temps['ISM330DL'] = imu.temperature_c() + # Print comparison table print('--- Temperature Comparison ---') for name, t in temps.items(): @@ -108,6 +116,7 @@ tests: sys.path.insert(0, '/remote/wsen-hids') sys.path.insert(0, '/remote/wsen-pads') sys.path.insert(0, '/remote/lis2mdl') + sys.path.insert(0, '/remote/ism330dl') from machine import I2C from time import sleep_ms @@ -131,6 +140,10 @@ tests: from lis2mdl.device import LIS2MDL mag = LIS2MDL(i2c) + from ism330dl.device import ISM330DL + imu = ISM330DL(i2c) + sleep_ms(200) # stabilize after reset + # Read reference just before each sensor to minimize drift ref_t = ref.temperature() hts_t = hts.temperature() @@ -141,34 +154,41 @@ tests: ref_t3 = ref.temperature() mag_t = mag.read_temperature_c() + ref_t4 = ref.temperature() + imu_t = imu.temperature_c() + print('--- Before offset alignment ---') print(' WSEN-HIDS (ref): ' + str(round(ref_t, 2)) + ' C') print(' HTS221: ' + str(round(hts_t, 2)) + ' C') print(' WSEN-PADS: ' + str(round(pads_t, 2)) + ' C') print(' LIS2MDL: ' + str(round(mag_t, 2)) + ' C') + print(' ISM330DL: ' + str(round(imu_t, 2)) + ' C') - spread_before = max(hts_t, pads_t, mag_t, ref_t) - min(hts_t, pads_t, mag_t, ref_t) + spread_before = max(hts_t, pads_t, mag_t, imu_t, ref_t) - min(hts_t, pads_t, mag_t, imu_t, ref_t) print(' Spread: ' + str(round(spread_before, 2)) + ' C') # Apply offset to align each sensor to the reference reading hts.set_temp_offset(ref_t - hts_t) pads.set_temp_offset(ref_t2 - pads_t) mag.set_temp_offset(ref_t3 - mag_t) + imu.set_temp_offset(ref_t4 - imu_t) # Re-read after offset alignment sleep_ms(50) - ref_t4 = ref.temperature() + ref_t5 = ref.temperature() hts_t2 = hts.temperature() pads_t2 = pads.temperature() mag_t2 = mag.read_temperature_c() + imu_t2 = imu.temperature_c() print('--- After offset alignment ---') - print(' WSEN-HIDS (ref): ' + str(round(ref_t4, 2)) + ' C') + print(' WSEN-HIDS (ref): ' + str(round(ref_t5, 2)) + ' C') print(' HTS221: ' + str(round(hts_t2, 2)) + ' C') print(' WSEN-PADS: ' + str(round(pads_t2, 2)) + ' C') print(' LIS2MDL: ' + str(round(mag_t2, 2)) + ' C') + print(' ISM330DL: ' + str(round(imu_t2, 2)) + ' C') - spread_after = max(hts_t2, pads_t2, mag_t2, ref_t4) - min(hts_t2, pads_t2, mag_t2, ref_t4) + spread_after = max(hts_t2, pads_t2, mag_t2, imu_t2, ref_t5) - min(hts_t2, pads_t2, mag_t2, imu_t2, ref_t5) print(' Spread: ' + str(round(spread_after, 2)) + ' C') # After alignment, spread should be < 2°C diff --git a/tests/scenarios/ism330dl.yaml b/tests/scenarios/ism330dl.yaml index 4a2a08c7..01976160 100644 --- a/tests/scenarios/ism330dl.yaml +++ b/tests/scenarios/ism330dl.yaml @@ -145,6 +145,33 @@ tests: expect_true: true mode: [mock] + - name: "Temperature offset shifts reading" + action: script + script: | + dev.set_temp_offset(-2.5) + result = abs(dev.temperature_c() - 22.5) < 0.1 + expect_true: true + mode: [mock] + + - name: "Temperature with two-point calibration" + action: script + script: | + dev.calibrate_temperature(20.0, 25.0, 30.0, 35.0) + result = dev.temperature_c() + expect_range: [19.0, 21.0] + mode: [mock] + + - name: "Calibration rejects equal measurements" + action: script + script: | + try: + dev.calibrate_temperature(20.0, 25.0, 30.0, 25.0) + result = False + except ValueError: + result = True + expect_true: true + mode: [mock] + - name: "Temperature in plausible range" action: call method: temperature_c