Translate

Saturday, October 25, 2014

Raspberry Pi - RPOf project


The Raspberry Pi can be used to run some kind of embedded Linux.
Like any *nix system, removing suddenly power is not a  good thing, it is very easy to corrupt  some SD card sector if the power removal happens during a writing cycle.

So, especially if the board is running some kind of "embedded" code, i.e. no keyboard/HDMI/remote connection, it is important to be able to shutdown it properly.



There are mainly two main operations to perform to correctly turn OFF a *nix system.

  • send a shutdown to the system
  • remove the power after the shutdown

It is possible to use a spare GPIO on the Raspberry Pi to allows to have a easy way to accomplish the job to shutdown the machine.
Using some external hardware is possible to remove the power supply when the shutdown sequence is completed.

The easiest way is to use a cheap microcontroller, like an AVR, PIC or MSP430 or anything programmable.

RPOf (Raspberry Pi On/off)


The RPOf is a circuit that allows to turn ON and OFF a Raspberry Pi with a single pushbutton.
Specifically the circuit allows to:
  • indicate the state of the power to the Raspberry Pi
  • give/remove main power (5V) to the Raspberry Pi
  • send to the Raspberry Pi a signal on a GPIO for the shutdown
  • monitor the status of the shutdown
  • remove the power after the shutdown is performed
Similar circuits are already on the market but it was fun to design my own.

Hardware


The circuit is based on a MSP430 family microcontroller but anything can really be used, also an Arduino or Trinket or bare AVR or any other small microcontroller.
This article describes a RPOf based on a MSP430F2012, the one that can be programmed using a TI LaunchPad (probably a smaller MSP430F2002 will be used since the code is very small and no particular peripherals are used).




The circuit has a 5V stabilized input, usually coming from an USB wall wart (at least 1A) and is connected to the Raspberry Pi on two points:
  • the power supply (+5V)
  • the shutdown input/feedback
The choice is to control the +5V and not supply the Raspberry Pi with the 3.3V for two reasons.
First the Raspberry Pi can control 5V peripherals (for example an LCD) and thus needs to have the full power, and second, in this way there is no need to modify the Raspberry Pi power supply.
A relay feeds the power to the Raspberry Pi and a single pushbutton (with LED) control all the operations.

When the power is applied to the circuit, the relay is deactivated, so NO power is provided to the Raspberry Pi.

It is important to note that the MSP430 is powered at 3.3V, so the I/O lines going to the Raspberry Pi are already set for the correct voltage level.
There is no need to interface the signals with transistors.

The first prototype was built over a Launchpad, thus some I/O were chosen to match what already existing on the Launchpad.
For example the LED output and the pushbutton input are the default ones on the Launchpad so that in the early stage of the development it was possible to use the Launchpad ones.

The circuit uses 2 LEDs.
  • One fixed red LED powered when there are the 5V input, to indicate that there is power to the RPOf.
  • The second LED is included in the On/Off pushbutton and indicates the status of the power.
    - OFF   Raspberry Pi not powered
    - ON     Raspberry Pi powered
    - FLASH  Raspberry Pi doing shutdown
  • Optional a  third LED can be is used as debug and it can be used to indicate that the Raspberry Pi is working.

Prototype


After the first tests on the Launchpad board, a  prototype was built over a perforated board.
It is round because is what I had around at the moment.






Operations


The operations are  based on a state machine with seven states :
  • IDLE
  • POWERON_START
  • POWERON_WAIT
  • POWERON
  • POWEROFF_START
  • POWEROFF_WAIT
  • POWEROFF

IDLE state

The default state is IDLE.
In this state the power to the Raspberry is OFF, the Power LED is OFF and it is constantly monitored the on/off pushbutton.
When the on/off pushbutton is pressed set the state to POWERON_START.


POWERON_START state

In the POWERON_START state :
  • The relay is turned ON
  • The Power LED is turned ON
  • Change state in POWERON when the on/off pushbutton is released.


POWERON_WAIT state

In the POWERON_WAIT state :
  • it is monitored a signal coming from the Raspberry Pi.
    This signal is set to one by the Raspberry Pi when is running and is reset after a shutdown.
    By default this signal is zero when the Raspberry Pi starts and remains to zero until a program on the Raspberry Pi starts and set it to one.
  • A safety timer of 2 minutes is set.
    If expires it means that in 2 minutes the Raspberry Pi didn't start and the power is removed from the Pi (forced PowerOff state).
  • When the signal goes ON:
      - Power LED is set to ON
      - the safety timer is removed.

POWERON state

In the POWERON state, it is monitored the pushing of the on/off pushbutton.
When the on/off pushbutton is pressed set the to  POWEROFF_START.


