Skip to content

Commit 36250c8

Browse files
committed
vl53l1x: Add driver
1 parent 2d02943 commit 36250c8

6 files changed

Lines changed: 205 additions & 0 deletions

File tree

lib/vl53l1x/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# MicroPython Driver for the vl53l1x ToF sensor
2+
3+
This library is a port of the [Micromicropython driver for the vl53l1x ToF sensor](https://github.com/drakxtwo/vl53l1x_pico).
4+
5+
The examples could be easily tested with [mpremote](https://docs.micropython.org/en/latest/reference/mpremote.html) with the following command :
6+
7+
```sh
8+
mpremote mount . run examples/distance.py
9+
```

lib/vl53l1x/examples/distance.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from machine import I2C
2+
from vl53l1x import VL53L1X
3+
import time
4+
5+
i2c = I2C(1)
6+
distance = VL53L1X(i2c)
7+
while True:
8+
print("range: %s mm " % distance.read())
9+
time.sleep_ms(50)

lib/vl53l1x/manifest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
metadata(
2+
description="Driver for the vl53l1x ToF sensor",
3+
version="0.0.1",
4+
)
5+
6+
package("vl53l1x")

lib/vl53l1x/vl53l1x/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from vl53l1x.device import VL53L1X
2+
3+
__all__ = [
4+
"VL53L1X",
5+
]

lib/vl53l1x/vl53l1x/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from micropython import const

lib/vl53l1x/vl53l1x/device.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import machine
2+
3+
VL51L1X_DEFAULT_CONFIGURATION = bytes(
4+
[
5+
0x00, # 0x2d : set bit 2 and 5 to 1 for fast plus mode (1MHz I2C), else don't touch */
6+
0x00, # 0x2e : bit 0 if I2C pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */
7+
0x00, # 0x2f : bit 0 if GPIO pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */
8+
0x01, # 0x30 : set bit 4 to 0 for active high interrupt and 1 for active low (bits 3:0 must be 0x1), use SetInterruptPolarity() */
9+
0x02, # 0x31 : bit 1 = interrupt depending on the polarity, use CheckForDataReady() */
10+
0x00, # 0x32 : not user-modifiable */
11+
0x02, # 0x33 : not user-modifiable */
12+
0x08, # 0x34 : not user-modifiable */
13+
0x00, # 0x35 : not user-modifiable */
14+
0x08, # 0x36 : not user-modifiable */
15+
0x10, # 0x37 : not user-modifiable */
16+
0x01, # 0x38 : not user-modifiable */
17+
0x01, # 0x39 : not user-modifiable */
18+
0x00, # 0x3a : not user-modifiable */
19+
0x00, # 0x3b : not user-modifiable */
20+
0x00, # 0x3c : not user-modifiable */
21+
0x00, # 0x3d : not user-modifiable */
22+
0xFF, # 0x3e : not user-modifiable */
23+
0x00, # 0x3f : not user-modifiable */
24+
0x0F, # 0x40 : not user-modifiable */
25+
0x00, # 0x41 : not user-modifiable */
26+
0x00, # 0x42 : not user-modifiable */
27+
0x00, # 0x43 : not user-modifiable */
28+
0x00, # 0x44 : not user-modifiable */
29+
0x00, # 0x45 : not user-modifiable */
30+
0x20, # 0x46 : interrupt configuration 0->level low detection, 1-> level high, 2-> Out of window, 3->In window, 0x20-> New sample ready , TBC */
31+
0x0B, # 0x47 : not user-modifiable */
32+
0x00, # 0x48 : not user-modifiable */
33+
0x00, # 0x49 : not user-modifiable */
34+
0x02, # 0x4a : not user-modifiable */
35+
0x0A, # 0x4b : not user-modifiable */
36+
0x21, # 0x4c : not user-modifiable */
37+
0x00, # 0x4d : not user-modifiable */
38+
0x00, # 0x4e : not user-modifiable */
39+
0x05, # 0x4f : not user-modifiable */
40+
0x00, # 0x50 : not user-modifiable */
41+
0x00, # 0x51 : not user-modifiable */
42+
0x00, # 0x52 : not user-modifiable */
43+
0x00, # 0x53 : not user-modifiable */
44+
0xC8, # 0x54 : not user-modifiable */
45+
0x00, # 0x55 : not user-modifiable */
46+
0x00, # 0x56 : not user-modifiable */
47+
0x38, # 0x57 : not user-modifiable */
48+
0xFF, # 0x58 : not user-modifiable */
49+
0x01, # 0x59 : not user-modifiable */
50+
0x00, # 0x5a : not user-modifiable */
51+
0x08, # 0x5b : not user-modifiable */
52+
0x00, # 0x5c : not user-modifiable */
53+
0x00, # 0x5d : not user-modifiable */
54+
0x01, # 0x5e : not user-modifiable */
55+
0xDB, # 0x5f : not user-modifiable */
56+
0x0F, # 0x60 : not user-modifiable */
57+
0x01, # 0x61 : not user-modifiable */
58+
0xF1, # 0x62 : not user-modifiable */
59+
0x0D, # 0x63 : not user-modifiable */
60+
0x01, # 0x64 : Sigma threshold MSB (mm in 14.2 format for MSB+LSB), use SetSigmaThreshold(), default value 90 mm */
61+
0x68, # 0x65 : Sigma threshold LSB */
62+
0x00, # 0x66 : Min count Rate MSB (MCPS in 9.7 format for MSB+LSB), use SetSignalThreshold() */
63+
0x80, # 0x67 : Min count Rate LSB */
64+
0x08, # 0x68 : not user-modifiable */
65+
0xB8, # 0x69 : not user-modifiable */
66+
0x00, # 0x6a : not user-modifiable */
67+
0x00, # 0x6b : not user-modifiable */
68+
0x00, # 0x6c : Intermeasurement period MSB, 32 bits register, use SetIntermeasurementInMs() */
69+
0x00, # 0x6d : Intermeasurement period */
70+
0x0F, # 0x6e : Intermeasurement period */
71+
0x89, # 0x6f : Intermeasurement period LSB */
72+
0x00, # 0x70 : not user-modifiable */
73+
0x00, # 0x71 : not user-modifiable */
74+
0x00, # 0x72 : distance threshold high MSB (in mm, MSB+LSB), use SetD:tanceThreshold() */
75+
0x00, # 0x73 : distance threshold high LSB */
76+
0x00, # 0x74 : distance threshold low MSB ( in mm, MSB+LSB), use SetD:tanceThreshold() */
77+
0x00, # 0x75 : distance threshold low LSB */
78+
0x00, # 0x76 : not user-modifiable */
79+
0x01, # 0x77 : not user-modifiable */
80+
0x0F, # 0x78 : not user-modifiable */
81+
0x0D, # 0x79 : not user-modifiable */
82+
0x0E, # 0x7a : not user-modifiable */
83+
0x0E, # 0x7b : not user-modifiable */
84+
0x00, # 0x7c : not user-modifiable */
85+
0x00, # 0x7d : not user-modifiable */
86+
0x02, # 0x7e : not user-modifiable */
87+
0xC7, # 0x7f : ROI center, use SetROI() */
88+
0xFF, # 0x80 : XY ROI (X=Width, Y=Height), use SetROI() */
89+
0x9B, # 0x81 : not user-modifiable */
90+
0x00, # 0x82 : not user-modifiable */
91+
0x00, # 0x83 : not user-modifiable */
92+
0x00, # 0x84 : not user-modifiable */
93+
0x01, # 0x85 : not user-modifiable */
94+
0x01, # 0x86 : clear interrupt, use ClearInterrupt() */
95+
0x40, # 0x87 : start ranging, use StartRanging() or StopRanging(), If you want an automatic start after VL53L1X_init() call, put 0x40 in location 0x87 */
96+
]
97+
)
98+
99+
100+
class VL53L1X:
101+
def __init__(self, i2c, address=0x29):
102+
self.i2c = i2c
103+
self.address = address
104+
self.reset()
105+
machine.lightsleep(1)
106+
if self.read_model_id() != 0xEACC:
107+
raise RuntimeError("Failed to find expected ID register values. Check wiring!")
108+
# write default configuration
109+
self.i2c.writeto_mem(self.address, 0x2D, VL51L1X_DEFAULT_CONFIGURATION, addrsize=16)
110+
# machine.lightsleep(100)
111+
# the API triggers this change in VL53L1_init_and_start_range() once a
112+
# measurement is started; assumes MM1 and MM2 are disabled
113+
self.writeReg16Bit(0x001E, self.readReg16Bit(0x0022) * 4)
114+
machine.lightsleep(200)
115+
116+
def writeReg(self, reg, value):
117+
return self.i2c.writeto_mem(self.address, reg, bytes([value]), addrsize=16)
118+
119+
def writeReg16Bit(self, reg, value):
120+
return self.i2c.writeto_mem(
121+
self.address, reg, bytes([(value >> 8) & 0xFF, value & 0xFF]), addrsize=16
122+
)
123+
124+
def readReg(self, reg):
125+
return self.i2c.readfrom_mem(self.address, reg, 1, addrsize=16)[0]
126+
127+
def readReg16Bit(self, reg):
128+
data = self.i2c.readfrom_mem(self.address, reg, 2, addrsize=16)
129+
return (data[0] << 8) + data[1]
130+
131+
def read_model_id(self):
132+
return self.readReg16Bit(0x010F)
133+
134+
def reset(self):
135+
self.writeReg(0x0000, 0x00)
136+
machine.lightsleep(100)
137+
self.writeReg(0x0000, 0x01)
138+
139+
def read(self):
140+
data = self.i2c.readfrom_mem(self.address, 0x0089, 17, addrsize=16) # RESULT__RANGE_STATUS
141+
range_status = data[0]
142+
# report_status = data[1]
143+
stream_count = data[2]
144+
dss_actual_effective_spads_sd0 = (data[3] << 8) + data[4]
145+
# peak_signal_count_rate_mcps_sd0 = (data[5]<<8) + data[6]
146+
ambient_count_rate_mcps_sd0 = (data[7] << 8) + data[8]
147+
# sigma_sd0 = (data[9]<<8) + data[10]
148+
# phase_sd0 = (data[11]<<8) + data[12]
149+
final_crosstalk_corrected_range_mm_sd0 = (data[13] << 8) + data[14]
150+
peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = (data[15] << 8) + data[16]
151+
# status = None
152+
# if range_status in (17, 2, 1, 3):
153+
# status = "HardwareFail"
154+
# elif range_status == 13:
155+
# status = "MinRangeFail"
156+
# elif range_status == 18:
157+
# status = "SynchronizationInt"
158+
# elif range_status == 5:
159+
# status = "OutOfBoundsFail"
160+
# elif range_status == 4:
161+
# status = "SignalFail"
162+
# elif range_status == 6:
163+
# status = "SignalFail"
164+
# elif range_status == 7:
165+
# status = "WrapTargetFail"
166+
# elif range_status == 12:
167+
# status = "XtalkSignalFail"
168+
# elif range_status == 8:
169+
# status = "RangeValidMinRangeClipped"
170+
# elif range_status == 9:
171+
# if stream_count == 0:
172+
# status = "RangeValidNoWrapCheckFail"
173+
# else:
174+
# status = "OK"
175+
return final_crosstalk_corrected_range_mm_sd0

0 commit comments

Comments
 (0)