BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

DIY PiSwitch - switching AC gracefully on and off

Tue Nov 19, 2013 7:19 pm

Since May I'm a proud owner of a Pi. As a first project I've installed RaspBMC on it and use it as a media center. One thing which I was annoyed with, was that after shutting the Pi down, it was still powered (and using the same amount of energy when idling). So I went back to my trustworthy Arduino for making a prototype for the AC Switch.

Requirements:
- 1 button operation (on, shutdown and force power-off);
- cutting AC lines, not the USB cable to prevent the adapter to be energized (the adapter would most likely cost more energy than a Pi idling);
- being able to also cut-off power to amplifier on shutdown.

In this series I want to display the system I've designed. The 'orignal' name of my project was PiPower, unfortunately more people have been building power-supplies for the Pi, so this name was recently already used by another user here http://www.raspberrypi.org/phpBB3/viewt ... 45&t=37459. I don't want to claim any name.

BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Tue Nov 19, 2013 10:08 pm

Schematics

The heart of the switch is an AtTiny45. This choice comes from my experience with the Arduino:
- it can be simulated with an Arduino;
- it is easily programmed with an Arduino.

Image

The AtTiny works directly from 5V. A level converter (schematic on the right side) converts between the 5V logic of the AtTiny and the 3.3V logic of the Raspberry. The AtTiny runs also perfectly fine on 3.3 V. One can consider drawing the 3.3V from the GPIO header and run this whole circuit on 3.3 V, saving the level converter.

Because the circuit switches off the AC there is no power to start the circuit. There are two options:
1) have a switch in the main line (220V);
2) at a battery to start the relay.

I've chosen for the second option for the purpose of safety. It just didn't feel well to combine high voltage and logic levels within one switch. The set-up also allows for future upgrades (monitoring the mains)

Code AtTiny45
Below is the code which is programmed in AtTiny. Basically what it does:
- setting the pin connected with the Pi as input (normally floating high);
- setting the pin connected with the SS relay as output and high (thus enabling the relay);
- setting the pin connected to the switch as input (normally pulled low).

A low signal from the Pi means that the Pi has been shutdown. A high signal on the button means the button has been pressed:
- when off => start the circuit;
- when on, and pushed shortly => the pin connected to the Pi is set as output (temporarily) and set Low. This indicates the Pi that it should turn itself of;
- when on, and pushed long => disable the SS relay and do a hard power down.

Code: Select all


//Pin declaration
const int pinButton = 3;     // the number of the Pushbutton pin
const int pinSSRelay = 4;
const int pinPi = 0;

//Configuration
const int AUTOPOWERON = 1;           // this value indicates that the circuit will power the relay immediately when it is powered
const long PISTARTUPTIME = 500;      // the time it takes the Pi to start up and apply a high voltage to the pinPiIn.
const long PISHUTDOWNTIME = 10000;   // the time the system keeps powered on while the Pi pulls the GPIO pin low. Should be long enough to stop the Pi and let it be able to reboot.
const long HARDPOWEROFFDELAY = 4000; // the time it takes the Pi to start up and apply a high voltage to the pinPiIn.

// Global variables will change:
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin. A LOW value means thae button is not pressed.
int lastPiState = HIGH;      // the previous reading from the Pi

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;      // the last time the output pin was toggled
long lastPiShutDownRequest = 0; // the last time the Pi requested for shut down
long debounceDelay = 50;        // the debounce time; increase if the output flickers


void setup() {
  //Set pin modes
  
  pinMode(pinButton, INPUT);
  pinMode(pinSSRelay, OUTPUT);
  pinMode(pinPi, INPUT);
  
  //Disable the internal pull-up resistor on the button
  digitalWrite(pinButton, LOW);
  digitalWrite(pinPi, HIGH);
    
  //When it is power on when power has been supplied to this circuit,
  //enable the relay by writing a high value to the relay pin. Other 
  //behavior to be implemented
  if (AUTOPOWERON == 1) {
    digitalWrite(pinSSRelay, HIGH);
  }
  
  //Let the Pi start up and be able to supply a high voltage to the pin
  delay(PISTARTUPTIME);
  
}

