Skip to content

Commit 66b46a7

Browse files
committed
Stop mixing single and double tap detection.
This changes the API to have single boolean `tapped` property (formerly read_click). This change aligns the behavior with the expectation that a tap thats part of a double tap does not register as a single tap. It will now only detect single or double taps as set by `set_tap`. Names with click were renamed to tap so they align with what is actually happening rather than the data sheet names. A comment in the code points this out. The tap example now also deduplicates taps because tap detection holds the status for a while.
1 parent 278bef3 commit 66b46a7

File tree

2 files changed

+50
-55
lines changed

2 files changed

+50
-55
lines changed

adafruit_lis3dh.py

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,10 @@ def __init__(self):
8181

8282
@property
8383
def data_rate(self):
84-
"""Get/set the data rate of the accelerometer. Can be DATA_RATE_400_HZ,
85-
DATA_RATE_200_HZ, DATA_RATE_100_HZ, DATA_RATE_50_HZ, DATA_RATE_25_HZ,
86-
DATA_RATE_10_HZ, DATA_RATE_1_HZ, DATA_RATE_POWERDOWN, DATA_RATE_LOWPOWER_1K6HZ,
87-
or DATA_RATE_LOWPOWER_5KHZ.
88-
"""
84+
"""The data rate of the accelerometer. Can be DATA_RATE_400_HZ, DATA_RATE_200_HZ,
85+
DATA_RATE_100_HZ, DATA_RATE_50_HZ, DATA_RATE_25_HZ, DATA_RATE_10_HZ,
86+
DATA_RATE_1_HZ, DATA_RATE_POWERDOWN, DATA_RATE_LOWPOWER_1K6HZ, or
87+
DATA_RATE_LOWPOWER_5KHZ."""
8988
ctl1 = self._read_register_byte(REG_CTRL1)
9089
return (ctl1 >> 4) & 0x0F
9190

@@ -98,9 +97,8 @@ def data_rate(self, rate):
9897

9998
@property
10099
def range(self):
101-
"""Get/set the range of the accelerometer. Can be RANGE_2_G, RANGE_4_G,
102-
RANGE_8_G, or RANGE_16_G.
103-
"""
100+
"""The range of the accelerometer. Can be RANGE_2_G, RANGE_4_G, RANGE_8_G, or
101+
RANGE_16_G."""
104102
ctl4 = self._read_register_byte(REG_CTRL4)
105103
return (ctl4 >> 4) & 0x03
106104

@@ -183,35 +181,35 @@ def read_adc_mV(self, adc): # pylint: disable=invalid-name
183181
# y1 = 900
184182
return 1800+(raw+32512)*(-900/65024)
185183

