Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / IoT / Raspberry-Pi

Build a Raspberry Pi powersupply with Digispark Attiny85

4.89/5 (7 votes)
28 Dec 2016CPOL3 min read 41.1K   432  
Power on, safe shutdown and power cut-off for Raspberry Pi

Introduction

Raspberry Pi is an amazing device, packing so much power into a small form factor with such a cheap cost.

Unfortunately, it does not comes with its own power supply. Shutting down involves running the shutdown command and unplugging the USB power.

A video demonstration of the implementation can be found here.

Design

This power supply consists of:

  1. Push Button - To trigger on, off and forced power off function
  2. LED light - To show status of, ON (light up), Turning off (blinking), OFF (light off)
  3. Relay - Driving the power into the Pi using Attiny85 (5V USB power)
  4. Transistors x 2 (2N2222 or any similar NPN Transistor)
    • One for driving the Relay to feed power into Pi
    • One for trigging the shutdown command of Pi (using GPIO12 / Pin32 in this example)
  5. Attiny85 (I used Digispark USB development board for development) - Main controller

Here's how the switch is designed to work:

When power is connected, the attiny85 is powered up, relay is in OFF state and Pi is NOT powered. The attiny85 is waiting for button to be pressed.

  • When button is pressed, relay is switched on. Pi is powered and boots up.
  • When button is pressed again, the program sends a signal to Pi to shutdown. The Pi has a python script running and listening to signal on the GPIO port. When signal is received, Pi will run shutdown command.
  • The program waits until Pi is fully shutdown by monitoring GPIO14 (UART TX) (voltage <0.1).
  • Once confirmed Pi is fully shutdown, the program turns the relay to OFF and Pi's power will be cut.

Circuit Diagram

  • Circuit diagram also attached:
    • P0 of digispark drives the relay to power to Pi
    • P1 of digispark drives the status LED
    • P2 of digispark takes input from button for power on / off button
    • P3 of digispark trigger shutdown of Pi via GPIO12
    • P4 of digispark detects if Pi is shutdown via GPIO14 (UART TX)

Using the Code

  • Install the sketch into attiny85. I am using Digispark USB development board (sketch_pi_switch.ino)
  • Run the shutdown script in Raspberry Pi (ShutdownDetect.py)

Points of Interest

C++
int SHUTDOWN_PIN = 3;
int RELAY_PIN = 0;
int BUTTON_PIN = 2;
int LED_PIN = 1;

The powerstatus variable is used to keep track of the power status of pi.

C++
int powerstatus = 0; 
//Power Toggle Mode
// 0 Power off
// 1 Powering On (not used for now)
// 2 Powered on 
// 3 Powering off
// 4 Waiting for Safe Shutdown to finish
// 5 Hard Shutdown

Each loop is delayed by 50ms, making timing a bit easy (e.g., how long the button has been pressed).

If button is pressed for a long time (60 * 50ms) = 3s, force to power down.

C++
if(buttondowncount>=60 && buttonupcount >2)
    {//Long Pressed Button
      buttondowncount = 0;
      buttonupcount = 0;
      powerstatus = 5;
    }

If button is pressed for a short time (3 * 50ms) = 150ms. Either move from power off (powerstatus 0 to 1) or start power off sequence (powerstatus 2 to 3).

C++
else if(buttondowncount>=3 && buttonupcount >2)
        {//Button Pressed
          buttondowncount = 0;
          buttonupcount = 0;
          if(powerstatus==0)
            powerstatus=2;
          else if(powerstatus==2)
            powerstatus=3;            
        }

The next section of the code is where the actions are for each powerstatus.

C++
//Switch on relay to power on
if(powerstatus==2)
{
    digitalWrite(SHUTDOWN_PIN, LOW);
    digitalWrite(LED_PIN, HIGH);
    digitalWrite(RELAY_PIN, HIGH);
}
else if(powerstatus==3)
{
    //Start Shutdown Sequence
    //Trigger shutdown script in Pi
    digitalWrite(SHUTDOWN_PIN, HIGH);
    delay(100);
    digitalWrite(SHUTDOWN_PIN, LOW);
    powerstatus=4;
    checkOffCount = 0;
}
else if(powerstatus==4)
{
    //Waiting for fully power off signal in TX pin
    //Blink LED to signal powering off
    digitalWrite(LED_PIN, LOW);
    delay(300);
    digitalWrite(LED_PIN, HIGH);
    delay(200);

    //Check if it's off 5 times before shutting down
    if(checkPiOff())
      checkOffCount = checkOffCount + 1;
    else
      checkOffCount=0;

    if(checkOffCount==10)
    {
        //It's really off
        digitalWrite(LED_PIN, LOW);
        digitalWrite(RELAY_PIN, LOW);
        powerstatus = 0;
        checkOffCount = 0;
    }
}
else if(powerstatus==5) //Hard shutdown
{
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN, LOW);
    powerstatus = 0;
    checkOffCount = 0;
}

The most interesting section would be powerstatus==3 and 4. Below triggers the pi and runs the shutdown command and sets the powerstatus to 4 (waiting for Safe Shutdown to finish).

C++
digitalWrite(SHUTDOWN_PIN, HIGH);
delay(100);
digitalWrite(SHUTDOWN_PIN, LOW);

powerstatus=4;

Then in powerstatus == 4, it blinks the LED light and monitors whether the pi is fully in shutdown state.

C++
else if(powerstatus==4)
{
    digitalWrite(LED_PIN, LOW);
    delay(300);
    digitalWrite(LED_PIN, HIGH);
    delay(200);

    //Check if it's off 5 times before shutting down
    if(checkPiOff())
      checkOffCount = checkOffCount + 1;
    else
      checkOffCount=0;

    if(checkOffCount==5)
    {
        //It's really off
        digitalWrite(LED_PIN, LOW);
        digitalWrite(RELAY_PIN, LOW);
        powerstatus = 0;
        checkOffCount = 0;
    }
}

Points of Interest

  • Digispark does draw some power, even when the PI is shutdown. I am running it in 1Mhz mode so that it draws the minimum power.
  • This project can be easily improved to remotely control the Pi's power via Infrared. Let me know your thoughts!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)