POWEROFF_START state

In the POWEROFF_START state :
  • Send the signal to the Raspberry Pi to execute the shutdown.
  • The Power LED is set to FLASH
  • Start 15 minutes safety timer
  • Set the state to POWEROFF.

POWEROFF_WAIT state

In the POWEROFF_WAIT state :
  • Monitor when the Raspberry Pi shutdown is completed
    - if safety timer expires:
      - relay is turned OFF
      - Power LED is turned OFF
      - Shutdown signal is turned OFF

    - if shutdown completed:
      - Start OFF TIMER


POWEROFF state

In the POWEROFF state :
  • Wait for the OFF TIMER to expire. When it expires:
      - relay is turned OFF
      - Power LED is turned OFF
      - Shutdown signal is turned OFF
      - Set the state to IDLE


Forcing and Detecting shutdown

We need two free GPIO on the Raspberry Pi to be used for the shutdown procedure.

  • Shutdown request
    Raspberry Pi side will be an input
    RPOf side will be an output
    This signal will indicate to the Raspberry Pi to start the Shutdown command (sudo shutdown -h now)
  • Shutdown feedback
    Raspberry Pi side will be an output
    RPOf side will be an input
    This signal will indicate to the RPOf that the Raspberry Pi successfully completed the shutdown procedure and thus the power can be removed.
    That GPIO is set as output and forced to high (1).
    When the shutdown is complete, all the I/Os are forced to low, thus the RPOf can monitor the GPIO we set up as output and it  can determine if the shutdown was executed and completed.

There are a couple of options to do so.

1) Raspberry Pi script


In order for the RPOf to work, a daemon need to run on the Raspberry Pi, monitoring a GPIO input connected to the RPOf circuit.
When the signal monitored goes down, the script starts the shutdown sequence.
Handling the GPIO via script uses a different GPIO listing. Read the notes.

The same script, started automatically after the Raspberry Pi boot up, set also the GPIO to allow RPOf to detect the completion of the shutdown.

2) Local program


If a program is supposed to run, it is possible to add the I/O management in the program itself.
The program will set up the Shutdown feedback signal ON (it will be set to zero when the shutdown will be completed).
On the same time, the program will include the constant monitoring of the Shutdown request signal.


RPOf Software

The software is written in C, compiled with the  mspgcc compiler and load in the chip with the mspdebug, all under Linux.
The timing for this project is not critical, so no crystal is used. Instead is used the internal oscillator set for the maximum speed, 16 Mhz

The code resides in a single file called RPOf.c and uses a very easy makefile to compile.

Makefile


CC=msp430-gcc
CFLAGS=-O0 -Wall -g -mmcu=msp430f2012

OBJS=RPOf.o


all: $(OBJS)
$(CC) $(CFLAGS) -o RPOf.elf $(OBJS)

%.o: %.c
$(CC) $(CFLAGS) -c $<

clean:
rm -fr RPOf.elf $(OBJS)

Code


The code is quite straightforward.
There are specific functions for the main basic tasks, like reading the pushbutton or reading the shutdown feedback signal or handling the pushbutton LED behavior.

Function readPushbutton()

Reads the status of the On/Off pushbutton.
It returns 1 (ON) if pressed, 0 (OFF) if not pressed.

Function readShutdownFeedback()

Reads the status of the signal to monitor the end of the shutdown sequence.
It returns 1 (ON) if shutdown ended (machine stopped), 0 (OFF) otherwise.
It can be used to determine if the Raspberry Pi is running.

Function LEDPower()

Control the Power LED of the On/Off pushbutton.
A global variable (LEDStatus) control how the LED behave:

Value   Define       Description       
 0      OFF           LED Off
 1      ON            LED On
 2      FLASH         LED Flash (.5 sec)

Function Relay()

Control the Relay.
A global variable (RelayStatus) control how the Relay behave:

Value   Define       Description       
 0      OFF           Relay Off
 1      ON            Relay On

Git

The RPOf project is on github.

Improvements


Here some possible improvements to the circuit:

  1. work to reduce the power usage.
    Reduce the frequency, have it working in low power mode when in IDLE
  2. Add a 5V battery.
    A 5V battery charged from the main supply, could allow to guarantee a correct shutdown even if the external power is suddenly removed

Resources


Here some links:

1 comment:

  1. Hi Steve, to reduce power simply enable interrupt on input port pins, on interrupt service exit LPM clear irq flags (to avoid IRQ loop).
    On main read status, if set do action then reenter deep sleep (LPM4 CPU and oscillator Stopped).
    Change default mode for pin 6,7 of port B from oscillator to gpio and drive low.
    Robert

    ReplyDelete