186-
def read_click_raw(self):
187-
"""Read the raw click register byte value."""
188-
return self._read_register_byte(REG_CLICKSRC)
189-
190-
def read_click(self):
191-
"""Read a 2-tuple of bools where the first value is True if a single
192-
click was detected and the second value is True if a double click was
193-
detected.
194-
"""
195-
raw = self.read_click_raw()
196-
return (raw & 0x10 > 0, raw & 0x20 > 0)
197-
198-
def set_click(self, click, threshold, *,
184+
@property
185+
def tapped(self):
186+
"""True if a tap was detected recently. Whether its a single tap or double tap is
187+
determined by the tap param on `set_tap`. This may be True over multiple reads
188+
even if only a single tap or single double tap occurred."""
189+
raw = self._read_register_byte(REG_CLICKSRC)
190+
return raw & 0x40 > 0
191+
192+
def set_tap(self, tap, threshold, *,
199193
time_limit=10, time_latency=20, time_window=255, click_cfg=None):
200-
"""Set the click detection parameters. Must specify at least:
201-
click - Set to 0 to disable click detection, 1 to detect only single
202-
clicks, and 2 to detect single & double clicks.
203-
threshold - A threshold for the click detection. The higher the value
204-
the less sensitive the detection. This changes based on
205-
the accelerometer range. Good values are 5-10 for 16G,
206-
10-20 for 8G, 20-40 for 4G, and 40-80 for 2G.
207-
Optionally specify (see datasheet for meaning of these):
208-
time_limit - Time limit register value (default 10).
209-
time_latency - Time latency register value (default 20).
210-
time_window - Time window register value (default 255).
211-
"""
212-
if (click < 0 or click > 2) and click_cfg is None:
213-
raise ValueError('Click must be 0 (disabled), 1 (single click), or 2 (double click)!')
214-
if click == 0 and click_cfg is None:
194+
"""Set the tap detection parameters.
195+
196+
.. note:: Tap related registers are called CLICK_ in the datasheet.
197+
198+
:param int tap: 0 to disable tap detection, 1 to detect only single
199+
taps, and 2 to detect only double taps.
200+
:param int threshold: A threshold for the tap detection. The higher the value
201+
the less sensitive the detection. This changes based on the accelerometer
202+
range. Good values are 5-10 for 16G, 10-20 for 8G, 20-40 for 4G, and 40-80 for
203+
2G.
204+
:param int time_limit: TIME_LIMIT register value (default 10).
205+
:param int time_latency: TIME_LATENCY register value (default 20).
206+
:param int time_window: TIME_WINDOW register value (default 255).
207+
:param int click_cfg: CLICK_CFG register value."""
208+
if (tap < 0 or tap > 2) and click_cfg is None:
209+
raise ValueError('Tap must be 0 (disabled), 1 (single tap), or 2 (double tap)!')
210+
if threshold > 127 or threshold < 0:
211+
raise ValueError('Threshold out of range (0-127)')
212+
if tap == 0 and click_cfg is None:
215213
# Disable click interrupt.
216214
r = self._read_register_byte(REG_CTRL3)
217215
r &= ~(0x80) # Turn off I1_CLICK.
@@ -224,9 +222,9 @@ def set_click(self, click, threshold, *,
224222
if click_cfg is not None:
225223
# Custom click configuration register value specified, use it.
226224
self._write_register_byte(REG_CLICKCFG, click_cfg)
227-
elif click == 1:
225+
elif tap == 1:
228226
self._write_register_byte(REG_CLICKCFG, 0x15) # Turn on all axes & singletap.
229-
elif click == 2:
227+
elif tap == 2:
230228
self._write_register_byte(REG_CLICKCFG, 0x2A) # Turn on all axes & doubletap.
231229
self._write_register_byte(REG_CLICKTHS, threshold)
232230
self._write_register_byte(REG_TIMELIMIT, time_limit)

examples/click.py renamed to examples/tap.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Click detection example.
1+
# Tap detection example.
22
# Will loop forever printing when a single or double click is detected.
33
# Open the serial port after running to see the output printed.
44
# Author: Tony DiCola
@@ -29,26 +29,23 @@
2929
# Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G).
3030
lis3dh.range = adafruit_lis3dh.RANGE_2_G
3131

32-
# Set click detection to double and single clicks. The first parameter is a value:
33-
# - 0 = Disable click detection.
34-
# - 1 = Detect single clicks.
35-
# - 2 = Detect single and double clicks.
32+
# Set tap detection to double taps. The first parameter is a value:
33+
# - 0 = Disable tap detection.
34+
# - 1 = Detect single taps.
35+
# - 2 = Detect double taps.
3636
# The second parameter is the threshold and a higher value means less sensitive
37-
# click detection. Note the threshold should be set based on the range above:
37+
# tap detection. Note the threshold should be set based on the range above:
3838
# - 2G = 40-80 threshold
3939
# - 4G = 20-40 threshold
4040
# - 8G = 10-20 threshold
4141
# - 16G = 5-10 threshold
42-
lis3dh.set_click(2, 80)
42+
lis3dh.set_tap(2, 80)
4343

44-
# Loop forever printing if a single or double click is detected.
44+
# Loop forever printing if a double tap is detected. A single double tap may cause multiple
45+
# `tapped` reads to return true so we make sure the last once was False.
46+
last_tap = False
4547
while True:
46-
# Read the click detection. Two booleans are returned, single click and
47-
# double click detected. Each can be independently true/false.
48-
single, double = lis3dh.read_click()
49-
if single:
50-
print('Single click!')
51-
if double:
52-
print('Double click!')
53-
# Small delay to keep things responsive but give time for interrupt processing.
54-
time.sleep(0.05)
48+
tap = lis3dh.tapped
49+
if tap and not last_tap:
50+
print('Double tap!')
51+
last_tap = tap

0 commit comments

Comments
 (0)