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 '17 at 9:45
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 '17 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 '17 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 '17 at 7:54

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .