Shutdown or reset switch


17 posts
by bashhacker » Fri Aug 10, 2012 9:18 pm
I wrote a working yet improvable solution for a reboot or shutdown switch. It works under certain conditions. By that I mean if the system crashes etc. it wont work. The hardware and software cause the system to shutdown "properly" so as to avoid corrupting the file system. I'm using my guy with just a game controller and no network. I thought it would be a good idea to have this. Please let me know what you think ... or better solutions. After googling around I didn't see anything like this but I apologize if this is redundant.

The gist of the script is that it checks the GPIO pin every half second and shuts the system down if the pin goes low. I use an external pullup resistor as I did not want to have to install the wiring library (not that I have a problem with it at all).

The hardware used is a 10k pullup resistor to 3v3 on the header. The other end is connected to GPIO0 (one pin lower). A momentary switch is connected from the GPIO pin to ground. The diagram for the P1 headder and a diagram of how to make the circuit is provided in the wiki.

Here is the script:
Code: Select all
#! /bin/bash

# This script is used to check a pin at half second intervals and
# will shutdown the system if the pin is at a low level.

# Portions of this script adapted from "GPIO Driving Example (Shell script)"
# found on elinux.org .

# Note that the GPIO numbers that you program here refer to the pins
# of the BCM2835 and *not* the numbers on the pin header.
# So, if you want to activate GPIO7 on the header you should be
# using GPIO4 in this script. Likewise if you want to activate GPIO0
# on the header you should be using GPIO17 here.
# GPIO numbers should be from this list
# 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25

## I'm not sure what all that means but using a 0 in this script
## indicates using the pin just next to 3v3 (the not 5v one)

# use GPIO 0 as indicated on the header
# this pin will be used to shutdown the system
PIN_ON_BCM2835="0"

READ_PIN_PATH=/sys/class/gpio/gpio"$PIN_ON_BCM2835"/value

# Set up GPIO 17 and set to input
echo "$PIN_ON_BCM2835" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio"$PIN_ON_BCM2835"/direction

# if the pin exists ...
# if the pin is low do the shutdown command with halt now.
# That is in 0 seconds.
while ( true ); do
        if [ -a "$READ_PIN_PATH" ]; then
                if [ $(<$READ_PIN_PATH) == 0 ]; then
                   shutdown -h 0
                   echo "pin is low"
                fi
        fi
# a small delay
        sleep 0.5
#  for debugging just show the pin value
#  echo $(<$READ_PIN_PATH)
done


in the script that launches this script I have:

Code: Select all
PIN_ON_BCM2835="0"
READ_PIN_PATH=/sys/class/gpio/gpio"$PIN_ON_BCM2835"/value

if [ -e "$READ_PIN_PATH" ]; then
   echo reset already being checked
else
   sudo /home/pi/watch_reset.sh &
fi


one question I have is where to put the second script... I hate to say where I have it now... should it go in /etc/init.d/ ??

I really don't know how that stuff works. Is there a better place to put a script like this... such as in chron @reboot ??

-tldr
Posts: 5
Joined: Fri Aug 10, 2012 1:08 am
by poglad » Tue Aug 14, 2012 12:53 pm
I like this idea. But I don't know enough to answer any of your questions though, sorry! :)
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland
by RaTTuS » Tue Aug 14, 2012 1:13 pm
the script that launches the script should be called from init.d
however
you can get away with putting it in /etc/rc.local
you will need to remove the sudo from that script as rc.local gets run as root ...
in fact in general you should not have
sudo
in a script
as unless it is run as root it will stop and ask for the password - which may be not what your after in general .

as to the method of the main script I'll leave that for others to comment on
http://www.catb.org/esr/faqs/smart-questions.html <- ask smart Questions
"That's not right, the badgers have moved the goalposts."
1QC43qbL5FySu2Pi51vGqKqxy3UiJgukSX - Prosliver FTW
User avatar
Posts: 5339
Joined: Tue Nov 29, 2011 11:12 am
Location: North West UK
by bashhacker » Tue Aug 14, 2012 2:56 pm
Thanks RaTTuS,
I really don't normally put sudo in a script. As you said it's better to do the sudoing outside of the script making it more explicit.

If I put the script that launches the script in init.d do I have to do all that fancy stuff with the skeleton file?
And then add a link in the right folder for the right runlevel. I guess if I was going to put it in there what would I put in
Code: Select all
Required-Start
.

I should probably follow something like this: http://www.debian-administration.org/articles/28

Does putting it in /etc/rc.local make things easier? I'd rather do it properly than easily..

