Page 1 of 1

### Ultrasonic Sensor Problems

Posted: Thu Aug 14, 2014 7:48 am
hi im a beginner in programming and currently working with hc-sr04 and raspberry pi.
I just wanna your opinion on how to filter the hc-sr04 result.
i wanna take its previous data if the present data is too impossible. What is the best algorithm? or do u hav any opinion?

### Re: Ultrasonic Sensor Problems

Posted: Thu Aug 14, 2014 8:58 am
You could smooth the data, something along the lines of

distance = (new_distance * weight) + (distance * (1-weight))

Where weight is >0 and <=1.

A higher value for weight will favour the latest readings over the older.

e.g. suppose weight is 0.3 and distance is 23.

If new distance is 25 then

distance = (25 * 0.3) + (23 * 0.7) = 7.5 + 16.1 = 23.6

### Re: Ultrasonic Sensor Problems

Posted: Sat Aug 16, 2014 12:44 am

Your smoothing method is great but as you can see my readings vary too much. First , i think because of the signal is not stable by using GPIO.setup library. So, I use RPIO.setup and it's getting better. But still the readings vary too much. So i think i need some algorithm. Right now i try to use median filter. But my time.sleep or delay time is 10ms second, so i dont know whether it's too fast for the programming. Below is my ultrasonic sensor using servo and rpio library. The delay time is 10ms.

### Re: Ultrasonic Sensor Problems

Posted: Sat Aug 16, 2014 2:09 am
Have a look at http://www.raspberrypi.org/forums/viewt ... 57#p563957 for one method of getting accurate results.

### Re: Ultrasonic Sensor Problems

Posted: Mon Aug 18, 2014 1:39 am
Thanks joan..

I already read your link. But my hc-sr04 was tested in fixed condition actually. If i'm wrong please correct me . From the graph, i tested within 7 cm range, but the results is terrible . Is it because my time.sleep (10ms) ? Btw this is my code

Code: Select all

``````#!/usr/bin/python2

import RPi.GPIO as GPIO
from RPIO import PWM
import time
import RPIO
servo = PWM.Servo()

RPIO.setup(17,RPIO.IN)
RPIO.setup(17,RPIO.IN,pull_up_down=RPIO.PUD_DOWN)
def measure():

while RPIO.input(17) ==0:
start = time.time()

while RPIO.input(17) ==1:
stop = time.time()

distance = (stop-start)*34326.0/2.0

return distance

try:

while True:

servo.set_servo(4, 2000)
time.sleep(0.01)

distance = measure()

print ("Distance : %.10f" % distance)

except KeyboardInterrupt:
# User pressed CTRL-C
# Reset GPIO settings
GPIO.cleanup()
``````

### Re: Ultrasonic Sensor Problems

Posted: Mon Aug 18, 2014 7:22 am
I'm not sure what you are doing. There seems to be a mixture of the RPi and RPIO Python modules. I'd just use the one. If you are using PWM then RPIO is likely to be better (especially for servos).

There is no evidence of the trigger being sent to the HC-SR04. I'm surprised you get any readings at all. Could you check that you have posted the complete code.

Are you attempting to send the trigger pulse with the servo command? That is fairly specialised usage. If that's the intention please say as that might affect any proposed solution.

### Re: Ultrasonic Sensor Problems

Posted: Mon Aug 18, 2014 8:36 am
I use the servos library to stable the trigger signal. And the result is better compare by using a gpio library. When i used gpio library, it always freeze suddenly. From my research , python is a bit slow compare to others , that is why the ultrasonic sensor freeze suddenly( i dun know whether this is true or not) . Now i wanna do median or take previous data for filtering my result. But im lost.. Seriously im stuck coz i dun know how to do it. Im trying to search on internet but it just too little. I hope that you can give me references or book-that-must-buy for understanding and doing the python programming...
Thanks joan( sorry a bit upset today coz im just stuck..)

### Re: Ultrasonic Sensor Problems

Posted: Mon Aug 18, 2014 11:13 am
Here is some pigpio code which will give accurate results.

You need to change the ECHO and TRIGGER constants to reflect the Broadcom numbers of the gpios you are using.

You need to power the HC-SR04 from 5V and make sure you have a voltage divider to lower the echo line from 5V to 3.3V. If you power the HC-SR04 from 3.3V it will not give reliable results.

Code: Select all

``````#!/usr/bin/env python

# 2014-08-18 hc-sr04.py

import time

import pigpio

TRIGGER=21
ECHO=20

high_tick = None # global to hold high tick.

