Page 1 of 1

Mother needs help with Push Button GPIO

Posted: Fri Nov 25, 2016 8:23 pm
by Testamine
First off, I am a beginner in programming, so have some faith in me :) I started with Raspberry after my kids got a kit for christmas. I have searched for a solution, but found none. Also error-searching to try fix it my self have been 20+hours, so I really hope some clever heads can guide me.

The problem:
I have a TV connected to a Raspberry Pi 3. From the Raspberry I have connected a pushbutton that turns ON/OFF the Raspberry. The pushbutton is connected to GPIO3 and GROUND (5,6) (no resistors, just cables from GPIO and to my pushbutton. Every thing works perfect, except when I connect something to a close powersocket, like my scrapping glue gun / heating machine. When I do this, the Raspberry shuts down, looks like Ive pressed the Push button to turn it off. I think it has to be a power disturbance for the Raspberry messing up?

Also I figure this has something to do with my script (?), and maybe I need to put a delay on it somehow? So that when the Raspberry gets the power disturbance, it will overlook it since it only was there for under a second. Am I on the right path here?

This is the python script Im using. Please help my modify it so that the Raspberry stops shutting down ramdomly when something is disturbing the power.


#!/bin/python

# Simple script for shutting down the raspberry Pi at the press of a button.

import RPi.GPIO as GPIO

import time

import os


GPIO.setmode(GPIO.BCM)
GPIO.setup(3, GPIO.IN, pull_up_down = GPIO.PUD_UP)

# Our function on what to do when the button is pressed
def Shutdown(channel): os.system("sudo shutdown -h now") 



# Add our function to execute when the button pressed event happens
GPIO.add_event_detect(3, GPIO.FALLING, callback = Shutdown, bouncetime = 2000)


# Now wait!

while 1: time.sleep(1)

Re: Mother needs help with Push Button GPIO

Posted: Fri Nov 25, 2016 10:57 pm
by jdb
Hello, and thank you for persevering with Pi.

I think I understand what your button and Python script combo does - unfortunately no simple modification of the script will stop arbitrary shutdowns.

Let's start with some background: the GPIO pins on a Pi are capable of very high-speed operation. If you declare a pin as an input and register an edge-triggered condition on that pin (as the python script does), the edge condition can be registered by even the fastest blip of signal on that pin.

In the python script, the GPIO pin is sampled 250 million times per second by the hardware. If a previously "high" condition (button not pressed) has just two samples of a "low" condition (either button pressed or interference spike) registered then the GPIO pin will register a falling-edge event. This spurious button-press is what's causing your Pi to shut down unexpectedly.

The spurious button-press is caused by electromagnetic interference. When you plug an appliance into a local socket, electrical interference is generated that fools the Pi into thinking that its GPIO pin has been flipped to a low condition for more than a few microseconds.

The correct solution is to add a de-bounce circuit to the GPIO input - this requires at least a resistor and capacitor added to smooth out any interference-generated pulses that could disrupt the button's actual signal.

In absence of hardware mods, you could edit the python script - instead of an "edge" condition, you could register a "level" condition and check it several times before commanding a shutdown - this would filter out any transient levels generated by static discharge or interference.

Re: Mother needs help with Push Button GPIO

Posted: Sat Nov 26, 2016 8:02 am
by dasmanul
How about adding a second callback for GPIO.RISING? You could then just store the current time in your FALLING callback function and in the one for RISING check how long the button was pressed and only call shutdown if it was for at least <n> milliseconds.

Re: Mother needs help with Push Button GPIO

Posted: Sat Nov 26, 2016 11:09 am
by Testamine
Thanks for the help guys! As of now, I see three solutions? Please help me some steps further to my goal, would be fantastic.

1.
The correct solution is to add a de-bounce circuit to the GPIO input - this requires at least a resistor and capacitor added to smooth out any interference-generated pulses that could disrupt the button's actual signal.
I have resistors, but no capacitors.

2
In absence of hardware mods, you could edit the python script - instead of an "edge" condition, you could register a "level" condition and check it several times before commanding a shutdown - this would filter out any transient levels generated by static discharge or interference.
Im a beginner programmer, so maybe you can guide me a little how to edit my script to registrer a "level" condition?

3
How about adding a second callback for GPIO.RISING? You could then just store the current time in your FALLING callback function and in the one for RISING check how long the button was pressed and only call shutdown if it was for at least <n> milliseconds.
How ti I add a callback for GPIO.RISING? Is this a script edit, or do I need to add a ned cable to a new GPIO? Please help.

Again, thanks for helping:)

