Tuesday, April 3, 2018

Ultrasonic distance sensors

There are 3 pin modules , 4 pin as well as 5 pin modules. These are the most common and inexpensive ones I have come across.


1. Ping Module
2. HC-SR04
3. DYP-ME007v1

HC-SR04 is an ultrasonic ranging sensor. This economical sensor provides
2cm to 400cm of non-contact measurement functionality with a ranging
accuracy that can reach up to 3mm. Each HC-SR04 module includes an
ultrasonic transmitter, a receiver and a control circuit.
There are four pins on the HC-SR04: VCC (Power), Trig (Trigger), Echo (Receive), and GND (Ground).

There's another variant called DYP-ME007. This module has 5 pins. 5 pin module
can be used as a 4 pin or 3 pin module. If you leave out the 4th pin  (OUT)  in
a  5 Pin Module , it behaves as a 4 pin Module. If you Ground the 4th pin then
it behaves as a 3 pin PING module. If 4th pin is connected to GND ,pin 2 is left out.
Now the  Trigger Input & Echo Output appears on single pin 3 (behaves as a 3 pin module).
So 4th pin of a 5pin module acts as a Mode Select pin.

I have tested both the 4 pin and 5 pin modules with RPi. Both performed similarly. The datasheet
claims these modules to have 2cm to 400 cm range but in practice it's effective upper range cuts
off at about 200 cm. The lower range is about 4 cm. The detection angle is around ±30°. The RPi being an MPU won't have accurate results as it's not strictly executing just my program and the timing will be a bit off. If accuracy is needed then MCU should be used as it offers tighter controls.

Unfortunately, I don't have the 3 pin ping module at hand for testing.

Here's my setup (ignore the SIM800L module it's for another project)


It should be noted that the ECHO pin is fed to the RPi via resistor dividers since the sensor is powered from 5V. Using simple resistors to shift the voltage level might introduce some inaccuracies but that is yet to be tested. It would be ideal to use a proper level shifter in my opinion but the accuracy was never of any concern in this project. 

Here's a quick and dirty demo code I wrote for RPi 3 Model B on Raspbian Wheezy distro. It might need further furnishing (probably does). ➤

πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
TRIG = 23
ECHO = 24
LED  = 27
u = 200 #upper threshold
l = 4         #lower threshold
count = 0

print "Measuring distance:"

GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
GPIO.setup(LED,  GPIO.OUT)
GPIO.output(LED, False)

def onCount():

global count
while count < 5:

GPIO.output(TRIG, False)
print "On processing..."
time.sleep(0.1)

GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)

while GPIO.input(ECHO) == 0:
pulse_start = time.time()

while GPIO.input(ECHO) == 1:
pulse_end = time.time()

pulse_duration = pulse_end - pulse_start

distance = pulse_duration * 17150

distance = round(distance, 2)

print "Distance: ", distance, "cm"

if int(distance) in range (l, u):
count += 1;
else:
count = 0;

pulse_start = 0
pulse_end    = 0
pulse_duration = 0

count = 0
GPIO.output(LED, True)

def offCount():

global count
while count < 5:

GPIO.output(TRIG, False)
print "Off processing..."
time.sleep(0.1)

GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)

while GPIO.input(ECHO) == 0:
pulse_start = time.time()

while GPIO.input(ECHO) == 1:
pulse_end = time.time()

pulse_duration = pulse_end - pulse_start

distance = pulse_duration * 17150

distance = round(distance, 2)

print "Distance: ", distance, "cm"

if int(distance) in range (l, u):
count = 0;
else:
count += 1;

pulse_start = 0
pulse_end    = 0
pulse_duration = 0

count = 0
GPIO.output(LED, False)

try:
while True:

onCount()
offCount()

finally:

GPIO.cleanup()

πŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”Ί

I actually plan on using this sensor to sense presence in front of a 46" LED TV from 1.5 m away. The TV will play and pause a video according to the viewer standing in front.

I shall post another post about that project when it's done.

Here's a demo code of how to play and pause videos on omxplayer which starts a video, pauses 3 seconds in to the video for 3 seconds and then plays it for 3 seconds and finally closes the video. There are probably far better ways to do this but this is the method that came to me at the time of writing. ➤

πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»πŸ”»

import os
import sys
import subprocess
from time import sleep
from subprocess import Popen

path = "/home/pi/video1.mp4"

def play_video():
omxprocess = subprocess.Popen(['omxplayer', '-b', '--no-osd', path], stdin=subprocess.PIPE, stdout=None, stderr=None, bufsize=0)
sleep(3)
omxprocess.stdin.write('p')
sleep(3)
omxprocess.stdin.write('p')
sleep(3)
omxprocess.stdin.write('q')

play_video()

πŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”ΊπŸ”Ί

I followed this tutorial ---------------------->

Tutorial 1

This one is useful too ----------------------->

Tutorial 2

I wonder whether ultrasonic bursts are harmful to humans. I haven't seen many articles on this topic although I didn't look thoroughly. It would be interesting to research on this topic.

No comments:

Post a Comment