def cbfunc(gpio, level, tick):
global high_tick
if level == 0: # echo line changed from high to low.
if high_tick is not None:
echo = pigpio.tickDiff(high_tick, tick)
cms = (echo / 1000000.0) * 34030 / 2
print("echo was {} micros long ({:.1f} cms)".format(echo, cms))
else:
high_tick = tick

pi = pigpio.pi() # Connect to local Pi.

pi.set_mode(TRIGGER, pigpio.OUTPUT)
pi.set_mode(ECHO, pigpio.INPUT)

cb = pi.callback(ECHO, pigpio.EITHER_EDGE, cbfunc)

start = time.time()

while (time.time()-start) < 60:
pi.gpio_trigger(TRIGGER, 10)
time.sleep(0.1)

cb.cancel() # Cancel callback.
pi.stop() # Close connection to Pi
``````
Moving a piece of card forwards and backwards.

Code: Select all

``````harry ~ \$ /code/hc-sr04.py
echo was 1365 micros long (23.2 cms)
echo was 1285 micros long (21.9 cms)
echo was 1205 micros long (20.5 cms)
echo was 1136 micros long (19.3 cms)
echo was 1040 micros long (17.7 cms)
echo was 941 micros long (16.0 cms)
echo was 895 micros long (15.2 cms)
echo was 845 micros long (14.4 cms)
echo was 805 micros long (13.7 cms)
echo was 784 micros long (13.3 cms)
echo was 705 micros long (12.0 cms)
echo was 670 micros long (11.4 cms)
echo was 610 micros long (10.4 cms)
echo was 560 micros long (9.5 cms)
echo was 530 micros long (9.0 cms)
echo was 500 micros long (8.5 cms)
echo was 480 micros long (8.2 cms)
echo was 455 micros long (7.7 cms)
echo was 435 micros long (7.4 cms)
echo was 426 micros long (7.2 cms)
echo was 409 micros long (7.0 cms)
echo was 395 micros long (6.7 cms)
echo was 390 micros long (6.6 cms)
echo was 375 micros long (6.4 cms)
echo was 425 micros long (7.2 cms)
echo was 435 micros long (7.4 cms)
echo was 445 micros long (7.6 cms)
echo was 455 micros long (7.7 cms)
echo was 505 micros long (8.6 cms)
echo was 515 micros long (8.8 cms)
echo was 555 micros long (9.4 cms)
echo was 590 micros long (10.0 cms)
echo was 630 micros long (10.7 cms)
echo was 680 micros long (11.6 cms)
echo was 755 micros long (12.8 cms)
echo was 860 micros long (14.6 cms)
echo was 950 micros long (16.2 cms)
echo was 1055 micros long (18.0 cms)
echo was 1165 micros long (19.8 cms)
echo was 1265 micros long (21.5 cms)
echo was 1354 micros long (23.0 cms)
``````

### Re: Ultrasonic Sensor Problems

Posted: Tue Aug 19, 2014 5:00 am

Thanks Joan , may god bless you..
The result is amazing. Speechless*.....Thanks x1000000
sorry but I have a few more questions for you.
1) Why the result is stable? Is it because you make the library from C , thus making it work faster and stable compare to GPIO.library?
2) Base on your website, is it the same if I use your pull_up_down resistor instead of using resistors to regulate the voltage in Echo pin?
Im still studying your library..btw thanks Joan for developing such great library

### Re: Ultrasonic Sensor Problems

Posted: Tue Aug 19, 2014 8:25 am
nizam wrote: ...
1) Why the result is stable? Is it because you make the library from C , thus making it work faster and stable compare to GPIO.library?
2) Base on your website, is it the same if I use your pull_up_down resistor instead of using resistors to regulate the voltage in Echo pin?
...
1. pigpio samples the gpio levels (on or off) many times a second using DMA. If the level changes the time of the sample is stored as well as the new level. The time of the sample is accurate to within a few microseconds. Other programs don't do this, the first they know about the level change is either when they are woken (callback or interrupt) or when they read the level (busy spin). Both those methods introduce inaccuracies to do with the way Linux schedules processes. Generally you would be better off using busy spins to detect level changes in other programs, if you want accuracy.
2. No, pull-ups/downs are not the same and as far as I'm aware offer little or no protection against high external voltages. A voltage divider using a pair of resistors is the simplest and safest option.

### Re: Ultrasonic Sensor Problems

Posted: Wed Aug 20, 2014 5:24 am
A million thanks Joan...

Is it true that python language is a bit slow compare to C language?
Btw Im working and trying on changing the code to my old code. Pray for me though..coz Im a noob programmer

### Re: Ultrasonic Sensor Problems