void loop() {
  
  //Read the state of the switch into a local variable:
  int reading = digitalRead(pinButton);

  //Check to see if you just pressed the button 
  //(i.e. the input went from LOW to HIGH),  and you've waited 
  //long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // Reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  // Check whether press has been long enough to change the state of the button
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
  
  // When the button is pressed, shut down the Pi gently by pulling the PiPinOut to the ground
  if (buttonState == HIGH) {
    digitalWrite(pinPi, LOW);
    pinMode(pinPi, OUTPUT);
    delay(500);
    pinMode(pinPi, INPUT);
    digitalWrite(pinPi, HIGH);
  }
  
  // When the button is pressed very long, shut down the by killing the supply
  if ((buttonState == HIGH) && ((millis() - lastDebounceTime) > HARDPOWEROFFDELAY)) {
    digitalWrite(pinSSRelay, LOW);
  }
  
  // Save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
  
  
  //Listen to the Pi whether it indicates whether the power can be turned off
  int piReading = digitalRead(pinPi);
  
  // A low value of the PiInPin means the Pi wants to be shut down
  if ((lastPiState != piReading) && (piReading == LOW)) {
    lastPiShutDownRequest = millis();
  }
  
  if ((piReading == LOW) && ((millis() - lastPiShutDownRequest) > PISHUTDOWNTIME)) {
    digitalWrite(pinSSRelay, LOW);
  }
  
  // Save the PiState.  Next time through the loop,
  // it'll be the lastPiState:
  lastPiState = piReading;  
  
}
To be continued
Tomorrow I'll continue with the code which is running on the Pi which listens to the Pi Switch

BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Wed Nov 20, 2013 8:49 pm

Code Pi
The Pi runs on RaspBMC, which uses UpStart. This code should work for all distros using UpStart. The code consists of:
1. a Python script listening for a falling edge on GPIO4, indicating to shutdown;
2. a Python script which is started when the Pi is shutting down, pulling the GPIO4 low and thus killing the AC;
3. an UpStart script which starts the Python scripts.

1. Python script SoftShut.py
The goal of the script is:
- to set up the GPIO pin as input;
- define a function which is called when the falling edge is detected, in this case calling the shutdown;
- wait for the falling edge.

This script is based on the PiSupply script found here.

Code: Select all

# Pi Supply Soft Shutdown Script
# Version 1.1
# Original by Natham Bookham 2013
# Adapted for PiSwitch

# PiPower is a adaptation of the PiSupply, which includes the
# following features:
# - single button start up, soft shutdown and hard shutdown
# - completely cuts main to prevent leakage of currents
# - uses a 3V battery to restart the adapter

# The PowerPi uses GPIO4 to communicate to the PiPower module. The GPIO4
# pin is located on pin 7 of the GPIO bus.

# Import the modules to send commands to the system and access GPIO pins
from subprocess import call
try:
        import RPi.GPIO as gpio
except RuntimeError:
        print("Error importing Rpi.GPIO! Did you use sudo?")

# Define a variable to store the pin number
soft_shutdown_pin = 7

# Define a function to run when an interrupt is called
def shutdown():
        call('sudo halt', shell=True)

# Set pin numbering to board numbering
gpio.setmode(gpio.BOARD)
# Set up pin 7 as input and enable pull-up resistance
gpio.setup(soft_shutdown_pin, gpio.IN, pull_up_down=gpio.PUD_UP)

# Wait for input from button
gpio.wait_for_edge(soft_shutdown_pin, gpio.FALLING)

#Run the whutdown function (the edge has been detected)
shutdown()
2. Python script ShutDownAC.py
The goal of the script is:
- to set up the GPIO pin as output;
- pull it low to signal the PiSwitch.

Code: Select all

# PiSwitch is a adaptation of the PiSupply, which includes the following features:
# - single button start up, soft shutdown and hard shutdown
# - completely cuts main to prevent leakage of currents
# - uses a 3V battery to restart the adapter

# The PiSwitch uses GPIO4 to communicate to the PiPower module. The GPIO4
# pin is located on pin 7 of the GPIO bus. This script turns the GPIO4
# to output and set it low to shutdown the AC

# Import the modules to send commands to the system and access GPIO pins
from subprocess import call
try:
        import RPi.GPIO as gpio
except RuntimeError:
        print("Error importing Rpi.GPIO! Did you use sudo?")