poglad, once I get it worked out I'll put up the files I modified.
Posts: 5
Joined: Fri Aug 10, 2012 1:08 am
by cyberhedz » Sun Aug 26, 2012 3:26 am
Just curious if you managed to get this working or not. I'm in a similar situation and am trying to avoid using a switch to cut the power as I would actually need a DPDT. one downside I've found to the pi pcb, if you have a powered hub, you better make sure that the pi is powered first, or you'll never boot. makes resetting a pain since I now have to cut power to the hub AND the pi with the reset condition.
Posts: 3
Joined: Wed Aug 08, 2012 1:14 pm
by bashhacker » Sun Aug 26, 2012 5:31 am
It works great as far as the hardware, and the software end works as well. Right now I do not have the script running in a "according to the right way to do things" way. I actually have the chunk of code that launches the script stuffed in my .bashrc ... ok there, I said it. Feel fre to tell me that it's not the right way and not what the bashrc is for.. I know but I just wanted to try it.

The launcher script should go in the init.d. I've just never messed with that stuff. And, I have not had time to go back to it. The principle is that you pole the pin and when it changes you can do whatever you want it to, for example shutdown. Or, really anything. So, yes it works. No, I have not gone back and put the script in the right place.
Posts: 5
Joined: Fri Aug 10, 2012 1:08 am
by Dweeber » Mon Sep 03, 2012 4:07 pm
Init.d script could look like (using your location and pi as the user)

Code: Select all
#!/bin/sh

### BEGIN INIT INFO
# Provides:          watchreset
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Should-Start:      $all
# Should-Stop:       $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/stop watchreset
# Description:       Start/stop watchreset
### END INIT INFO

# /etc/init.d/watchreset

PIN_ON_BCM2835="0"
READ_PIN_PATH=/sys/class/gpio/gpio"$PIN_ON_BCM2835"/value

case "$1" in
    start)
        if [ -e "$READ_PIN_PATH" ]; then
            echo "WatchReset is already running"
        else
            su pi -c '/home/pi/watch_reset.sh &'
            echo "Starting WatchReset Looking at Pin $PIN_ON_BCM2835 "
        fi
        ;;
    stop)
        pkill watch_reset.sh
        echo "WatchReset Stopped"
        ;;
    *)
        echo "Usage: /etc/init.d/watchreset {start|stop}"
        exit 1
        ;;
esac
exit 0

Don't really need to do the su pi stuff, could just run it as it would (as root).

Just sticking it into /etc/rc.local works too. This just runs as root, no su to pi needed...
Code: Select all
####################
PIN_ON_BCM2835="0"
READ_PIN_PATH=/sys/class/gpio/gpio"$PIN_ON_BCM2835"/value
if [ -e "$READ_PIN_PATH" ]; then
  echo "WatchReset is already running"
else
  /home/pi/watch_reset.sh &
  echo "Starting WatchReset Looking at Pin $PIN_ON_BCM2835 "
fi
#####################

Insert it before the last exit 0 in the /etc/rc.local script that is already there.

Not having much background in electronics, I'd be interested in what parts you used to connect to the GPIO pins. Getting a momentary switch is easy. Is a 10k pullup resister the same thing as a 10k resister? I know the layout of the GPIO pins, but what are you connecting to what (ground etc..).
Dweeber A.K.A. Kevin...
My RPI Info Pages including Current Setup - http://rpi.tnet.com
User avatar
Posts: 606
Joined: Fri Aug 17, 2012 3:35 am
Location: Mesa, AZ
by bashhacker » Tue Sep 04, 2012 3:49 am
A pull up resistor is just a regular resistor. The "pull up" part just gives an indication to the function.

It is used when you have a signal that is created by ether grounding or not grounding some other thing. The resistor is connected to a higher voltage and the terminal that will be either grounded or not. You then take measurements at the maybe grounded may be not end of the resistor. If the end is grounded then you get 0 volts, and if it's not grounded then there will be no current flowing in the resistor, resulting in no voltage drop across the resistor, meaning that the measurement would show the higher voltage.

The connector used would be called a 2 by n female header. Where n is the number of pins in each row.

I physically tore out the pin on the female header that connected to the 5v supply just to make sure it would not short to anything.

some ting like this: http://www.pololu.com/catalog/product/1026

Thanks for all the tips everyone. I'd say it's pretty solved as far as the method described.
Posts: 5
Joined: Fri Aug 10, 2012 1:08 am
by Dilligaf » Tue Sep 04, 2012 4:48 am
Great idea!!! As far as connectors most all PC enthusiasts have old cd audio jumpers, or fan connectors or a multitude of other assorted jumpers with connectors on the end most of which have the needed pin spacing for connecting to the gpio header so if one is looking to perform this mod you should have the needed connectors in the junk drawer. If you are serious about using the gpio and plan on using multiple pins then it would be wise to invest in a 2x13 or whatever connector and terminals
Posts: 283
Joined: Wed May 23, 2012 6:48 pm
by kilokahn » Sun Sep 09, 2012 3:46 am
I would love to learn more on what it would take to make this work!

