@@ -137,6 +137,9 @@ class VL53L0X:
137
137
# thread safe!
138
138
_BUFFER = bytearray (3 )
139
139
140
+ # Is VL53L0X is currently continuous mode? (Needed by `range` property)
141
+ _continuous_mode = False
142
+
140
143
def __init__ (self , i2c , address = 41 , io_timeout_s = 0 ):
141
144
# pylint: disable=too-many-statements
142
145
self ._i2c = i2c
@@ -515,11 +518,21 @@ def distance(self):
515
518
516
519
@property
517
520
def range (self ):
518
- """Perform a single reading of the range for an object in front of
519
- the sensor and return the distance in millimeters.
521
+ """Perform a single (or continuous if `start_continuous` called)
522
+ reading of the range for an object in front of the sensor and
523
+ return the distance in millimeters.
524
+ """
525
+ # Adapted from readRangeSingleMillimeters in pololu code at:
526
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
527
+ if not self ._continuous_mode :
528
+ self .do_range_measurement ()
529
+ return self .read_range ()
530
+
531
+ def do_range_measurement (self ):
532
+ """Perform a single reading of the range for an object in front of the
533
+ sensor, but without return the distance.
520
534
"""
521
- # Adapted from readRangeSingleMillimeters &
522
- # readRangeContinuousMillimeters in pololu code at:
535
+ # Adapted from readRangeSingleMillimeters in pololu code at:
523
536
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
524
537
for pair in (
525
538
(0x80 , 0x01 ),
@@ -539,6 +552,16 @@ def range(self):
539
552
and (time .monotonic () - start ) >= self .io_timeout_s
540
553
):
541
554
raise RuntimeError ("Timeout waiting for VL53L0X!" )
555
+
556
+ def read_range (self ):
557
+ """Return a range reading in millimeters.
558
+
559
+ Note: Avoid calling this directly. If you do single mode, you need
560
+ to call `do_range_measurement` first. Or your program will stuck or
561
+ timeout occurred.
562
+ """
563
+ # Adapted from readRangeContinuousMillimeters in pololu code at:
564
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
542
565
start = time .monotonic ()
543
566
while (self ._read_u8 (_RESULT_INTERRUPT_STATUS ) & 0x07 ) == 0 :
544
567
if (
@@ -552,6 +575,68 @@ def range(self):
552
575
self ._write_u8 (_SYSTEM_INTERRUPT_CLEAR , 0x01 )
553
576
return range_mm
554
577
578
+ @property
579
+ def is_continuous_mode (self ):
580
+ """Is the sensor currently in continuous mode?"""
581
+ return self ._continuous_mode
582
+
583
+ def continuous_mode (self ):
584
+ """Activate the continuous mode manager"""
585
+ return self
586
+
587
+ def __enter__ (self ):
588
+ """For continuous mode manager, called when used on `with` keyword"""
589
+ self .start_continuous ()
590
+ return self
591
+
592
+ def __exit__ (self , exc_type , exc_value , traceback ):
593
+ """For continuous mode manager, called at the end of `with` scope"""
594
+ self .stop_continuous ()
595
+
596
+ def start_continuous (self ):
597
+ """Perform a continuous reading of the range for an object in front of
598
+ the sensor.
599
+ """
600
+ # Adapted from startContinuous in pololu code at:
601
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
602
+ for pair in (
603
+ (0x80 , 0x01 ),
604
+ (0xFF , 0x01 ),
605
+ (0x00 , 0x00 ),
606
+ (0x91 , self ._stop_variable ),
607
+ (0x00 , 0x01 ),
608
+ (0xFF , 0x00 ),
609
+ (0x80 , 0x00 ),
610
+ (_SYSRANGE_START , 0x02 ),
611
+ ):
612
+ self ._write_u8 (pair [0 ], pair [1 ])
613
+ start = time .monotonic ()
614
+ while (self ._read_u8 (_SYSRANGE_START ) & 0x01 ) > 0 :
615
+ if (
616
+ self .io_timeout_s > 0
617
+ and (time .monotonic () - start ) >= self .io_timeout_s
618
+ ):
619
+ raise RuntimeError ("Timeout waiting for VL53L0X!" )
620
+ self ._continuous_mode = True
621
+
622
+ def stop_continuous (self ):
623
+ """Stop continuous readings."""
624
+ # Adapted from stopContinuous in pololu code at:
625
+ # https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
626
+ for pair in (
627
+ (_SYSRANGE_START , 0x01 ),
628
+ (0xFF , 0x01 ),
629
+ (0x00 , 0x00 ),
630
+ (0x91 , 0x00 ),
631
+ (0x00 , 0x01 ),
632
+ (0xFF , 0x00 ),
633
+ ):
634
+ self ._write_u8 (pair [0 ], pair [1 ])
635
+ self ._continuous_mode = False
636
+
637
+ # restore the sensor to single ranging mode
638
+ self .do_range_measurement ()
639
+
555
640
def set_address (self , new_address ):
556
641
"""Set a new I2C address to the instantaited object. This is only called when using
557
642
multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the
0 commit comments