# Define a variable to store the pin number
soft_shutdown_pin = 7

# Set pin numbering to board numbering
gpio.setmode(gpio.BOARD)
# Set up pin 7 as input and enable pull-up resistance
gpio.setup(soft_shutdown_pin, gpio.OUT)

# Write a low to indicate that the AC can be shutdown
gpio.output(soft_shutdown_pin, gpio.LOW)
UpStart .conf file
Goals of the UpStart file are:
- starting script 1 on startup (entering runlevel 2, 3, 4 and 5);
- stopping script 1 on stop (entering runlevel 0 or 6, respectively halt and reboot). When script 1 is being stopped, script 2 is being started. In case of reboot the delay in cutting the AC is long enough for the Pi to reboot and pull the GPIO4 pin back high.

Code: Select all

description "PiPower shutsdown listens to GPIO4 for a negative edge and shutsd$
author "BAKBoord, 2013"
version "0.1 Test version"

start on runlevel [2345]
stop on runlevel [06]

pre-stop script
     #sudo touch /home/pi/PiPower/testShutDown
     python /home/pi/PiPower/shutdownAC.py &
end script

expect fork
exec python /home/pi/PiPower/softshut.py &

BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Wed Nov 20, 2013 9:10 pm

Conclusion
The scripts in combination with the electronics work fine. When calling 'halt' from the shell the AC is killed. When shutting down the Pi from RaspBMC the power is not shutdown. One way or the other, quitting RaspBMC does not put the Pi in runlevel 0. Can somebody verify this? I cannot SSH to the Pi anymore when shutdown from RaspBMC.

The solution I'm now seeking in adapting the action when clicking the Shutdown button in the Confluence skin, as described here. However, this is not my preference :(. Advise is welcome.

Costs
The total costs for the project were:
- AtTiny45, €1.25;
- 39MF22 (solid state relais), €1.80;
- AC switch, on(I)-off-on(II), €1,60;
- resistors, €0.10 each, total €0.40;
- CR2032-battery €0.55;
- CR2032-holder €0.55;
- pushbutton, normally open, free (scavenged);
- diode, LED, free (scavenged);
- adapter, an old IPhone 1A 5V adapter scavenged from a way too old 3G;
- an old piece of experimental PCB, scavenged.

Total: €6.15. Above prices are Dutch prices. It has been told that components are relatively expensive here.

User avatar
redhawk
Posts: 3465
Joined: Sun Mar 04, 2012 2:13 pm
Location: ::1

Re: DIY PiSwitch - switching AC gracefully on and off

Wed Nov 20, 2013 9:22 pm

I can't comment on RaspBMC shutdown behaviour but if you perform a reboot this should cause GPIO 4 to go low momentarily before the Pi starts up again.

Richard S.

hippy
Posts: 8230
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: DIY PiSwitch - switching AC gracefully on and off

Thu Nov 21, 2013 5:03 pm

Can you clarify the AC In / S2 / U1 / J1 configuration and operation. It doesn't make a lot of sense to me.

I would also suggest including the obligatory warning on working with mains and the need for safety and safe working practices.

BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Fri Nov 22, 2013 8:51 pm

@Redhawk
If it turns out that the GPIO pins are pulled low after shutdown, the second Python script is not necessary. However, I did not notice the GPIO line to go low, because without the script the switch didn't turn off. Please feel free to experiment and make improvements!

@hippy
Yeah, you're right that I'm working with AC. People should know what they are doing, have proper residual-current device installed, and off-course don't touch the wrong parts when they are powered. By not doing so, it can do severe harm or cause death. If there is a standard text for the obligatory warning, please let me know where to find it and I'll add it.

The switch is a three way switch:
- 0 (off)
- I (the adapter is powered through the PiSwitch)
- II (the adapter is powered directly, the PiSwitch is surpassed)

I have used this switch to be able to surpass the PiSwitch without removing or changing wires. This becomes handy for example when the battery runs out (that only happens after more than 80 hours of continuous pressing, so it is not very likely), or when you want to test scripts with in which the PI is shutdown/restarted frequently and you don't want the power to be cut.

hippy
Posts: 8230
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: DIY PiSwitch - switching AC gracefully on and off

Sat Nov 23, 2013 11:25 am

