Skip to content

Commit d92ef26

Browse files
authored
Merge pull request #1 from grantramsay/feat/major-refactor
Feat/major refactor
2 parents d076e99 + 1f0e33e commit d92ef26

7 files changed

Lines changed: 442 additions & 403 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ Notes on using TCA9548A I2C Multiplexer:
3939
### Installation
4040
```bash
4141
# Python2
42-
pip2 install git+https://github.com/johnbryanmoore/VL53L0X_rasp_python.git
42+
pip2 install git+https://github.com/grantramsay/VL53L0X_rasp_python.git
4343
# Python3
44-
pip3 install git+https://github.com/johnbryanmoore/VL53L0X_rasp_python.git
44+
pip3 install git+https://github.com/grantramsay/VL53L0X_rasp_python.git
4545
```
4646

4747
### Compilation

python/VL53L0X.py

Lines changed: 123 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -21,108 +21,167 @@
2121
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2222
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
# SOFTWARE.
24-
from ctypes import *
24+
from ctypes import CDLL, CFUNCTYPE, POINTER, c_int, c_uint, pointer, c_ubyte, c_uint8, c_uint32
2525
import smbus2 as smbus
2626
import site
2727

28-
VL53L0X_GOOD_ACCURACY_MODE = 0 # Good Accuracy mode
29-
VL53L0X_BETTER_ACCURACY_MODE = 1 # Better Accuracy mode
30-
VL53L0X_BEST_ACCURACY_MODE = 2 # Best Accuracy mode
31-
VL53L0X_LONG_RANGE_MODE = 3 # Longe Range mode
32-
VL53L0X_HIGH_SPEED_MODE = 4 # High Speed mode
3328

34-
i2cbus = smbus.SMBus(1)
29+
class Vl53l0xError(RuntimeError):
30+
pass
3531

3632

37-
# i2c bus read callback
38-
def i2c_read(address, reg, data_p, length):
39-
ret_val = 0
40-
result = []
41-
42-
try:
43-
result = i2cbus.read_i2c_block_data(address, reg, length)
44-
except IOError:
45-
ret_val = -1
33+
class Vl53l0xAccuracyMode:
34+
GOOD = 0 # 33 ms timing budget 1.2m range
35+
BETTER = 1 # 66 ms timing budget 1.2m range
36+
BEST = 2 # 200 ms 1.2m range
37+
LONG_RANGE = 3 # 33 ms timing budget 2m range
38+
HIGH_SPEED = 4 # 20 ms timing budget 1.2m range
4639

47-
if ret_val == 0:
48-
for index in range(length):
49-
data_p[index] = result[index]
5040

51-
return ret_val
41+
class Vl53l0xDeviceMode:
42+
SINGLE_RANGING = 0
43+
CONTINUOUS_RANGING = 1
44+
SINGLE_HISTOGRAM = 2
45+
CONTINUOUS_TIMED_RANGING = 3
46+
SINGLE_ALS = 10
47+
GPIO_DRIVE = 20
48+
GPIO_OSC = 21
5249

5350

54-
# i2c bus write callback
55-
def i2c_write(address, reg, data_p, length):
56-
ret_val = 0
57-
data = []
51+
class Vl53l0xGpioAlarmType:
52+
OFF = 0
53+
THRESHOLD_CROSSED_LOW = 1
54+
THRESHOLD_CROSSED_HIGH = 2
55+
THRESHOLD_CROSSED_OUT = 3
56+
NEW_MEASUREMENT_READY = 4
5857

59-
for index in range(length):
60-
data.append(data_p[index])
61-
try:
62-
i2cbus.write_i2c_block_data(address, reg, data)
63-
except IOError:
64-
ret_val = -1
6558

66-
return ret_val
59+
class Vl53l0xInterruptPolarity:
60+
LOW = 0
61+
HIGH = 1
62+
6763

64+
# Read/write function pointer types.
65+
_I2C_READ_FUNC = CFUNCTYPE(c_int, c_ubyte, c_ubyte, POINTER(c_ubyte), c_ubyte)
66+
_I2C_WRITE_FUNC = CFUNCTYPE(c_int, c_ubyte, c_ubyte, POINTER(c_ubyte), c_ubyte)
6867

