2018-02-26 11:31:06 +01:00
|
|
|
import time
|
|
|
|
|
2018-07-06 02:08:38 +02:00
|
|
|
from platypush.plugins import action
|
2019-12-20 21:24:47 +01:00
|
|
|
from platypush.plugins.gpio import GpioPlugin
|
2018-04-13 15:49:10 +02:00
|
|
|
from platypush.plugins.gpio.sensor import GpioSensorPlugin
|
2018-02-26 11:31:06 +01:00
|
|
|
|
|
|
|
|
2019-12-20 21:24:47 +01:00
|
|
|
class GpioSensorDistancePlugin(GpioPlugin, GpioSensorPlugin):
|
2018-06-25 00:49:45 +02:00
|
|
|
"""
|
|
|
|
You can use this plugin to interact with a distance sensor on your Raspberry
|
|
|
|
Pi (tested with a HC-SR04 ultrasound sensor).
|
|
|
|
|
|
|
|
Requires:
|
|
|
|
|
|
|
|
* ``RPi.GPIO`` (``pip install RPi.GPIO``)
|
|
|
|
"""
|
|
|
|
|
2019-12-21 13:09:44 +01:00
|
|
|
def __init__(self, trigger_pin: int, echo_pin: int,
|
2019-12-22 18:18:41 +01:00
|
|
|
timeout: float = 1.0, warmup_time: float = 2.0, *args, **kwargs):
|
2018-06-25 00:49:45 +02:00
|
|
|
"""
|
2019-12-21 13:09:44 +01:00
|
|
|
:param trigger_pin: GPIO PIN where you connected your sensor trigger PIN (the one that triggers the
|
|
|
|
sensor to perform a measurement).
|
2018-06-25 00:49:45 +02:00
|
|
|
|
2019-12-21 13:09:44 +01:00
|
|
|
:param echo_pin: GPIO PIN where you connected your sensor echo PIN (the one that will listen for the
|
|
|
|
signal to bounce back and therefore trigger the distance calculation).
|
|
|
|
|
|
|
|
:param timeout: The echo-wait will terminate and the plugin will return null if no echo has been
|
|
|
|
received after this time (default: 1 second).
|
|
|
|
|
|
|
|
:param warmup_time: Number of seconds that should be waited on plugin instantiation
|
|
|
|
for the sensor to be ready (default: 2 seconds).
|
2018-06-25 00:49:45 +02:00
|
|
|
"""
|
|
|
|
|
2019-12-20 21:24:47 +01:00
|
|
|
GpioPlugin.__init__(self, *args, **kwargs)
|
2018-02-26 11:31:06 +01:00
|
|
|
self.trigger_pin = trigger_pin
|
|
|
|
self.echo_pin = echo_pin
|
2019-12-21 13:09:44 +01:00
|
|
|
self.timeout = timeout
|
|
|
|
self.warmup_time = warmup_time
|
|
|
|
self._initialized = False
|
|
|
|
self._init_gpio()
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-20 21:40:57 +01:00
|
|
|
def _init_gpio(self):
|
2019-12-21 13:09:44 +01:00
|
|
|
if self._initialized:
|
|
|
|
return
|
|
|
|
|
2019-12-22 18:18:41 +01:00
|
|
|
import RPi.GPIO as GPIO
|
|
|
|
GPIO.setmode(self.mode)
|
|
|
|
GPIO.setup(self.trigger_pin, GPIO.OUT)
|
|
|
|
GPIO.setup(self.echo_pin, GPIO.IN)
|
|
|
|
GPIO.output(self.trigger_pin, GPIO.LOW)
|
2019-12-21 13:09:44 +01:00
|
|
|
|
|
|
|
self.logger.info('Waiting {} seconds for the sensor to be ready'.format(self.warmup_time))
|
|
|
|
time.sleep(self.warmup_time)
|
|
|
|
self.logger.info('Sensor ready')
|
|
|
|
self._initialized = True
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-20 21:40:57 +01:00
|
|
|
def _get_data(self):
|
2019-12-22 18:18:41 +01:00
|
|
|
import RPi.GPIO as GPIO
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-22 18:18:41 +01:00
|
|
|
pulse_start = pulse_on = time.time()
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-21 13:09:44 +01:00
|
|
|
self._init_gpio()
|
2019-12-22 18:18:41 +01:00
|
|
|
GPIO.output(self.trigger_pin, GPIO.HIGH)
|
2019-12-21 13:09:44 +01:00
|
|
|
time.sleep(0.00001) # 1 us pulse to trigger echo measurement
|
2019-12-22 18:18:41 +01:00
|
|
|
GPIO.output(self.trigger_pin, GPIO.LOW)
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-22 18:18:41 +01:00
|
|
|
while GPIO.input(self.echo_pin) == 0:
|
2018-03-02 16:02:04 +01:00
|
|
|
pulse_on = time.time()
|
2019-12-21 13:09:44 +01:00
|
|
|
if pulse_on - pulse_start > self.timeout:
|
|
|
|
raise TimeoutError('Distance sensor echo timeout after {} seconds: 0'.
|
2019-12-22 18:18:41 +01:00
|
|
|
format(self.timeout))
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2018-03-02 16:02:04 +01:00
|
|
|
pulse_start = pulse_on
|
2019-12-21 13:09:44 +01:00
|
|
|
pulse_end = pulse_off = time.time()
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-22 18:18:41 +01:00
|
|
|
while GPIO.input(self.echo_pin) == 1:
|
2018-03-02 16:02:04 +01:00
|
|
|
pulse_off = time.time()
|
2019-12-21 13:09:44 +01:00
|
|
|
if pulse_off - pulse_end > self.timeout:
|
|
|
|
raise TimeoutError('Distance sensor echo timeout after {} seconds: 1'.
|
2019-12-22 18:18:41 +01:00
|
|
|
format(self.timeout))
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2018-03-02 16:02:04 +01:00
|
|
|
pulse_end = pulse_off
|
|
|
|
pulse_duration = pulse_end - pulse_start
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-21 13:09:44 +01:00
|
|
|
# s = vt where v = 1/2 * avg speed of sound in mm/s
|
2018-03-02 16:02:04 +01:00
|
|
|
return round(pulse_duration * 171500.0, 2)
|
2018-02-26 11:31:06 +01:00
|
|
|
|
2019-12-20 21:40:57 +01:00
|
|
|
@action
|
|
|
|
def get_measurement(self):
|
|
|
|
"""
|
|
|
|
Extends :func:`.GpioSensorPlugin.get_measurement`
|
|
|
|
|
|
|
|
:returns: Distance measurement as a scalar (in mm):
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
return self._get_data()
|
2019-12-21 13:09:44 +01:00
|
|
|
except TimeoutError as e:
|
|
|
|
self.logger.warning(str(e))
|
|
|
|
return
|
|
|
|
except Exception as e:
|
|
|
|
self.close()
|
|
|
|
raise e
|
|
|
|
|
|
|
|
@action
|
|
|
|
def close(self):
|
2019-12-22 18:18:41 +01:00
|
|
|
import RPi.GPIO as GPIO
|
2019-12-21 13:09:44 +01:00
|
|
|
if self._initialized:
|
2019-12-22 18:18:41 +01:00
|
|
|
GPIO.cleanup()
|
2019-12-21 13:09:44 +01:00
|
|
|
self._initialized = False
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
self._init_gpio()
|
|
|
|
|
|
|
|
def __exit__(self):
|
|
|
|
self.close()
|
2019-12-20 21:40:57 +01:00
|
|
|
|
|
|
|
|
2018-02-26 11:31:06 +01:00
|
|
|
# vim:sw=4:ts=4:et:
|