Let us go back to the distance sensor again. We haven't spent too much time on it.
For our project, we use the Ultrasonic Ranging Module HC - SR04. It is cheap and easy to work with. For more details about the sensor, here are two useful links:
- https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi
- http://www.micropik.com/PDF/HCSR04.pdf
- http://www.elecfreaks.com/store/download/product/Sensor/HC-SR04/HC-SR04_Ultrasonic_Module_User_Guide.pdf
The first link is highly recommended.
The sensor has four pins: (1)Ground;(2)Vcc;(3)Trig;(4)Echo. The first two pins are easy to understand. (1) need to be connect to ground and (2) provides the power to the sensor. 5V is in the working voltage range so we can connect the power pin of raspberry pi to the sensor directly.
The sensor has four pins: (1)Ground;(2)Vcc;(3)Trig;(4)Echo. The first two pins are easy to understand. (1) need to be connect to ground and (2) provides the power to the sensor. 5V is in the working voltage range so we can connect the power pin of raspberry pi to the sensor directly.
(3) is the input pin of the sensor. Once the sensor receives the input pulse, it sends out ultrasonic wave. Let T denote the time between the sensor sends out the wave and the time it receives the echo. After the sensor receives the echo, it will generate an output pulse in the Echo pin that lasts T (s). Therefore, the distance is 0.5 * speed_of_sound * T.
Before we talk about the code, we should point out that the original structure mentioned in the previous posts is not strong enough to hold the sensor when we connect the wire to the sensor. If the sensor is not strictly locked, the measures will have too much noise and will not be accurate enough to provide useful information. So we need to make some enhancements and here is the result:
Before we talk about the code, we should point out that the original structure mentioned in the previous posts is not strong enough to hold the sensor when we connect the wire to the sensor. If the sensor is not strictly locked, the measures will have too much noise and will not be accurate enough to provide useful information. So we need to make some enhancements and here is the result:
The code is not hard to write if we only measure the distance once. The problem is that we want to create a kind of "radar" that can scan the space in front of the car. It means that the sensor need to continuously measure the distance and send back the results. Let us assume that we have a function called measure_once which allows us to perform a single measure. If we simply put this function in a while loop, it will not work because in that case the sensor can no longer send back the results.
Fortunately, there is one solution to this problem: Coroutine.
For more details about Coroutine in Python, I highly recommend the online tutorial:
A Curious Course on Coroutines and Concurrency by David Beazley. The version of Python used in the tutorial is 2.7 but almost everything can work directly in Python 3. It seems that python 3 has a package called asyncio dedicated to the tasks and coroutines. It maybe a good idea to check the official documentation later.
Here is the first version of the code:
import RPi.GPIO as gpio import time #gpio.setmode(gpio.BCM) gpio.setmode(gpio.BOARD) class DistanceSensor: SUCC = 'SUCC' INIT = 'INIT' TIMEOUT = 'TIMEOUT' FAIL = 'FAIL' def __init__(self, pin_echo=None, pin_trig=None, unit='m'): assert pin_echo is not None and pin_trig is not None self._pin_echo = pin_echo self._pin_trig = pin_trig gpio.setup(pin_echo, gpio.IN, pull_up_down=gpio.PUD_DOWN) gpio.setup(pin_trig, gpio.OUT, initial=0) time.sleep(1.) self._pulse = 0.00001 self._status = DistanceSensor.INIT self._latest_measure = (None, DistanceSensor.INIT) def measure_once(self): """ measure the distance once. The returnd value is (distance, status) """ # send out the signal gpio.output(self._pin_trig, 1) time.sleep(self._pulse) gpio.output(self._pin_trig, 0) start = time.time() _start = start while gpio.input(self._pin_echo) == 0: # no echo signal received if time.time() - _start > 1.: self._status = DistanceSensor.TIMEOUT break start = time.time() if self._status == DistanceSensor.TIMEOUT: return None, self._status while gpio.input(self._pin_echo) == 1: # receiving the echo signal stop = time.time() distance_m = 170. * (stop - start) # sanity check if distance_m < 0.04 or distance_m > 4: self._status = DistanceSensor.FAIL distance_m = None else: self._status = DistanceSensor.SUCC return distance_m, self._status def measure(self, delay=0.1): """ Measure the distance several times. The Measure function will return a coroutine. """ try: while True: msg = (yield) self._latest_measure = self.measure_once() time.sleep(delay) except GeneratorExit: print('disconnect to the distance sensor') pass if __name__ == '__main__': echo = 18 trig = 16 distance_sensor = DistanceSensor(pin_echo=echo, pin_trig=trig) input('press any key to start') #print(distance_sensor.measure_once()) observer = distance_sensor.measure(repeat=30) next(observer) res = [] for msg in ['m','m','m','stop']: observer.send(msg) res.append(distance_sensor._latest_measure) observer.close() for item in res: print(item)
--END--
No comments:
Post a Comment