Skip to content

Commit

Permalink
Initial commit, version 0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
rsanchez committed Jan 7, 2017
1 parent f237798 commit 7b02beb
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 2 deletions.
71 changes: 69 additions & 2 deletions README.md
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)

```
79 changes: 79 additions & 0 deletions hcsr04.py
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

0 comments on commit 7b02beb

Please sign in to comment.