6968
# Load VL53L0X shared lib
70-
_possible_lib_locations = site.getsitepackages() + ['../bin']
71-
for lib_location in _possible_lib_locations:
69+
_POSSIBLE_LIBRARY_LOCATIONS = ['../bin'] + site.getsitepackages()
70+
for lib_location in _POSSIBLE_LIBRARY_LOCATIONS:
7271
try:
73-
tof_lib = CDLL(lib_location + "/vl53l0x_python.so")
72+
_TOF_LIBRARY = CDLL(lib_location + "/vl53l0x_python.so")
7473
break
7574
except OSError:
7675
pass
7776
else:
7877
raise OSError('Could not find vl53l0x_python.so')
7978

80-
# Create read function pointer
81-
READFUNC = CFUNCTYPE(c_int, c_ubyte, c_ubyte, POINTER(c_ubyte), c_ubyte)
82-
read_func = READFUNC(i2c_read)
83-
84-
# Create write function pointer
85-
WRITEFUNC = CFUNCTYPE(c_int, c_ubyte, c_ubyte, POINTER(c_ubyte), c_ubyte)
86-
write_func = WRITEFUNC(i2c_write)
87-
88-
# pass i2c read and write function pointers to VL53L0X library
89-
tof_lib.VL53L0X_set_i2c(read_func, write_func)
90-
9179

92-
class VL53L0X(object):
80+
class VL53L0X:
9381
"""VL53L0X ToF."""
94-
95-
object_number = 0
96-
97-
def __init__(self, address=0x29, TCA9548A_Num=255, TCA9548A_Addr=0):
82+
def __init__(self, i2c_bus=1, i2c_address=0x29, tca9548a_num=255, tca9548a_addr=0):
9883
"""Initialize the VL53L0X ToF Sensor from ST"""
99-
self.device_address = address
100-
self.TCA9548A_Device = TCA9548A_Num
101-
self.TCA9548A_Address = TCA9548A_Addr
102-
self.my_object_number = VL53L0X.object_number
103-
VL53L0X.object_number += 1
104-
105-
def start_ranging(self, mode=VL53L0X_GOOD_ACCURACY_MODE):
84+
self._i2c_bus = i2c_bus
85+
self.i2c_address = i2c_address
86+
self._tca9548a_num = tca9548a_num
87+
self._tca9548a_addr = tca9548a_addr
88+
self._i2c = smbus.SMBus()
89+
self._dev = None
90+
91+
def open(self):
92+
self._i2c.open(bus=self._i2c_bus)
93+
self._configure_i2c_library_functions()
94+
self._dev = _TOF_LIBRARY.initialise(self.i2c_address, self._tca9548a_num, self._tca9548a_addr)
95+
96+
def close(self):
97+
self._i2c.close()
98+
self._dev = None
99+
100+
def _configure_i2c_library_functions(self):
101+
# I2C bus read callback for low level library.
102+
def _i2c_read(address, reg, data_p, length):
103+
ret_val = 0
104+
result = []
105+
106+
try:
107+
result = self._i2c.read_i2c_block_data(address, reg, length)
108+
except IOError:
109+
ret_val = -1
110+
111+
if ret_val == 0:
112+
for index in range(length):
113+
data_p[index] = result[index]
114+
115+
return ret_val
116+
117+
# I2C bus write callback for low level library.
118+
def _i2c_write(address, reg, data_p, length):
119+
ret_val = 0
120+
data = []
121+
122+
for index in range(length):
123+
data.append(data_p[index])
124+
try:
125+
self._i2c.write_i2c_block_data(address, reg, data)
126+
except IOError:
127+
ret_val = -1
128+
129+
return ret_val
130+
131+
# Pass i2c read/write function pointers to VL53L0X library.
132+
self._i2c_read_func = _I2C_READ_FUNC(_i2c_read)
133+
self._i2c_write_func = _I2C_WRITE_FUNC(_i2c_write)
134+
_TOF_LIBRARY.VL53L0X_set_i2c(self._i2c_read_func, self._i2c_write_func)
135+
136+
def start_ranging(self, mode=Vl53l0xAccuracyMode.GOOD):
106137
"""Start VL53L0X ToF Sensor Ranging"""
107-
tof_lib.startRanging(self.my_object_number, mode, self.device_address,
108-
self.TCA9548A_Device, self.TCA9548A_Address)
109-
138+
_TOF_LIBRARY.startRanging(self._dev, mode)
139+
110140
def stop_ranging(self):
111141
"""Stop VL53L0X ToF Sensor Ranging"""
112-
tof_lib.stopRanging(self.my_object_number)
142+
_TOF_LIBRARY.stopRanging(self._dev)
113143

