Skip to content

Commit 79eaad2

Browse files
committed
Added support for LidarLite v3HP and added many more register reads to the main code (ones in common between v3 and v3HP)
1 parent 9d728cf commit 79eaad2

File tree

1 file changed

+105
-14
lines changed

1 file changed

+105
-14
lines changed

adafruit_lidarlite.py

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
A CircuitPython & Python library for Garmin LIDAR Lite sensors over I2C
1010
11-
* Author(s): ladyada
11+
* Author(s): ladyada, johnrbnsn
1212
1313
Implementation Notes
1414
--------------------
@@ -37,9 +37,29 @@
3737

3838
_ADDR_DEFAULT = const(0x62)
3939
_REG_ACQ_COMMAND = const(0x00)
40-
_CMD_RESET = const(0)
41-
_CMD_DISTANCENOBIAS = const(3)
42-
_CMD_DISTANCEWITHBIAS = const(4)
40+
_REG_DIST_MEAS_V3 = const(0x8F)
41+
_REG_DIST_MEAS_V3HP = const(0x0F)
42+
_REG_SIG_COUNT_VAL = const(0x02)
43+
_REG_ACQ_CONFIG_REG = const(0x04)
44+
_REG_THRESHOLD_BYPASS = const(0x1C)
45+
_REG_STATUS = const(0x01)
46+
_REG_UNIT_ID_HIGH = const(0x16)
47+
_REG_UNIT_ID_LOW = const(0x17)
48+
_REG_SIGNAL_STRENGTH = const(0x0E)
49+
_REG_HEALTH_STATUS_V3HP = const(0x48)
50+
_REG_POWER_CONTROL = const(0x65)
51+
_REG_I2C_CONFIG = const(0x1E)
52+
_REG_TEST_COMMAND = const(0x40)
53+
_REG_CORR_DATA = const(0x52)
54+
55+
_CMD_RESET = const(0x00)
56+
_CMD_DISTANCENOBIAS = const(0x03)
57+
_CMD_DISTANCEWITHBIAS = const(0x04)
58+
_CMD_DISTANCE_V3HP = const(0x03)
59+
_NUM_DIST_BYTES = 2 # How many bytes is the returned distance measurement?
60+
61+
TYPE_V3 = 'V3'
62+
TYPE_V3HP = 'V3HP'
4363

4464
CONFIG_DEFAULT = 0
4565
CONFIG_SHORTFAST = 1
@@ -48,6 +68,8 @@
4868
CONFIG_HIGHSENSITIVE = 4
4969
CONFIG_LOWSENSITIVE = 5
5070

71+
"""Status Registers"""
72+
# v3
5173
STATUS_BUSY = 0x01
5274
STATUS_REF_OVERFLOW = 0x02
5375
STATUS_SIGNAL_OVERFLOW = 0x04
@@ -56,6 +78,10 @@
5678
STATUS_HEALTHY = 0x20
5779
STATUS_SYS_ERROR = 0x40
5880

