Skip to content

Commit 90f0481

Browse files
committed
Replace firmware implementation of HCSR04 (closes fossasia#208)
1 parent bb53a33 commit 90f0481

File tree

3 files changed

+119
-50
lines changed

3 files changed

+119
-50
lines changed

pslab/external/HCSR04.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

pslab/external/hcsr04.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""Ultrasonic distance sensors."""
2+
import time
3+
4+
from pslab.instrument.logic_analyzer import LogicAnalyzer
5+
from pslab.instrument.waveform_generator import PWMGenerator
6+
from pslab.serial_handler import SerialHandler
7+
8+
9+
class HCSR04(LogicAnalyzer, PWMGenerator):
10+
"""Read data from ultrasonic distance sensor HC-SR04/HC-SR05.
11+
12+
These sensors can measure distances between 2 cm to 4 m (SR04) / 4.5 m
13+
(SR05).
14+
15+
Sensors must have separate trigger and echo pins. First a 10 µs pulse is
16+
output on the trigger pin. The trigger pin must be connected to the TRIG
17+
pin on the sensor prior to use.
18+
19+
Upon receiving this pulse, the sensor emits a sequence of sound pulses, and
20+
the logic level of its echo pin is also set high. The logic level goes LOW
21+
when the sound packet returns to the sensor, or when a timeout occurs.
22+
Timeout occurs if no echo is received within the time slot determinded by
23+
the sensor's maximum range.
24+
25+
The ultrasound sensor outputs a series of eight sound pulses at 40 kHz,
26+
which corresponds to a time period of 25 µs per pulse. These pulses reflect
27+
off of the nearest object in front of the sensor, and return to it. The
28+
time between sending and receiving of the pulse packet is used to estimate
29+
the distance. If the reflecting object is either too far away or absorbs
30+
sound, less than eight pulses may be received, and this can cause a
31+
measurement error of 25 µs which corresponds to 8 mm.
32+
33+
Parameters
34+
----------
35+
device : :class:`SerialHandler`
36+
Serial connection to PSLab device.
37+
trig : str, optional
38+
Name of the trigger pin. Defaults to SQ1.
39+
echo : str, optional
40+
Name of the echo pin. Defaults to LA1.
41+
42+
Example
43+
-------
44+
In this example the sensor's Vcc pin is connected to the PSLab's PV1 pin,
45+
the Trig pin is connected to SQ1, Echo to LA1, and Gnd to GND.
46+
47+
>>> import pslab
48+
>>> from pslab.external.hcsr04 import HCSR04
49+
>>> psl = pslab.ScienceLab()
50+
>>> distance_sensor = HCSR04(psl)
51+
>>> psl.power_supply.pv1 = 5 # Power the sensor.
52+
>>> distance_sensor.estimate_distance()
53+
2.36666667
54+
"""
55+
56+
def __init__(
57+
self,
58+
device: SerialHandler,
59+
trig: str = "SQ1",
60+
echo: str = "LA1",
61+
):
62+
self._device = device
63+
LogicAnalyzer.__init__(self, self._device)
64+
PWMGenerator.__init__(self, self._device)
65+
self._trig = trig
66+
self._echo = echo
67+
self._measure_period = 60e-3 # Minimum recommended by datasheet.
68+
self._trigger_pulse_length = 10e-6
69+
70+
def estimate_distance(
71+
self,
72+
average: int = 10,
73+
speed_of_sound: float = 340,
74+
) -> float:
75+
"""Estimate distance to an object.
76+
77+
Parameters
78+
----------
79+
average : int, optional
80+
Number of times to repeat the measurement and average the results.
81+
Defaults to 10.
82+
speed_of_sound : float, optional
83+
Speed of sound in air. Defaults to 340 m/s.
84+
85+
Returns
86+
-------
87+
distance : float
88+
Distance to object in meters.
89+
90+
Raises
91+
------
92+
RuntimeError if the ECHO pin is not LOW at start of measurement.
93+
TimeoutError if the end of the ECHO pulse is not detected (i.e. the
94+
object is too far away).
95+
"""
96+
self.capture(
97+
channels=self._echo,
98+
events=2 * average,
99+
block=False,
100+
)
101+
self.generate(
102+
channels=self._trig,
103+
frequency=self._measure_period**-1,
104+
duty_cycles=self._trigger_pulse_length / self._measure_period,
105+
)
106+
time.sleep(self._measure_period * average)
107+
self.set_state(**{self._trig.lower(): 0})
108+
(t,) = self.fetch_data()
109+
self._sanity_check(len(t), 2 * average)
110+
high_times = t[::2] - t[1::2]
111+
return speed_of_sound * high_times.mean() / 2 * 1e-6
112+
113+
def _sanity_check(self, events: int, expected_events: int):
114+
if self.get_initial_states()[self._echo]:
115+
raise RuntimeError("ECHO pin was HIGH when measurement started.")
116+
117+
if events < expected_events:
118+
raise TimeoutError

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ commands = coverage run --source pslab -m pytest --record
2121
[testenv:lint]
2222
deps = -rlint-requirements.txt
2323
setenv =
24-
INCLUDE_PSL_FILES = pslab/bus/ pslab/instrument/ pslab/serial_handler.py pslab/cli.py pslab/external/motor.py pslab/external/gas_sensor.py
24+
INCLUDE_PSL_FILES = pslab/bus/ pslab/instrument/ pslab/serial_handler.py pslab/cli.py pslab/external/motor.py pslab/external/gas_sensor.py pslab/external/hcsr04.py
2525
commands =
2626
black --check {env:INCLUDE_PSL_FILES}
2727
flake8 --show-source {env:INCLUDE_PSL_FILES}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy