1

I need to execute a bash-command in a python program on a raspberry pi, which starts a record, which really starts recording if their is the sound above a certain frequency and finishes after 8sec or if there is silence. After a record finished, it starts itself an waits for new sound to record. Each record is labeled with time. That's the code doing I quoted here:

while GPIO.input(26) == False:
    timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    process = subprocess.Popen ("rec -c 2 -r 192000 --buffer 50000 -b 32" + filepath + timestamp + ".wav sinc 0.1k silence 1 0.1 0.8% 1 0.4 0.8% vol 6 trim 0 8", shell = True)
    process.communicate()

As you can see, to finish the loop, the program waits for a GPIO-input signal (push button). I have an extra code which looks for the name of the subprocess and kills it.

But here is my problem: While the loop runs, it only "looks" for input in the millisecond between one record finishes and a new starts". If I push my button during a record, the loop continues after the record. It only breaks if I push in between.

At first, I thought maybe the while-loop is a bad choice...but if I am not wrong, the problem seems to be the running subprocess.

So here is my question: How can I accomplish this record loop but can stop/kill during a running record through user-input by GPIO. (ctrl+c won't be a viable option)

Many thanks

Esmi
  • 41
  • 4
  • `while GPIO.input(26) == False:` <-- doesn't this fire multiple times whenever it's false? I don't see any use of booleans or other locking/debouncing mechanisms to keep your program from starting 100s of subprocesses. `recording = False; while GPIO.input(26) == False and not recording: recording = True; start_recording(); # recording finishes... recording = False;` – jDo Mar 08 '16 at 21:28

1 Answers1

1

The issue is that the while loop only checks the condition once each time through the loop. The process.communicate() call waits for the rec command to finish, so you are absolutely right - the button is only checked once, just after the rec and before the timestamp = ....

A solution is to watch for the button in a separate thread, running in parallel with the rec. This answer suggests using event detection from the RPi.GPIO library. Try something like this:

should_exit = False

def my_callback(channel):
    if GPIO.input(26):
        should_exit = True

GPIO.add_event_detect(26, GPIO.RISING, callback=my_callback, bouncetime=300)

while not should_exit:
    timestamp = ...

The my_callback routine should run when the button is pressed, and set the should_exit flag. Once the rec finishes, the while will check should_exit and terminate. (Caution - not tested!)

Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81
  • many thanks, I will try it - My problem is that, I also would like to cancel the running record -but I guess - with this way I can execute the kill-script – Esmi Jan 12 '16 at 21:04
  • ok, I tryed it - and the event detect works - sometimes - but it seems very unreliable – Esmi Jan 12 '16 at 22:37
  • Glad it's better than nothing! I'm afraid I don't have personal experience with RPi.GPIO. Does the pushbutton have a proper pullup or pulldown? Are all the connections solid? Intermittent operation might be a hardware issue. Also, try a loop that doesn't run `rec` but just prints a debug message and see if the button is being detected properly. – cxw Jan 13 '16 at 13:59
  • i will try it thanks. until know sometimes it works nothing, than it works 2 times in a row and stops then detecting something and there are time it works very well for a longer time but stops detecting in input then, too - maybe it's an interference between the normal GPIO.in and the detection call – Esmi Jan 13 '16 at 19:48