BAKBoord wrote:The switch is a three way switch:
I still don't understand. S2 is shown as a DPDT switch, which seems to switch both Live and Neutral, with the opto's transistor bridging one set of contacts.

I am guessing S2 is actually a SSR but that's not how it's shown and the circuit for an SSR doesn't seem to be correct but perhaps I am being confused because it's shown as a DPDT switch.

User avatar
redhawk
Posts: 3465
Joined: Sun Mar 04, 2012 2:13 pm
Location: ::1

Re: DIY PiSwitch - switching AC gracefully on and off

Sat Nov 23, 2013 3:48 pm

I'm not sure why you're using a AtTiny45 the circuit looks a little overly complicated for what's required.
I built a similar circuit not so long ago since I needed the Pi active at certain times of the day and when I phone home via my land line (for ssh proxy access while on holiday). :)
I used an old Micromark timer switch from Argos for this task with some modifications but I'm guessing all digital timer switches work on the same design.

The timer circuit comes in 2 parts: the timer board with 3 wires +vcc, ground, and signal, and the relay circuit board which turns on / off via the signal wire.
For my modification I simply tapped into the signal wire with a resistor and an opto-coupler, the LED side of the opto-coupler was then driven by the Pi's GPIO 4 line via a load resistor (or with my phone ring detection circuit).
When the opto coupler is active the relay stays on whether the timer circuit was off or on, that is until the Pi has shutdown or rebooted and GPIO 4 goes low.

If you still stuck with your original problem then perhaps you could hack up and old timer switch with a built in relay driver.

Richard S.

hampi
Posts: 223
Joined: Fri May 31, 2013 11:29 am
Contact: Website

Re: DIY PiSwitch - switching AC gracefully on and off

Sat Nov 23, 2013 4:11 pm

Since the circuit has some similarity to what I am doing: I am switching the LM2576 regulator on/off with a transistor 2N3904. See the circuit diagram

https://github.com/oh7bf/RaspiPwr12V/bl ... pwr12V.pdf

BAKBoord
Posts: 7
Joined: Tue Nov 19, 2013 7:05 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Sat Nov 23, 2013 9:13 pm

@hippy
I think I've made a mistake in the drawing.. my English is also playing part here. You put me on the right track with DPDT, but that is not the part which I meant in the drawing. It should be a DPCO, or a on-off-on switch. One of the on-states lets puts the PiSwitch in series, the other state means the PiSwitch is bypassed. I'll update the scheme a little later.

@redhawk
The AtTiny45 is a cheap micro-processor, which I have loads off in my inventory. Maybe it is a little overkill for this application, but I still want extend the design so it can also shut down my amplifier, powered USB-hub when they are not needed. If you have some part-numbers of the timer circuit you used, I can dig in the datasheets and get used to that part.

wbrells
Posts: 4
Joined: Thu Jan 23, 2014 1:01 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Thu Jan 23, 2014 1:12 pm

Folks,