114144
def get_distance(self):
115145
"""Get distance from VL53L0X ToF Sensor"""
116-
return tof_lib.getDistance(self.my_object_number)
146+
return _TOF_LIBRARY.getDistance(self._dev)
117147

118148
# This function included to show how to access the ST library directly
119149
# from python instead of through the simplified interface
120150
def get_timing(self):
121-
dev = tof_lib.getDev(self.my_object_number)
122151
budget = c_uint(0)
123152
budget_p = pointer(budget)
124-
status = tof_lib.VL53L0X_GetMeasurementTimingBudgetMicroSeconds(dev, budget_p)
153+
status = _TOF_LIBRARY.VL53L0X_GetMeasurementTimingBudgetMicroSeconds(self._dev, budget_p)
125154
if status == 0:
126155
return budget.value + 1000
127156
else:
128157
return 0
158+
159+
def configure_gpio_interrupt(
160+
self, proximity_alarm_type: Vl53l0xGpioAlarmType = Vl53l0xGpioAlarmType.THRESHOLD_CROSSED_LOW,
161+
interrupt_polarity: Vl53l0xInterruptPolarity = Vl53l0xInterruptPolarity.HIGH,
162+
threshold_low_mm: int = 250, threshold_high_mm: int = 500):
163+
"""
164+
Configures a GPIO interrupt from device, be sure to call "clear_interrupt" after interrupt is processed.
165+
"""
166+
pin = c_uint8(0) # 0 is only GPIO pin.
167+
device_mode = c_uint8(Vl53l0xDeviceMode.CONTINUOUS_RANGING)
168+
functionality = c_uint8(proximity_alarm_type)
169+
polarity = c_uint8(interrupt_polarity)
170+
status = _TOF_LIBRARY.VL53L0X_SetGpioConfig(self._dev, pin, device_mode, functionality, polarity)
171+
if status != 0:
172+
raise Vl53l0xError('Error setting VL53L0X GPIO config')
173+
174+
threshold_low = c_uint32(threshold_low_mm << 16)
175+
threshold_high = c_uint32(threshold_high_mm << 16)
176+
status = _TOF_LIBRARY.VL53L0X_SetInterruptThresholds(self._dev, device_mode, threshold_low, threshold_high)
177+
if status != 0:
178+
raise Vl53l0xError('Error setting VL53L0X thresholds')
179+
180+
# Ensure any pending interrupts are cleared.
181+
self.clear_interrupt()
182+
183+
def clear_interrupt(self):
184+
mask = c_uint32(0)
185+
status = _TOF_LIBRARY.VL53L0X_ClearInterruptMask(self._dev, mask)
186+
if status != 0:
187+
raise Vl53l0xError('Error clearing VL53L0X interrupt')

python/VL53L0X_TCA9548A_example.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,37 @@
2626
import VL53L0X
2727

2828
# Create a VL53L0X object for device on TCA9548A bus 1
29-
tof1 = VL53L0X.VL53L0X(TCA9548A_Num=1, TCA9548A_Addr=0x70)
29+
tof1 = VL53L0X.VL53L0X(tca9548a_num=1, tca9548a_addr=0x70)
3030
# Create a VL53L0X object for device on TCA9548A bus 2
31-
tof2 = VL53L0X.VL53L0X(TCA9548A_Num=2, TCA9548A_Addr=0x70)
31+
tof2 = VL53L0X.VL53L0X(tca9548a_num=2, tca9548a_addr=0x70)
32+
tof1.open()
33+
tof2.open()
3234

