diff --git a/lib/vl53l1x/vl53l1x/device.py b/lib/vl53l1x/vl53l1x/device.py index 6e43362d..79ff3157 100644 --- a/lib/vl53l1x/vl53l1x/device.py +++ b/lib/vl53l1x/vl53l1x/device.py @@ -136,40 +136,32 @@ def reset(self): machine.lightsleep(100) self._write_reg(0x0000, 0x01) + def start_ranging(self): + self._write_reg(0x0087, 0x40) + + def stop_ranging(self): + self._write_reg(0x0087, 0x00) + + def _is_data_ready(self): + polarity = self._read_reg(0x0030) & 0x10 + ready_val = 1 if polarity == 0 else 0 + return (self._read_reg(0x0031) & 0x01) == ready_val + + def _clear_interrupt(self): + self._write_reg(0x0086, 0x01) + + def _ensure_data(self): + if not self._is_data_ready(): + self.start_ranging() + for _ in range(100): + if self._is_data_ready(): + return + machine.lightsleep(10) + raise OSError("VL53L1X data ready timeout") + def read(self): - data = self.i2c.readfrom_mem(self.address, 0x0089, 17, addrsize=16) # RESULT__RANGE_STATUS - # range_status = data[0] - # report_status = data[1] - # stream_count = data[2] - # dss_actual_effective_spads_sd0 = (data[3] << 8) + data[4] - # peak_signal_count_rate_mcps_sd0 = (data[5]<<8) + data[6] - # ambient_count_rate_mcps_sd0 = (data[7] << 8) + data[8] - # sigma_sd0 = (data[9]<<8) + data[10] - # phase_sd0 = (data[11]<<8) + data[12] + self._ensure_data() + data = self.i2c.readfrom_mem(self.address, 0x0089, 17, addrsize=16) final_crosstalk_corrected_range_mm_sd0 = (data[13] << 8) + data[14] - # peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = (data[15] << 8) + data[16] - # status = None - # if range_status in (17, 2, 1, 3): - # status = "HardwareFail" - # elif range_status == 13: - # status = "MinRangeFail" - # elif range_status == 18: - # status = "SynchronizationInt" - # elif range_status == 5: - # status = "OutOfBoundsFail" - # elif range_status == 4: - # status = "SignalFail" - # elif range_status == 6: - # status = "SignalFail" - # elif range_status == 7: - # status = "WrapTargetFail" - # elif range_status == 12: - # status = "XtalkSignalFail" - # elif range_status == 8: - # status = "RangeValidMinRangeClipped" - # elif range_status == 9: - # if stream_count == 0: - # status = "RangeValidNoWrapCheckFail" - # else: - # status = "OK" + self._clear_interrupt() return final_crosstalk_corrected_range_mm_sd0 diff --git a/tests/scenarios/vl53l1x.yaml b/tests/scenarios/vl53l1x.yaml index 0cebc564..e71195ff 100644 --- a/tests/scenarios/vl53l1x.yaml +++ b/tests/scenarios/vl53l1x.yaml @@ -15,6 +15,14 @@ mock_registers: 0x0000: 0x01 # MM_CONFIG__OUTER_OFFSET_MM (0x0022): used during init 0x0022: [0x00, 0x00] + # GPIO__TIO_HV_STATUS (0x0031): data ready (bit 0 = 1 when polarity=0) + 0x0031: 0x01 + # SYSTEM__INTERRUPT_CLEAR (0x0086) + 0x0086: 0x00 + # SYSTEM__MODE_START (0x0087) + 0x0087: 0x40 + # GPIO__HV_MUX__CTRL (0x0030): interrupt polarity (bit 4 = 0 -> active low) + 0x0030: 0x01 # RESULT__RANGE_STATUS (0x0089): 17-byte result block # Bytes: range_status, report_status, stream_count, # dss_spads(2), peak_rate(2), ambient_rate(2), @@ -39,6 +47,35 @@ tests: expect: 250 mode: [mock] + - name: "Data ready check works" + action: script + script: | + result = dev._is_data_ready() + expect_true: true + mode: [mock] + + - name: "Read clears interrupt" + action: script + script: | + i2c.clear_write_log() + dev.read() + log = i2c.get_write_log() + cleared = any(reg == 0x0086 and data[0] == 0x01 for reg, data in log) + result = cleared + expect_true: true + mode: [mock] + + - name: "Distance after stop and restart" + action: script + script: | + dev.stop_ranging() + d = dev.read() + result = isinstance(d, int) + expect_true: true + mode: [mock] + + # ----- Hardware ----- + - name: "Distance in plausible range" action: call method: read