Re: Mother needs help with Push Button GPIO

Posted: Sat Nov 26, 2016 5:37 pm
by dasmanul
I was thinking of something along the lines of (completely untested!):

Code: Select all

#!/bin/python 

# Simple script for shutting down the raspberry Pi at the press of a button.

import RPi.GPIO as GPIO

import time 

import os


# global variable to remember when the button was pressed
global start
start = None

GPIO.setmode(GPIO.BCM)
GPIO.setup(3, GPIO.IN, pull_up_down = GPIO.PUD_UP)

# function to register when the button was pressed
def buttonPressed(channel):
   start = time.time()

# function to check whether button was pressed long enough when it's released
def buttonReleased(channel):
  # check whether we have a start time and whether it's at least 1/10 of a second ago
  if start and time.time()-start > .1:
     os.system("sudo shutdown -h now")
  else:
     # unset the start time, just to be safe
     start = None

# Add our function to execute when the button pressed event happens 
GPIO.add_event_detect(3, GPIO.FALLING, callback = buttonPressed, bouncetime = 2000)

GPIO.add_event_detect(3, GPIO.RISING, callback = buttonReleased, bouncetime = 2000)


# Now wait! 

while 1: time.sleep(1)

Re: Mother needs help with Push GPIO

Posted: Sat Nov 26, 2016 9:50 pm
by tpylkko
There is another simpler (easier to use) GPIO controlling library called GPIO zero. On their page they have an example for a button that that shuts down the Pi after the power button is held down for certain amount of time. If it is indeed so that the electrical interference is causing a short spike in the gpio state, then this method should be immune to it as it will only function if the change is for a longer duration. The interference spike is likely to be very short, like under one second for sure.

https://gpiozero.readthedocs.io/en/v1.3 ... tml#button

Code: Select all

from gpiozero import Button
from subprocess import check_call
from signal import pause

def shutdown():
    check_call(['sudo', 'poweroff'])

shutdown_btn = Button(17, hold_time=2)
shutdown_btn.when_held = shutdown

pause()

Re: Mother needs help with Push GPIO

Posted: Thu Dec 15, 2016 10:45 am
by Testamine
tpylkko wrote:There is another simpler (easier to use) GPIO controlling library called GPIO zero. On their page they have an example for a button that that shuts down the Pi after the power button is held down for certain amount of time. If it is indeed so that the electrical interference is causing a short spike in the gpio state, then this method should be immune to it as it will only function if the change is for a longer duration. The interference spike is likely to be very short, like under one second for sure.

https://gpiozero.readthedocs.io/en/v1.3 ... tml#button

Code: Select all

from gpiozero import Button
from subprocess import check_call
from signal import pause

def shutdown():
    check_call(['sudo', 'poweroff'])

shutdown_btn = Button(17, hold_time=2)
shutdown_btn.when_held = shutdown

pause()
[/size]

This fixed my problem for the Pi keeps shutting down with electrical spikes!!!! I can now plug stuff inside the socket without the Pie shutting down.

Is it possible to make this work on the same button, just in another setting, so it dosnt start randomly? The electrical spikes also Powers UP my Raspberry from time to time. So to add a delay button to not start the RPi without holding the button for 2seconds?

Re: Mother needs help with Push Button GPIO

Posted: Thu Dec 15, 2016 10:36 pm
by tpylkko
You cannot have software run (python code) on a computer that is turned off. But, what you can do is use a usb cable with a switch, so that after you software shutdown the pi (using the function "shutdown" in your python code), then also flip the switch (or unplug the wire) so that it will not be getting electricity at all. Then when you do want to power on just turn the switch back on.