Do I need a circuit or do I just touch 2 pins together? And if so, for how long of a push will "shutdown" be and how would I start it again? My only concern is people may bump this button, so it would have to be countersunk.

Anyone have pictures of what they did? I am really curious because I want to do this on mine.

Chris
Chris Haslage, Owner
NexMix.com Productions
Posts: 21
Joined: Sun Sep 09, 2012 3:41 am
Location: Tallmadge, OH, USA
by kilokahn » Sun Sep 09, 2012 6:05 pm
Hrm... I just saw Revision 2 of Model B: http://www.raspberrypi.org/archives/1929

Looks like a reset switch is already in place, though no easy shutdown solution. This is curious. I have a Revision 2 board coming in the next few days, I am truly curious if this is a good solution or the switch idea above or both even?
Chris Haslage, Owner
NexMix.com Productions
Posts: 21
Joined: Sun Sep 09, 2012 3:41 am
Location: Tallmadge, OH, USA
by Dweeber » Sun Sep 09, 2012 6:19 pm
My new RPi that showed up was not a Rev 2 board, but instead a ECN0003 (Rev2 starts at ECN0004)... little disappointed as the mounting hole would have been useful. Will need another board soon, so hopefully the next one will be.

As for the reset switch.... its not clear to me if this is something that you can then detect the state with some software and then do what you want to do or if it just causes a hardware reset which would be similar to pulling the plug.

I'm not clear what will cause the BCM2835 to reset means. I'm sure someone will chime in though.
Dweeber A.K.A. Kevin...
My RPI Info Pages including Current Setup - http://rpi.tnet.com
User avatar
Posts: 606
Joined: Fri Aug 17, 2012 3:35 am
Location: Mesa, AZ
by TarjeiB » Thu Sep 13, 2012 12:32 pm
The script is excellent, Thanks!
I'm considering using it for my project, but I may also just put in simple bash scripts in cron: @boot to set the pin up ready for input, and then checking every minute (*****) if it's on, if not run shutdown. It sort of feels safer to use cron than to start a script from rc.local that may die in some way.
Posts: 130
Joined: Thu Jul 12, 2012 3:33 pm
by TarjeiB » Tue Sep 18, 2012 9:58 am
Here's my own stripped, mangled and simplified solution:

Root's crontab:
Code: Select all
@reboot gpioenable.sh
* * * * * lightsensor.sh


gpioenable.sh:
Code: Select all
#!/bin/bash
/usr/local/bin/gpio mode 4 in
/usr/local/bin/gpio mode 4 down # making sure GPIO is 0 when not getting a signal


lightsensor.sh:
Code: Select all
#!/bin/bash
gpio4=`/usr/local/bin/gpio read 4`
if [ "$gpio4" -eq "0" ]; then
  logger GPIO 4 is $gpio4, shutting down!
  shutdown -h now
fi


Takes up to a minute for shutdown to trigger, but that is more than sufficient for me (I have 5 minutes after "GPIO 0" before power is gone).
Posts: 130
Joined: Thu Jul 12, 2012 3:33 pm
by Badger101 » Mon Oct 01, 2012 1:29 pm
Hi,

This is a good script for shutting down the RPi.

I would like to use it in Openelec's version of XBMC, does anyone know how to do this?

Thanks,
Badger.
Posts: 16
Joined: Tue Jun 12, 2012 1:26 pm
by Dweeber » Sun Oct 21, 2012 5:54 am
TarjeiB wrote:
Code: Select all
#!/bin/bash
/usr/local/bin/gpio mode 4 in
/usr/local/bin/gpio mode 4 down # making sure GPIO is 0 when not getting a signal

Where are you getting the gpio command in /usr/local/bin from?
Dweeber A.K.A. Kevin...
My RPI Info Pages including Current Setup - http://rpi.tnet.com
User avatar
Posts: 606
Joined: Fri Aug 17, 2012 3:35 am
Location: Mesa, AZ
by TarjeiB » Tue Oct 23, 2012 9:41 pm
Dweeber wrote:
TarjeiB wrote:
Code: Select all
#!/bin/bash
/usr/local/bin/gpio mode 4 in
/usr/local/bin/gpio mode 4 down # making sure GPIO is 0 when not getting a signal

Where are you getting the gpio command in /usr/local/bin from?

That is from Gordons most excellent program wiringPi.
Posts: 130
Joined: Thu Jul 12, 2012 3:33 pm