81+
# v3 HP
82+
STATUS_BUSY_V3HP = 0x01
83+
STATUS_SIGNAL_OVERFLOW_V3HP = 0x02
84+
5985
# The various configuration register values, from arduino library
6086
_LIDAR_CONFIGS = (
6187
(0x80, 0x08, 0x00), # default
@@ -92,7 +118,8 @@ def __init__(
92118
*,
93119
reset_pin=None,
94120
configuration=CONFIG_DEFAULT,
95-
address=_ADDR_DEFAULT
121+
address=_ADDR_DEFAULT,
122+
sensor_type=TYPE_V3,
96123
):
97124
self.i2c_device = I2CDevice(i2c_bus, address)
98125
self._buf = bytearray(2)
@@ -101,6 +128,7 @@ def __init__(
101128
time.sleep(0.5)
102129
self.configure(configuration)
103130
self._status = self.status
131+
self._sensor_type = sensor_type
104132

105133
def reset(self):
106134
"""Hardware reset (if pin passed into init) or software reset. Will take
@@ -116,13 +144,15 @@ def reset(self):
116144
try:
117145
self._write_reg(_REG_ACQ_COMMAND, _CMD_RESET)
118146
except OSError:
147+
print('OSError')
119148
pass # it doesnt respond well once reset
120149
time.sleep(1)
121150
# take 100 readings to 'flush' out sensor!
122151
for _ in range(100):
123152
try:
124-
self.read_distance(True)
153+
self.read_distance_v3(True)
125154
except RuntimeError:
155+
print('RuntimeError')
126156
pass
127157

128158
def configure(self, config):
@@ -131,36 +161,97 @@ def configure(self, config):
131161
CONFIG_DEFAULTFAST, CONFIG_MAXRANGE, CONFIG_HIGHSENSITIVE, and
132162
CONFIG_LOWSENSITIVE."""
133163
settings = _LIDAR_CONFIGS[config]
134-
self._write_reg(0x02, settings[0])
135-
self._write_reg(0x04, settings[1])
136-
self._write_reg(0x1C, settings[2])
164+
self._write_reg(_REG_SIG_COUNT_VAL, settings[0])
165+
self._write_reg(_REG_ACQ_CONFIG_REG, settings[1])
166+
self._write_reg(_REG_THRESHOLD_BYPASS, settings[2])
137167

138-
def read_distance(self, bias=False):
168+
def read_distance_v3(self, bias=False):
139169
"""Perform a distance reading with or without 'bias'. It's recommended
140170
to take a bias measurement every 100 non-bias readings (they're slower)"""
141171
if bias:
142172
self._write_reg(_REG_ACQ_COMMAND, _CMD_DISTANCEWITHBIAS)
143173
else:
144174
self._write_reg(_REG_ACQ_COMMAND, _CMD_DISTANCENOBIAS)
145-
dist = self._read_reg(0x8F, 2)
175+
dist = self._read_reg(_REG_DIST_MEAS_V3, _NUM_DIST_BYTES)
146176
if self._status & (STATUS_NO_PEAK | STATUS_SECOND_RETURN):
147-
raise RuntimeError("Measurement failure")
177+
if self._status & STATUS_NO_PEAK:
178+
raise RuntimeError("Measurement failure STATUS_NO_PEAK")
179+
elif self._status & STATUS_SECOND_RETURN:
180+
raise RuntimeError("Measurement failure STATUS_NO_PEAK")
181+
else:
182+
raise RuntimeError("Some other runtime error")
183+
148184
if (self._status & STATUS_SYS_ERROR) or (not self._status & STATUS_HEALTHY):
149185
raise RuntimeError("System failure")
150186
return dist[0] << 8 | dist[1]
151187

188+
def read_distance_v3hp(self):
189+
"""Perform a distance measurement for the v3 HP sensor
190+
"""
191+
# Any non-zero value written to _REG_ACQ_COMMAND will start a reading on v3HP, no bias vs. non-bias
192+
self._write_reg(_REG_ACQ_COMMAND, _CMD_DISTANCEWITHBIAS)
193+
dist = self._read_reg(_REG_DIST_MEAS_V3HP, _NUM_DIST_BYTES)
194+
return dist[0] << 8 | dist[1]
195+
196+
@property
197+
def correlation_data(self):
198+
"""Reads correlation data"""
199+
# TODO: How to translate correlation data property?
200+
corr_data = self._read_reg(_REG_CORR_DATA, 2)
201+
return corr_data[0] << 8 | corr_data[1]
202+
203+
@property
204+
def test_command(self):
205+
"""Reads the test command"""
206+
return self._read_reg(_REG_TEST_COMMAND, 1)[0]
207+
208+
@property
209+
def i2c_config(self):
210+
"""Reads the I2C config"""
211+
return self._read_reg(_REG_I2C_CONFIG, 1)[0]
212+
213+
@property
214+
def power_control(self):
215+
"""Reads the power control register"""
216+
return self._read_reg(_REG_POWER_CONTROL, 1)[0]
217+
218+
@property
219+
def health_status(self):
220+
"""Reads health status for v3HP (not available on v3, will return -1)"""
221+
if self._sensor_type == TYPE_V3HP:
222+
return self._read_reg(_REG_HEALTH_STATUS_V3HP, 1)[0]
223+
else:
224+
return -1
225+
226+
@property
227+
def signal_strength(self):
228+
"""Reads the signal strength of the last measurement"""
229+
return self._read_reg(_REG_SIGNAL_STRENGTH, 1)[0]
230+
231+
@property
232+
def unit_id(self):
233+
"""Reads the serial number of the unit"""
234+
high_byte = self._read_reg(_REG_UNIT_ID_HIGH, 1)
235+
low_byte = self._read_reg(_REG_UNIT_ID_LOW, 1)
236+
237+
return high_byte[0] << 8 | low_byte[0]
238+
152239
@property
153240
def distance(self):
154241
"""The measured distance in cm. Will take a bias reading every 100 calls"""
155242
self._bias_count -= 1
243+
156244
if self._bias_count < 0:
157245
self._bias_count = 100 # every 100 reads, check bias
158-
return self.read_distance(self._bias_count <= 0)
246+
if self._sensor_type == TYPE_V3:
247+
return self.read_distance_v3(self._bias_count <= 0)
248+
elif self._sensor_type == TYPE_V3HP:
249+
return self.read_distance_v3hp()
159250

160251
@property
161252
def status(self):
162253
"""The status byte, check datasheet for bitmask"""
163-
buf = bytearray([0x1])
254+
buf = bytearray([_REG_STATUS])
164255
with self.i2c_device as i2c:
165256
i2c.write_then_readinto(buf, buf)
166257
return buf[0]

0 commit comments

Comments
 (0)