45
45
https://github.com/adafruit/circuitpython/releases
46
46
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
47
47
"""
48
+ import atexit
48
49
import math
49
50
import time
50
51
@@ -156,6 +157,9 @@ class VL53L0X:
156
157
# thread safe!
157
158
_BUFFER = bytearray (3 )
158
159
160
+ # Is VL53L0X is currently continuous mode? (Needed by `range` property)
161
+ _continuous_mode = False
162
+
159
163
def __init__ (self , i2c , address = 41 , io_timeout_s = 0 ):
160
164
# pylint: disable=too-many-statements
161
165
self ._device = i2c_device .I2CDevice (i2c , address )
@@ -317,6 +321,7 @@ def __init__(self, i2c, address=41, io_timeout_s=0):
317
321
self ._perform_single_ref_calibration (0x00 )
318
322
# "restore the previous Sequence Config"
319
323
self ._write_u8 (_SYSTEM_SEQUENCE_CONFIG , 0xE8 )
324
+ atexit .register (self ._cleanup )
320
325
321
326
def _read_u8 (self , address ):
322
327
# Read an 8-bit unsigned value from the specified 8-bit address.
@@ -453,6 +458,11 @@ def _get_sequence_step_timeouts(self, pre_range):
453
458
pre_range_mclks ,
454
459
)
455
460
461
+ def _cleanup (self ):
462
+ #when exiting, don't forget to also turn off continuous mode
463
+ if (self ._continuous_mode ):
464
+ self .stopContinuous ()
465
+
456
466
@property
457
467
def signal_rate_limit (self ):
458
468
"""The signal rate limit in mega counts per second."""
@@ -527,11 +537,21 @@ def measurement_timing_budget(self, budget_us):
527
537
528
538
@property
529
539
def range (self ):
530
- """Perform a single reading of the range for an object in front of
531
- the sensor and return the distance in millimeters.
540
+ """Perform a single (or continuous if `startContinuous` called)
541
+ reading of the range for an object in front of the sensor and
542
+ return the distance in millimeters.
543
+ """
544
+ # Adapted from readRangeSingleMillimeters in pololu code at:
545
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
546
+ if (not self ._continuous_mode ):
547
+ self .doRangeMeasurement ()
548
+ return self .readRange ()
549
+
550
+ def doRangeMeasurement (self ):
551
+ """Perform a single reading of the range for an object in front of the
552
+ sensor, but without return the distance.
532
553
"""
533
- # Adapted from readRangeSingleMillimeters &
534
- # readRangeContinuousMillimeters in pololu code at:
554
+ # Adapted from readRangeSingleMillimeters in pololu code at:
535
555
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
536
556
for pair in (
537
557
(0x80 , 0x01 ),
@@ -551,6 +571,16 @@ def range(self):
551
571
and (time .monotonic () - start ) >= self .io_timeout_s
552
572
):
553
573
raise RuntimeError ("Timeout waiting for VL53L0X!" )
574
+
575
+ def readRange (self ):
576
+ """Return a range reading in millimeters.
577
+
578
+ Note: Avoid calling this directly. If you do single mode, you need
579
+ to call doRangeMeasurement first. Or your program will stuck or
580
+ timeout occurred.
581
+ """
582
+ # Adapted from readRangeContinuousMillimeters in pololu code at:
583
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
554
584
start = time .monotonic ()
555
585
while (self ._read_u8 (_RESULT_INTERRUPT_STATUS ) & 0x07 ) == 0 :
556
586
if (
@@ -564,6 +594,59 @@ def range(self):
564
594
self ._write_u8 (_SYSTEM_INTERRUPT_CLEAR , 0x01 )
565
595
return range_mm
566
596
597
+ @property
598
+ def continuous_mode (self ):
599
+ return self ._continuous_mode
600
+
601
+ @continuous_mode .setter
602
+ def continuous_mode (self , enabled ):
603
+ if (enabled ):
604
+ self .startContinuous ()
605
+ else :
606
+ self .stopContinuous ()
607
+
608
+ def startContinuous (self ):
609
+ """Perform a continuous reading of the range for an object in front of
610
+ the sensor.
611
+ """
612
+ # Adapted from startContinuous in pololu code at:
613
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
614
+ for pair in (
615
+ (0x80 , 0x01 ),
616
+ (0xFF , 0x01 ),
617
+ (0x00 , 0x00 ),
618
+ (0x91 , self ._stop_variable ),
619
+ (0x00 , 0x01 ),
620
+ (0xFF , 0x00 ),
621
+ (0x80 , 0x00 ),
622
+ (_SYSRANGE_START , 0x02 ),
623
+ ):
624
+ self ._write_u8 (pair [0 ], pair [1 ])
625
+ start = time .monotonic ()
626
+ while (self ._read_u8 (_SYSRANGE_START ) & 0x01 ) > 0 :
627
+ if (
628
+ self .io_timeout_s > 0
629
+ and (time .monotonic () - start ) >= self .io_timeout_s
630
+ ):
631
+ raise RuntimeError ("Timeout waiting for VL53L0X!" )
632
+ self ._continuous_mode = True
633
+
634
+ def stopContinuous (self ):
635
+ """Stop continuous readings.
636
+ """
637
+ # Adapted from stopContinuous in pololu code at:
638
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
639
+ for pair in (
640
+ (_SYSRANGE_START , 0x01 ),
641
+ (0xFF , 0x01 ),
642
+ (0x00 , 0x00 ),
643
+ (0x91 , 0x00 ),
644
+ (0x00 , 0x01 ),
645
+ (0xFF , 0x00 )
646
+ ):
647
+ self ._write_u8 (pair [0 ], pair [1 ])
648
+ self ._continuous_mode = False
649
+
567
650
def set_address (self , new_address ):
568
651
"""Set a new I2C address to the instantaited object. This is only called when using
569
652
multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the
0 commit comments