3335
# Start ranging on TCA9548A bus 1
34-
tof1.start_ranging(VL53L0X.VL53L0X_BETTER_ACCURACY_MODE)
36+
tof1.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)
3537
# Start ranging on TCA9548A bus 2
36-
tof2.start_ranging(VL53L0X.VL53L0X_BETTER_ACCURACY_MODE)
38+
tof2.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)
3739

3840
timing = tof1.get_timing()
39-
if (timing < 20000):
41+
if timing < 20000:
4042
timing = 20000
41-
print ("Timing %d ms" % (timing/1000))
43+
print("Timing %d ms" % (timing/1000))
4244

43-
for count in range(1,101):
45+
for count in range(1, 101):
4446
# Get distance from VL53L0X on TCA9548A bus 1
4547
distance = tof1.get_distance()
46-
if (distance > 0):
47-
print ("1: %d mm, %d cm, %d" % (distance, (distance/10), count))
48+
if distance > 0:
49+
print("1: %d mm, %d cm, %d" % (distance, (distance/10), count))
4850

4951
# Get distance from VL53L0X on TCA9548A bus 2
5052
distance = tof2.get_distance()
51-
if (distance > 0):
52-
print ("2: %d mm, %d cm, %d" % (distance, (distance/10), count))
53+
if distance > 0:
54+
print("2: %d mm, %d cm, %d" % (distance, (distance/10), count))
5355

5456
time.sleep(timing/1000000.00)
5557

5658
tof1.stop_ranging()
5759
tof2.stop_ranging()
5860

61+
tof1.close()
62+
tof2.close()

python/VL53L0X_example.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,22 @@
2727

2828
# Create a VL53L0X object
2929
tof = VL53L0X.VL53L0X()
30-
30+
tof.open()
3131
# Start ranging
32-
tof.start_ranging(VL53L0X.VL53L0X_BETTER_ACCURACY_MODE)
32+
tof.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)
3333

3434
timing = tof.get_timing()
35-
if (timing < 20000):
35+
if timing < 20000:
3636
timing = 20000
37-
print ("Timing %d ms" % (timing/1000))
37+
print("Timing %d ms" % (timing/1000))
3838

39-
for count in range(1,101):
39+
for count in range(1, 101):
4040
distance = tof.get_distance()
41-
if (distance > 0):
42-
print ("%d mm, %d cm, %d" % (distance, (distance/10), count))
41+
if distance > 0:
42+
print("%d mm, %d cm, %d" % (distance, (distance/10), count))
4343

4444
time.sleep(timing/1000000.00)
4545

4646
tof.stop_ranging()
47+
tof.close()
4748

python/VL53L0X_example_livegraph.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828
import VL53L0X
2929

3030
fig = plt.figure()
31-
ax1 = fig.add_subplot(1,1,1)
31+
ax1 = fig.add_subplot(1, 1, 1)
3232

3333
xarr = []
3434
yarr = []
3535
count = 0
3636

37+
3738
def animate(i):
3839
global count
3940
distance = tof.get_distance()
@@ -42,22 +43,24 @@ def animate(i):
4243
yarr.append(distance)
4344
time.sleep(timing/1000000.00)
4445
ax1.clear()
45-
ax1.plot(xarr,yarr)
46+
ax1.plot(xarr, yarr)
47+
4648

4749
# Create a VL53L0X object
4850
tof = VL53L0X.VL53L0X()
49-
51+
tof.open()
5052
# Start ranging
51-
tof.start_ranging(VL53L0X.VL53L0X_BETTER_ACCURACY_MODE)
53+
tof.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)
5254

5355
timing = tof.get_timing()
54-
if (timing < 20000):
56+
if timing < 20000:
5557
timing = 20000
56-
print ("Timing %d ms" % (timing/1000))
58+
print("Timing %d ms" % (timing/1000))
5759

58-
print ("Press ctrl-c to exit")
60+
print("Press ctrl-c to exit")
5961

6062
ani = animation.FuncAnimation(fig, animate, interval=100)
6163
plt.show()
6264

6365
tof.stop_ranging()
66+
tof.close()

0 commit comments

Comments
 (0)