I notice that this device was designed for XBMC running on the Raspberry Pi. However, I'm running the latest Raspbian version of Wheezy and wondered if the same Python code could be used to drive the PiSwitch on THAT operating system? (Sorry to say, but I'm a Python novice!) [I'm using Squeezelite on a Raspberry Pi to drive a small audio system & would like to automatically turn the amplifier ON and OFF along with the RPi.]

Thanks,
Wayne

User avatar
Jufo
Posts: 25
Joined: Fri May 23, 2014 11:49 am
Location: Warsaw, Poland
Contact: Website

Re: DIY PiSwitch - switching AC gracefully on and off

Sun Aug 17, 2014 2:34 pm

How to add into script unmount /boot for safely shutdown hardware ?

ShutdownAC.py:

Code: Select all

from subprocess import call
import RPi.GPIO as gpio

call('umount /boot', shell=True)
gpio.setmode(gpio.BOARD)
gpio.setup(7, gpio.OUT)
gpio.output(7, gpio.LOW)
Working only an option halt ?

upstart.conf:

Code: Select all

start on runlevel [2345]
stop on runlevel [0]

pre-stop script
     python /home/pi/PiPower/shutdownAC.py &
end script

expect fork
exec python /home/pi/PiPower/softshut.py &
softshut.py:

Code: Select all

from subprocess import call
import RPi.GPIO as gpio

def shutdown():
    call('halt', shell=False)

gpio.setmode(gpio.BOARD)
gpio.setup(7, gpio.IN)
gpio.wait_for_edge(7, gpio.RISING)
shutdown()
Best Regards
Robert

bennybubble
Posts: 10
Joined: Thu Feb 09, 2012 2:12 pm

Re: DIY PiSwitch - switching AC gracefully on and off

Thu Jan 08, 2015 8:06 pm

Hello Robert,

I'm trying to install the python code, can you be more precise on the fact in which directory etc all the code is installed and with which privileges ?

Tia!

-ben

meigrafd
Posts: 97
Joined: Tue May 29, 2012 9:28 am
Location: Germany

Re: DIY PiSwitch - switching AC gracefully on and off

Wed Nov 18, 2015 8:24 pm

Hello.

I have a Problem with circuit from here: http://www.mosaic-industries.com/embedd ... controller
It looks similar like this here..

My Problem is that the Raspberry turns back on after it was shutdown. First it looks great, pressing the Switch turns on the Pi. After the Pi is booted and i hit the Switch again it shutdown and turns off the Power. But after about 5 sec. the circuit turns back on Power :?

Im using Rasbian Jessie with systemd and following Scripts:

/etc/systemd/system/pipower.service

Code: Select all

[Unit]
Description=turn off AC Power after Shutdown
DefaultDependencies=no
Conflicts=umount.target
#Before=umount.target shutdown.target halt.target poweroff.target
Before=umount.target
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
StandardOutput=syslog+console
StandardError=syslog+console
ExecStart=/usr/bin/python3 /usr/local/sbin/shutdown.py 4
ExecStop=/bin/bash /usr/local/sbin/pipower.sh 4
/usr/local/sbin/shutdown.py

Code: Select all

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# script v0.3 by meigrafd
#
from __future__ import print_function
import RPi.GPIO as GPIO, time, sys
from subprocess import call
#------------------------------------------------------------------------

if sys.argv[1]:
    gpioPin = int(sys.argv[1])
else:
    gpioPin = 4

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(gpioPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def shutdown():
    print("[{}] shutting down!".format( time.strftime("%d.%m.%Y %H:%M:%S") ))
    #run command
    call('sudo halt', shell=True)

try:
    print("Waiting for falling edge on gpio%d" % gpioPin)
    # Wait for input from button
    GPIO.wait_for_edge(gpioPin, GPIO.FALLING)
    # Run the shutdown function (the edge has been detected)
    shutdown()
except (KeyboardInterrupt, SystemExit):
    print("\nQuit\n")
/usr/local/sbin/pipower.sh

Code: Select all

#!/bin/bash

[ ! -z "$1" ] && PIN=$1 || PIN=4

sleep 10
echo "----------\> Turning off Power supply (gpio${PIN}) \<----------"
[ ! -f /sys/class/gpio/gpio$PIN/value ] && echo $PIN > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio$PIN/direction
echo 0 > /sys/class/gpio/gpio$PIN/value
echo "Waiting for AC..."

exit 0
circuit:
Image
Image


Anyone knows what's wrong?
Thanks!

jonathanCCC
Posts: 23
Joined: Thu Apr 21, 2016 7:56 am

Re: DIY PiSwitch - switching AC gracefully on and off

Wed Jun 08, 2016 9:28 am

Hi meigrafd,

I have the same problem with my pi rebooting after the software shutdown, did you find a solution ?

Thanks,

rtfromnc
Posts: 1
Joined: Sat Apr 11, 2015 11:43 am

Re: DIY PiSwitch - switching AC gracefully on and off

Mon Jul 18, 2016 1:57 am

jonathanCCC,

FYI - I had the same problem when I had the Auto-off Auto-on switch in the Auto-off position. I removed the switch and tied the .01ufd cap to ground and everything worked for me.

rtfromnc

jonathanCCC
Posts: 23
Joined: Thu Apr 21, 2016 7:56 am

Re: DIY PiSwitch - switching AC gracefully on and off

Mon Jul 18, 2016 8:46 am

Hi rtfromnc,

Thanks for your answer, I will test it.

Return to “HATs and other add-ons”