Page 1 of 1

[HELP] One button two tasks

Posted: Mon Feb 20, 2017 8:22 pm
by Mates1774

Code: Select all

import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
    input_state = GPIO.input(24)
    if input_state == False:
        run = False
        if run == False:
                os.system("nohup /home/pi/radio.sh &>/dev/null &")
                time.sleep(4)
                print()
                run = True
        time.sleep(0.2)
        if run == True:
                os.system("sudo pkill mplayer")
                run = False
        time.sleep(0.2)
I want if I click for the first time turn on script and if a script run and I click to button again, the script kill mplayer. But my code doesn't work. Please help. Thank's
[Sorry for my bad English]

Re: [HELP] One button two tasks

Posted: Tue Feb 21, 2017 2:05 pm
by ghp
Hello,
think there are two areas where your script needs to be improved.
One point is the arrangement of code

Code: Select all

        if run == False:
                os.system("nohup /home/pi/radio.sh &>/dev/null &")
                time.sleep(4)
                print()
                run = True
        time.sleep(0.2)
        if run == True:
                os.system("sudo pkill mplayer")
                run = False
 
if the first "if run == False"- block, the run-variable is set to True. Which immediately results in the execution of the " if run == True:"-Block. So your mplayer gets stopped immediately after a start.
Here an 'else if '-condition for the second block would help.

The other point is the handling of button pressed-event. Think you want to achieve something like 'when button pressed first time, then switch on, when button pressed second, switch off' The unspoken event in between is to check for a button released condition.

Here a proposal for a state based approach. I used GPIO 3, change this back to your GPIO used. The quite long delay(0.1) is to debounce the button and avoids excessive cpu usage.

Code: Select all

import RPi.GPIO as GPIO
import time

debug = True

BUTTON_GPIO = 3

GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_GPIO, GPIO.IN)

# the signals used to detect button pressed/released signals.
# here: button is connected to gnd (active is a low signal)
PRESSED = 0
RELEASED = 1

# the state enumerations are defined here as 'constants'. The development environment I use 
# allows for variable lookup and thus avoids problem by misspelling
#
START = 'start'
B0_RELEASED = 'B0_RELEASED'
B0_PRESSED= 'B0_PRESSED'

B1_RELEASED= 'B1_RELEASED'
B1_PRESSED= 'B1_PRESSED'

state = START
nextState = None

while True:
    time.sleep(0.1)
    nextState = None
    c = GPIO.input(BUTTON_GPIO)
    if state == START:
        if c == RELEASED:
            nextState = B0_RELEASED
            
    elif state == B0_RELEASED:
        if c == PRESSED:
            nextState = B0_PRESSED
            print("do your switch ON radio action here")
                 
    elif state == B0_PRESSED:
        if c == RELEASED:
            nextState = B1_RELEASED
            
    elif state == B1_RELEASED:
        if c == PRESSED:
            nextState = B1_PRESSED
            print("do your switch OFF radio action here")

    elif state == B1_PRESSED:
        if c == RELEASED:
            nextState = B0_RELEASED
    
    if debug == True:
        if nextState != None:
            print("{state:s} --[ {c:d} ]--> {nextstate:s}".format(state=state, c=c, nextstate=nextState))
    if nextState != None:
        state = nextState
Regards,
Gerhard

Re: [HELP] One button two tasks

Posted: Tue Feb 21, 2017 2:31 pm
by gordon77
Try this...

Code: Select all

import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)

run = False
while True:
    if GPIO.input(24) == False:
        if run == False:
           os.system("nohup /home/pi/radio.sh &>/dev/null &")
           #time.sleep(4)
           print('start')
           run = True
           while GPIO.input(24) == False:
              time.sleep(.2)
        if run == True and GPIO.input(24) == False:
           os.system("sudo pkill mplayer")
           print ('stop')
           run = False
        time.sleep(0.2)

Re: [HELP] One button two tasks

Posted: Tue Feb 21, 2017 5:35 pm
by Davies
or this..

Code: Select all

import RPi.GPIO as GPIO
import os
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, GPIO.PUD_UP)

run = 0  # variable to see different states
while True:
    if not GPIO.input(24) and run == 0:  # gpio to ground and not currently running
        os.system("nohup /home/pi/radio.sh &>/dev/null &")
        print('start')
        run = 1
        while not GPIO.input(24):  # buffer to wait until button release
            time.sleep(0.2)
    if not GPIO.input(24) and run == 1:  # gpio to ground and currently running
        os.system("sudo pkill mplayer")
        print ('stop')
        run = 0
        while not GPIO.input(24):  # buffer to wait until button release
            time.sleep(0.2)
    time.sleep(0.2)  # sleep so you dont have an out of control while loop eating up cpu while button not pressed


Re: [HELP] One button two tasks

Posted: Wed Feb 22, 2017 8:48 pm
by Mates1774
ghp wrote:Hello,
think there are two areas where your script needs to be improved.
One point is the arrangement of code

Code: Select all

        if run == False:
                os.system("nohup /home/pi/radio.sh &>/dev/null &")
                time.sleep(4)
                print()
                run = True
        time.sleep(0.2)
        if run == True:
                os.system("sudo pkill mplayer")
                run = False
 
if the first "if run == False"- block, the run-variable is set to True. Which immediately results in the execution of the " if run == True:"-Block. So your mplayer gets stopped immediately after a start.
Here an 'else if '-condition for the second block would help.

The other point is the handling of button pressed-event. Think you want to achieve something like 'when button pressed first time, then switch on, when button pressed second, switch off' The unspoken event in between is to check for a button released condition.

Here a proposal for a state based approach. I used GPIO 3, change this back to your GPIO used. The quite long delay(0.1) is to debounce the button and avoids excessive cpu usage.

Code: Select all

import RPi.GPIO as GPIO
import time

debug = True

BUTTON_GPIO = 3

GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_GPIO, GPIO.IN)

# the signals used to detect button pressed/released signals.
# here: button is connected to gnd (active is a low signal)
PRESSED = 0
RELEASED = 1

# the state enumerations are defined here as 'constants'. The development environment I use 
# allows for variable lookup and thus avoids problem by misspelling
#
START = 'start'
B0_RELEASED = 'B0_RELEASED'
B0_PRESSED= 'B0_PRESSED'

B1_RELEASED= 'B1_RELEASED'
B1_PRESSED= 'B1_PRESSED'

state = START
nextState = None

while True:
    time.sleep(0.1)
    nextState = None
    c = GPIO.input(BUTTON_GPIO)
    if state == START:
        if c == RELEASED:
            nextState = B0_RELEASED
            
    elif state == B0_RELEASED:
        if c == PRESSED:
            nextState = B0_PRESSED
            print("do your switch ON radio action here")
                 
    elif state == B0_PRESSED:
        if c == RELEASED:
            nextState = B1_RELEASED
            
    elif state == B1_RELEASED:
        if c == PRESSED:
            nextState = B1_PRESSED
            print("do your switch OFF radio action here")

    elif state == B1_PRESSED:
        if c == RELEASED:
            nextState = B0_RELEASED
    
    if debug == True:
        if nextState != None:
            print("{state:s} --[ {c:d} ]--> {nextstate:s}".format(state=state, c=c, nextstate=nextState))
    if nextState != None:
        state = nextState
Regards,
Gerhard
Thank you, it work's.