Raspberry Pi, Arduino, Sensors and the data they produce

Shutdown the OS using an OSEPP button


This page presents a program that shuts down the OS when a button is pressed. The narrative is more about the problems associated with normally open button circuits and how they are managed using edge detection techniques.


Presented below is the program called Powerdown.py. This program should run as a service to be useful. Use your favorite method, but I have found that Supervisor is useful. I have not used other techniques and I have questions about how they mitigate the problem associated with the program’s references to modules during the time in which the program initializes.

The program name might suggest it is capable of actually powering down the Pi, but it is executed as a prelude to pulling the power cord.

The actual goal of this program is to shut down the operating system without the obligation of opening a putty session to issue the “sudo shutdown -h now” command before pulling the power plug. Powerdown.py works with a OSEPP button with its signal wire connected to GPIO pin number 7. The voltage wire is connected to 5v and the ground wire goes to ground. The voltage wire could also have been connected to the 3.3v pin, but for no reason whatsoever, the 5v pin was chosen.

The OSEPP button was chosen for this task because is is a self contained PC module that contains a resistor, so we don’t need to go to the trouble of soldering a circuit of our own.


The button’s schematic:

This OSEPP tutorial talks about the problems associated with normally open buttons. The relevant excerpt is below.

By default, the tact switch is an open circuit, so the electrical current would flow from the 5V power supply to the D12 pin. The amount of current flowing into the digital pin is very low because the input pin is a CMOS input. (This current is referred to as a Cgs leakage current and typically in the μA range.) Because there is very little current flow, the voltage drop across the 10kohm resistor will be close to 0V. If you measure the voltage at the input pin, you should see a 5V. When the tact switch is pressed, a short circuit will form and the digital input pin will be grounded. If you measure the voltage on the input, you should see a 0V.

Useful Note: The resistor on this circuit is to prevent the 5V from shorting to ground when the tact switch is pressed. With a 10kohm resistor you will only be sinking 0.5mA of current from the power supply. If you use a resistor with very low resistance, you could over load and damage the power supply.

Another interesting article about edge detection.

It has been noted that when the button is pressed the buttonPushed() function is called twice. Although probably not necessary for this purpose, logic was provided to prevent the call to the shutdown command from occurring twice.

Other techniques could be employed here such as rewriting the function to simply wait for the digital 0.

try: GPIO.wait_for_edge(gpio_pin_number, GPIO.FALLING) #Use falling edge detection to see if pin is pulled #low to avoid repeated polling os.system("sudo shutdown -h now") #Send command to system to shutdown except: pass

Testing of the method above is required, but for now, the program below does the job. Improvements to PowerDown.py will be coming in the future.


#!/usr/bin/python #********************************************************************** # Program : PowerDown.py # Date : 20160716 # #********************************************************************** import os import sys import platform import time import datetime from datetime import datetime import RPi.GPIO as GPIO #********************************************************************** #***** VARIABLES ***** #********************************************************************** progName = os.path.basename(__file__) # Full path of this python script mypath=os.path.abspath(__file__) # Path location only (excluding script name) baseDir=mypath[0:mypath.rfind("/")+1] baseFileName=mypath[mypath.rfind("/")+1:mypath.rfind(".")] BUTTON_SHUTDOWN = 7 shutdownRequested = False #======================================== # GPIO Prep #======================================== GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) GPIO.cleanup() GPIO.setup(BUTTON_SHUTDOWN, GPIO.IN) #********************************************************************** #***** FUNCTION DECLARATIONS ***** #********************************************************************** #---------------------------------------------------------------------- def myFunction(): print "Entered myFunction()" return; #---------------------------------------------------------------------- # This function accepts a value to be compared with the low and high # values that are also provided. These values are expressed as integers # and if the value (the first parameter) falls between the low and high # values (inclusive), True will be returned, otherwise False. #---------------------------------------------------------------------- def inRange(value, low, high): intVal = int(value) intLow = int(low) intHigh = int(high) if intLow <= intHigh: return intLow <= intVal <= intHigh else: return intLow <= intVal or intVal <= intHigh #---------------------------------------------------------------------- def buttonPushed(): global shutdownRequested buttonPushed = GPIO.input(BUTTON_SHUTDOWN) if(buttonPushed == 0 and shutdownRequested == False): #print("Pushed - shutdown starting") shutdownRequest = True os.system('shutdown now -h') #At this point, observe green lights on board. #When it stops, pull the power plug. Done. return #---------------------------------------------------------------------- def execute(): GPIO.setup(BUTTON_SHUTDOWN, GPIO.IN) while True: buttonPushed() return #********************************************************************** #***** M A I N L I N E C O N T R O L L E R ***** #********************************************************************** if __name__ == '__main__': print("+++++++++++++++++++++++++++++++++++") print("%s - Entering Program" % progName) print "Path to program = " + mypath print sys.version_info print "The O/S = " + platform.system() try: execute() finally: print("%s - Exiting Program" % progName) print("+++++++++++++++++++++++++++++++++++") print("") #********************************************************************** #********************************************************************** #***** E N D O F S O U R C E ***** #********************************************************************** #**********************************************************************



Adding a switch to power down

Source code using edge detection

Pi Supply Switch v1.1 Code Examples

A good tutorial on button events, call backs pull up and pull down resistors. It’s all about GPIO pins 23 and 24. The Raspberry Pi has internal pull-up and pull-down resistors that can be specified when the pin declarations are made.


Configuring pullup and pulldown resistors

On the Raspberry Pi, most GPIOs have either their pull-up or pull-down resistor activated by default. The defaults can be seen in Table 6-31 on pages 102 and 103 of the BCM2835 ARM Peripherals documentation.

Pullup and pulldown resistors for GPIOs can be configured with device tree overlays. The Wiki page Enabling Pullup and Pulldown Resistors on The Raspberry Pi describes how this can be acheived on the Raspberry Pi.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: