-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
rsanchez
committed
Jan 7, 2017
1 parent
f237798
commit 7b02beb
Showing
2 changed files
with
148 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,69 @@ | ||
# micropython-hcsr04 | ||
Micropython driver for ultrasonic sensor HC-SR04 | ||
#HC-SR04 Sensor driver in micropython | ||
|
||
Micropython driver for the well-known untrasonic sensor [HC-SR04](http://www.micropik.com/PDF/HCSR04.pdf) | ||
|
||
The driver has been tested on Wemos D1 mini PRO, but It should work on whatever other micropython board, | ||
if anyone find problems in other boards, please open an issue and We'll see. | ||
|
||
##Motivation | ||
|
||
The existing drivers in micropython are a bit old and they don't use the relatively new method `machine.time_pulse_us()` which | ||
Is more accurate that whatever other method using pure python, besides the code is compliant with "standard" micropython, | ||
there is no code for specific boards. | ||
|
||
Finally I've added a method, `distance_mm()` that don't use floating point operations, for environments where there is no | ||
floating point capabilities. | ||
|
||
##Examples of use: | ||
|
||
###How to get the distance | ||
|
||
The `distance_cm()` method returns a `float` with the distance measured by the sensor. | ||
|
||
```python | ||
from hcsr04 import HCSR04 | ||
|
||
sensor = HCSR04(trigger_pin=16, echo_pin=0) | ||
|
||
distance = sensor.distance_cm() | ||
|
||
print('Distance:', distance, 'cm') | ||
``` | ||
|
||
There is another method, `distance_mm()`, that returns the distance in milimeters (`int` type) and **no floating point is used**, designed | ||
for environments that doesn't support floating point operations. | ||
|
||
```python | ||
distance = sensor.distance_mm() | ||
|
||
print('Distance:', distance, 'mm') | ||
``` | ||
|
||
We can also define a different timeout, passing the new value in microseconds to the constructor | ||
|
||
```python | ||
from hcsr04 import HCSR04 | ||
|
||
sensor = HCSR04(trigger_pin=16, echo_pin=0, echo_timeout_us=1000000) | ||
|
||
distance = sensor.distance_cm() | ||
|
||
print('Distance:', distance, 'cm') | ||
``` | ||
|
||
###Error management | ||
|
||
When the driver reaches the timeout while is listening the echo pin the error is converted to `OSError('Out of range')` | ||
|
||
```python | ||
from hcsr04 import HCSR04 | ||
|
||
sensor = HCSR04(trigger_pin=16, echo_pin=0, echo_timeout_us=10000) | ||
|
||
try: | ||
distance = sensor.distance_cm() | ||
print('Distance:', distance, 'cm') | ||
except OSError as ex: | ||
print('ERROR getting distance:', ex) | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import machine, time | ||
from machine import Pin | ||
|
||
__version__ = '0.1.0' | ||
__author__ = 'Roberto Sánchez' | ||
__license__ = "Apache License 2.0. https://www.apache.org/licenses/LICENSE-2.0" | ||
|
||
class HCSR04: | ||
""" | ||
Driver to use the untrasonic sensor HC-SR04. | ||
The sensor range is between 2cm and 4m. | ||
The timeouts received listening to echo pin are converted to OSError('Out of range') | ||
""" | ||
# Timeout is based in chip range limit (400cm) | ||
TIMEOUT_US = 500*2*30 | ||
def __init__(self, trigger_pin, echo_pin, echo_timeout_us=HCSR04.TIMEOUT_US): | ||
""" | ||
trigger_pin: Output pin to send pulses | ||
echo_pin: Readonly pin to measure the distance. The pin should be protected with 1k resistor | ||
echo_timeout_us: Timeout in microseconds to listen to echo pin. | ||
By default is based in sensor limit range (4m) | ||
""" | ||
self.echo_timeout_us = echo_timeout_us | ||
# Init trigger pin (out) | ||
self.trigger = Pin(trigger_pin, mode=Pin.OUT, pull=None) | ||
self.trigger.low() | ||
|
||
# Init echo pin (in) | ||
self.echo = Pin(echo_pin, mode=Pin.IN, pull=None) | ||
|
||
def _send_pulse_and_wait(self): | ||
""" | ||
Send the pulse to trigger and listen on echo pin. | ||
We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received. | ||
""" | ||
self.trigger.low() # Stabilize the sensor | ||
time.sleep_us(5) | ||
self.trigger.high() | ||
# Send a 10us pulse. | ||
time.sleep_us(10) | ||
self.trigger.low() | ||
try: | ||
pulse_time = machine.time_pulse_us(self.echo, 1, self.echo_timeout_us) | ||
return pulse_time | ||
except OSError as ex: | ||
if ex.args[0] == 110: # 110 = ETIMEDOUT | ||
raise OSError('Out of range') | ||
raise ex | ||
|
||
def distance_mm(self): | ||
""" | ||
Get the distance in milimeters without floating point operations. | ||
""" | ||
pulse_time = self._send_pulse_and_wait() | ||
|
||
# To calculate the distance we get the pulse_time and divide it by 2 | ||
# (the pulse walk the distance twice) and by 29.1 becasue | ||
# the sound speed on air (343.2 m/s), that It's equivalent to | ||
# 0.34320 mm/us that is 1mm each 2.91us | ||
# pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582 | ||
mm = pulse_time * 100 // 582 | ||
return mm | ||
|
||
def distance_cm(self): | ||
""" | ||
Get the distance in centimeters with floating point operations. | ||
It returns a float | ||
""" | ||
pulse_time = self._send_pulse_and_wait() | ||
|
||
# To calculate the distance we get the pulse_time and divide it by 2 | ||
# (the pulse walk the distance twice) and by 29.1 becasue | ||
# the sound speed on air (343.2 m/s), that It's equivalent to | ||
# 0.034320 cm/us that is 1cm each 29.1us | ||
cms = (pulse_time / 2) / 29.1 | ||
return cms | ||
|