0

I apologize for my lack of knowledge, but I'm tying to have an ultrasonic sensor measure distance but I want it to measure distance every time I press the button. the script I have works, but only once and then I have to re run (F5) the program to get another reading. what am I missing? am I going about this the wrong way?

from gpiozero import Button
button=Button(21)

button.wait_for_press()

import RPi.GPIO as GPIO
import time
GPIO.setmode (GPIO.BCM)

TRIG = 23
ECHO = 24

print ("Distance Measurement In Progress")

GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)

GPIO.output(TRIG, False)
print ("waiting For Sensor To Settle")
time.sleep(2)

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 * 6756

distance = round(distance, 2)

print ("Distance:",distance,"in.")

GPIO.cleanup()

So after I press the button, and it runs through the script giving me a distance measurement, I want to be able to press the button again for a new measurement. Thank you in advance.

1
  • The sonar ranger code contains errors which will cause a hang eventually. Have a look at gpiozero (since you are already using it for the button) and see if it has a sonar ranger method.
    – joan
    Jan 4, 2017 at 9:45

3 Answers 3

1

Try this

#!/usr/bin/env python

# import 'pause' to efficiently wait for control+c signal from console to
# terminate the script
from signal import pause

from gpiozero import Button

from time import sleep, time

TRIGGER_PIN = 23                # physical pin # 16
ECHO_PIN = 24                   # physical pin # 18
BUTTON_PIN = 2                  # physical pin # 3

button = None                   # global reference
sensor = None                   # global reference


def take_measurement():
    global sensor
    print("distance is %0.2f cm" % (sensor.distance * 100))


def setup_sensor():             # one time initialization
    global button, sensor

    print("Initializing hardware ...")

    button = Button(BUTTON_PIN)
    button.when_pressed = take_measurement

    # queue_len = 1 should effectively make reading the distance property return the most
    # recently measured distance
    sensor = DistanceSensor(echo=ECHO_PIN, trigger=TRIGGER_PIN, queue_len=1)

    print("Ready. Push button to show distance.")


if __name__ == '__main__':
    setup_sensor()

    pause()

References

0

You need to put the main operation/process in a loop like while to keep it running constantly. You could do this a couple ways:

while true: # will run forever or until control+c is pressed or manually cancelled
    (operation)

or

import time

start_time = time.time()

duration = 10 #or however many seconds you want to run it for

elapsed_time = start_time - time.time()

while elapsed_time < duration:
    (operation)

    elapsed_time = start_time - time.time()
1
  • 1
    Busy looping for input is not a good thing (as per that article, an "anti-pattern"). It should be interrupt driven.
    – goldilocks
    Jan 4, 2017 at 12:33
0

Ideally, you should use interrupts. Define the button.when_pressed value to call a function instead of looping and waiting for input. This way you can have multiple buttons each waiting for a press. Here's an example which uses your code:

from gpiozero import Button
import RPi.GPIO as GPIO
import time

GPIO.setmode (GPIO.BCM)

continue_running=True

def measure_distance():
    TRIG = 23
    ECHO = 24

    print ("Distance Measurement In Progress")

    GPIO.setup(TRIG,GPIO.OUT)
    GPIO.setup(ECHO,GPIO.IN)

    GPIO.output(TRIG, False)
    print ("waiting For Sensor To Settle")
    time.sleep(2)

    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 * 6756

    distance = round(distance, 2)

    print ("Distance:",distance,"in.")

def exit_cleanly():
    global continue_running
    print ("Goodbye, World!")
    continue_running=False

def main():
    global continue_running
    buttonA=Button(21)
    buttonB=Button(GPIO_PIN_BUTTON_B) # Insert the number of the other pin
    buttonA.when_pressed = measure_distance
    buttonB.when_pressed = exit_cleanly

    # Now loop until you no longer need to
    while(continue_running):
        time.sleep(0.1)

if __name__ == "__main__": main()

Try it out, and let me know how that works!

2
  • I ran the program, it doesn't error but it doesn't do anything either even when I preys the button. Thank you for your attempt, I greatly appreciate it! Jan 5, 2017 at 3:09
  • Sorry, it needs to loop somewhere so it stays running. Using that method allows you to listen for button presses from more than one button. I'll update the code with a basic loop. Jan 5, 2017 at 7:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.