Posted: Wed Aug 20, 2014 7:16 am
nizam wrote: ...
Is it true that python language is a bit slow compare to C language?
...(
It depends on what you are doing. Most of Python is function calls to C anyhow so there will be no difference once that call is made.

For example the following code (generating jpegs from pngs) will not run noticeably slower than its C alternative but will probably be faster to develop.

Code: Select all

``````...
from wand.image import Image
...
for i in range(1000):
with Image(filename='in{}.png'.format(i)) as img:
img.format = 'jpeg'
img.save(filename='out{}.jpg'.format(i))
...
``````

### Re: Ultrasonic Sensor Problems

Posted: Fri Aug 22, 2014 12:36 pm
thanks joan... this time i had some trouble with installing your library to my other rpi.
it says can't lock /var/run/crond.pid pigpio initialisation failed
It appears when i run sudo ./x_pigpio and sudo pigpiod
Where should i initialise it?

### Re: Ultrasonic Sensor Problems

Posted: Fri Aug 22, 2014 1:11 pm
nizam wrote:thanks joan... this time i had some trouble with installing your library to my other rpi.
it says can't lock /var/run/crond.pid pigpio initialisation failed
It appears when i run sudo ./x_pigpio and sudo pigpiod
Where should i initialise it?
x_pigpio is a standalone program to test the C library interface. You can't run it at the same time as the pigpio daemon.

If the pigpio daemon is running then use the following command to stop it.

sudo killall pigpiod

Then you can test the C I/F.

sudo ./x_pigpio

The you can start the daemon

sudo pigpiod

and test the C daemon I/F, Python I/F, pipe I/F, and socket I/F.

./x_pigpiod_if
./x_pigpio.py
./x_pipe
./x_pigs

### Re: Ultrasonic Sensor Problems

Posted: Sun Apr 12, 2015 4:38 pm
Hi,i am a beginner. I am making a project with ultrasonic sensor which play some sound files on the audio jack when the distance is between 1 and 10,then another sound for ranges which is greater than 10 cm.

Please, can anyone wrote me the program.if you do so,please enter some directory in the variable to tell raspberry where the sound file is,i.e in desktop or a folder, i will change to the correct directory.

Thanks

### Re: Ultrasonic Sensor Problems

Posted: Fri Jan 13, 2017 12:52 am
joan wrote:Here is some pigpio code which will give accurate results.

You need to change the ECHO and TRIGGER constants to reflect the Broadcom numbers of the gpios you are using.

You need to power the HC-SR04 from 5V and make sure you have a voltage divider to lower the echo line from 5V to 3.3V. If you power the HC-SR04 from 3.3V it will not give reliable results.

Code: Select all

``````#!/usr/bin/env python

# 2014-08-18 hc-sr04.py

import time

import pigpio

TRIGGER=21
ECHO=20

high_tick = None # global to hold high tick.

def cbfunc(gpio, level, tick):
global high_tick
if level == 0: # echo line changed from high to low.
if high_tick is not None:
echo = pigpio.tickDiff(high_tick, tick)
cms = (echo / 1000000.0) * 34030 / 2
print("echo was {} micros long ({:.1f} cms)".format(echo, cms))
else:
high_tick = tick

pi = pigpio.pi() # Connect to local Pi.

pi.set_mode(TRIGGER, pigpio.OUTPUT)
pi.set_mode(ECHO, pigpio.INPUT)

cb = pi.callback(ECHO, pigpio.EITHER_EDGE, cbfunc)

start = time.time()

while (time.time()-start) < 60:
pi.gpio_trigger(TRIGGER, 10)
time.sleep(0.1)

cb.cancel() # Cancel callback.
pi.stop() # Close connection to Pi
``````
Moving a piece of card forwards and backwards.

Code: Select all

``````harry ~ \$ /code/hc-sr04.py
echo was 1365 micros long (23.2 cms)
echo was 1285 micros long (21.9 cms)
echo was 1205 micros long (20.5 cms)
echo was 1136 micros long (19.3 cms)
echo was 1040 micros long (17.7 cms)
echo was 941 micros long (16.0 cms)
echo was 895 micros long (15.2 cms)
echo was 845 micros long (14.4 cms)
echo was 805 micros long (13.7 cms)
echo was 784 micros long (13.3 cms)
echo was 705 micros long (12.0 cms)
echo was 670 micros long (11.4 cms)
echo was 610 micros long (10.4 cms)
echo was 560 micros long (9.5 cms)
echo was 530 micros long (9.0 cms)
echo was 500 micros long (8.5 cms)
echo was 480 micros long (8.2 cms)
echo was 455 micros long (7.7 cms)
echo was 435 micros long (7.4 cms)
echo was 426 micros long (7.2 cms)
echo was 409 micros long (7.0 cms)
echo was 395 micros long (6.7 cms)
echo was 390 micros long (6.6 cms)
echo was 375 micros long (6.4 cms)
echo was 425 micros long (7.2 cms)
echo was 435 micros long (7.4 cms)
echo was 445 micros long (7.6 cms)
echo was 455 micros long (7.7 cms)
echo was 505 micros long (8.6 cms)
echo was 515 micros long (8.8 cms)
echo was 555 micros long (9.4 cms)
echo was 590 micros long (10.0 cms)
echo was 630 micros long (10.7 cms)
echo was 680 micros long (11.6 cms)
echo was 755 micros long (12.8 cms)
echo was 860 micros long (14.6 cms)
echo was 950 micros long (16.2 cms)
echo was 1055 micros long (18.0 cms)
echo was 1165 micros long (19.8 cms)
echo was 1265 micros long (21.5 cms)
echo was 1354 micros long (23.0 cms)
``````
Hi Joan!

I'm working on a school project and we're trying to make a theremin with pi and python. Here's our code

Code: Select all

``````# -*- coding: utf-8 -*-
"""
Created on Thu Nov 24 00:43:51 2016

@author: ABC
"""
import RPi.GPIO as GPIO
import pygame
import pygame.midi
import time
import math
import statistics

def prepare(GPIO_TRIGGER, GPIO_ECHO):
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.output(GPIO_TRIGGER, False)
time.sleep(0.1)

def get_distance(GPIO_TRIGGER, GPIO_ECHO):
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
try:
while GPIO.input(GPIO_ECHO)==0:
start = time.time()
except Exception:
pass
try:
while GPIO.input(GPIO_ECHO)==1:
stop = time.time()
except Exception:
pass
elapsed = stop - start
distance = (elapsed * 34300)/2
return int(distance)

#def interrupt:

def conf_midi():
instrument = 79
device_id = 2
latency = 0
buffer_size = 0
global midiOutput
midiOutput = pygame.midi.Output(device_id, latency, buffer_size)
midiOutput.set_instrument(instrument)

def get_note(median_dist):
minDist = 5
maxDist = 50
octaves = 2
minNote = 48
maxNote = minNote + 12*octaves
fup = (median_dist - minDist)*(maxNote-minNote)
fdown = (maxDist - minDist)
note = maxNote - (fup/fdown)
if (median_dist>50):
note=b4note
if (median_dist<5):
note=b4note
return int (note)

def play_midi(note, b4note, velocity):
if (note != b4note):
midiOutput.note_off(b4note, 0)
midiOutput.note_on(note, 127)

pygame.init()
pygame.midi.init()

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

GPIO_TRIGGER = 8
GPIO_ECHO = 7

prepare(GPIO_TRIGGER, GPIO_ECHO)

note = 0
velocity = 0

conf_midi()

try:
while True:
b4note = note
list = []
print('Start distance messurement')
while len(list) < 4:
dist = get_distance(GPIO_TRIGGER, GPIO_ECHO)
list.append(dist)
time.sleep(0.1)
median_dist = statistics.median(list)
print("median:", median_dist)
str(dist)
del list [:]
note = get_note(median_dist)
#print(note)
str(note)
play_midi(note, b4note, velocity)
time.sleep(0.1)

except Exception:
pass

except KeyboardInterrupt:
GPIO.cleanup()
del midiOutput
pygame.midi.quit()
GPIO.cleanup()

``````
It works but always freezes after 20-30s and we're really stuck now ( We're both raspberry and python noobs. And the deadline is in 1 week T_T
I stumbled upon your post and thought maybe we can try it out! So I tried to use pigpio to get the distance but not sure now how to get the "cms" from that function for later use.
I tried to to put

Code: Select all

``return int(cms)``
at the end of your code but it didn't work.
Try to call it name it "cbfunc.cms" so that we can call it outside the function but nothing happened.

### Re: Ultrasonic Sensor Problems

Posted: Fri Jan 13, 2017 7:55 am
I am not @joan, but this is a forum not a messaging service. ( @joan responds in these forums on most days, so you may get a personal response later.)

It looks to me as though the code you have posted is unrelated to the working sample you quote, and does not use the pigpio library that @joan has written.

To return the measured distance from the sample cbfunc function you would need to put the return statement after the print statement, not at the end. But I think the level of python coding in that sample probably exceeds your level of coding ability and you probably won't be able to learn enough to fix that in the week left to submit your project.

### Re: Ultrasonic Sensor Problems

Posted: Fri Jan 13, 2017 8:01 am
The gpiozero python library contains support for ultrasonic distance sensors.

Maybe using that code instead of your own version would help determine where the freeze-up is occurring?