FamiPi Power Switch and shutdown handling: Part 1

Home / Projects / FamiPi Power Switch and shutdown handling: Part 1

Below is the start to my arduino nano based power circuit for Famicom based retro pie build.
The goal of this Arduino sketch is to detect when the Super Famicom power switch state has changed and either power on the Rpi3 or tell the Rpi3 to shutdown and then  remove power from the Rpi3 circuit. To accomplish these goals I would like it to do the following:

  1. Graceful shutdown of Rpi after power switch is turned off.
    • Serial Communication between Rpi and Arduino over I2C to initiate and confirm shutdown.
  2. Power on of Rpi without touching the power cable.
  3. Illumination of the Power LED.

Arduino Sketch:


const int switchPin = 2; // pin the SNES power switch is connected to
const int powerLedPin = 13; // pin the SNES power LED is connected to
const int mainPowerRelayPin = 6; // pin for the 5V relay that provides power to the Rpi
const int piStatusPin = 7; // pin for telling the pi when it is time to shutdown (shutdown = 0, run = 1)

int switchState = 0; // SNES power switch state
int switchStatePrevious = 0; // Previous state of power switch

void setup() {
 pinMode(switchPin, INPUT); // initialize the SNES power switch pin
 pinMode(powerLedPin, OUTPUT); // initialize the SNES power LED pin
 pinMode(mainPowerRelayPin, OUTPUT); //initialize Relay pin
 digitalWrite(mainPowerRelayPin, HIGH); //Set relay to High as it triggers low
 pinMode(piStatusPin, OUTPUT); //initialize Pi status pin

 Serial.begin(9600); // initialize serial
}


void loop() {
 switchState = digitalRead(switchPin); // check the state of the SNES power switch

 //Check to see if the state of the power switch has changed
 if (switchState == switchStatePrevious) {
 Serial.print("-"); 
 } 
 
 //If the Power switch state has changed and the new state is HIGH, start the power on procedure
 else if ( switchState != switchStatePrevious && switchState == HIGH){
 powerOn(); 
 } 
 
 //If the Power switch state has change and the new state is LOW, start the power off procedure
 else if ( switchState != switchStatePrevious && switchState == LOW){
 powerOff();
 }
 
 switchStatePrevious = switchState;
 delay(1000);
}

//Power On
//Turn on power LED
//Switch on power relay to provide power to Rpi and logic converter
void powerOn(){
 pinHigh(powerLedPin);
 pinHigh(piStatusPin);
 pinLow(mainPowerRelayPin);
 
}

//Shutdown function
//Turn off power LED
//Wait 30 seconds for Rpi to shutdown and then switch of Relay
//TODO: replace delay with confirmation of shutdown from Rpi using Serial
void powerOff(){
 pinLow(powerLedPin);
 pinLow(piStatusPin);
 delay(10000); //TODO: change from test time of 3sec to 30
 pinHigh(mainPowerRelayPin); 
}

//Move a pin to high and output that change to serial
void pinHigh( int pin){
 digitalWrite(pin, HIGH);
 Serial.print(pin);
 Serial.println(" switched to HIGH");
}

//Move a pin to low and output that change to serial
void pinLow( int pin){
 digitalWrite(pin, LOW);
 Serial.print(pin);
 Serial.println(" switched to LOW");
}

 

The following python script will need to be placed on the Raspberry Pi. I recommend placing it in /home/pi/Scripts/, you may have to create the Scripts folder if you have not already done so.
This script will detect when a GPIO pin which is pulled low, is instead high. Once this state is detected the shutdown command will be run.

#!/bin/python  
# Configure Rpi to check if the GPIO pin for shutdown is high, if so, shutdown the Rpi.
  
import RPi.GPIO as GPIO  
import time  
import os  

int shutdownPin = 23

# Setup  shutdownPin with pull DOWN enabled.  
GPIO.setmode(GPIO.BCM)  
GPIO.setup(shutdownPin, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)  
 
# Gracefully shutdown when shutdownPin is HIGH
def Shutdown(channel):  
    os.system("sudo shutdown -h now")  
 
# Detect when shutdownPin goes high, and run the shutdown function
GPIO.add_event_detect(23, GPIO.RISING, callback = Shutdown, bouncetime = 2000)  
 
# Sleep thread so that shutdownPin is only checked once a second 
while 1:  
    time.sleep(1)

With the script tested and working on the Rpi, we need to make sure it runs at startup. To do this we will need to add a line to /etc/rc.local.
The easiest way to do this is with nano using the command

sudo nano/etc/rc.local

The following line will needed to be added before “fi”

sudo python /home/pi/Scripts/shutdown_pi.py &

Be sure to include the ampersand at the end. This forks the process which is important as this script will be running continuously until shutdown.

In Part 2 we will test the code above on the hardware side.

Leave a Reply

Your email address will not be published. Required fields are marked *