In this instructable I describe a method for automatically resetting a Banana Pi when it freezes, or looses power and does not restart. This method will also work for the Raspberry Pi as long as the correct GPIO pins are used (which I believe are slightly different than the Banana Pi pins). The method is very simple and uses a small circuit containing an ATtiny45 microcontroller and a small relay to turn the power off then back on to restart the Pi that has frozen or has turned off for any reason. When the Pi is on and functioning correctly it periodically sends a signal to the circuit indicating that it is functioning. If the Pi freezes, the circuit will not receive the signal and after a set amount of time, the circuit will cut the relay off, and back on to the reset the Pi. The code for the ATtiny is very simple and consists of an external interrupt and a timer interrupt. The Pi uses two shell scripts, one called at start up, and one that is called to send the awake signal, and a python script. With this, there is no reason to worry about the Pi freezing up when you can't get to it to restart it.
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: Create Circuit Board
First we need to build the circuit. I have attached a schematic along with a picture of the one I made. I am currently in the process of building a mill for circuit boards, but it is not finished yet and as a result I soldered the components together on some perfboard. This resulted in a circuit that functions but is not very pretty. The parts I used were:
1 - EC2-5SNU 2A 5v latching relay (http://www.digikey.com/product-detail/en/0/399-110...
1 - ATTiny45-20PU microcontroller (http://www.digikey.com/product-detail/en/0/ATTINY4...)
2 - PJ-102B 2.5mm Power Jack (http://www.digikey.com/product-detail/en/0/CP-102B...
2 - 1K .25W Resistors
1 - 10uF Electrolytic capacitor
1 - 22pF Ceramic capacitor
1 - 2 pin header for connection to Pi's GPIO pins
1 - 6 pin connector for programming ATtiny
2 - PP3-002B 2.5mm Female plug connector (http://www.digikey.com/product-detail/en/0/CP3-100...
Once everything was soldered, I cut the power cord I used for the Pi and soldered the 2.5 mm female plugs to the ends to run the power through the newly built circuit and to the PI. I then compiled the Pi_power_brd.c code and flashed it to the ATtiny with the fuses set to 0x62, 0xdf and 0xff for the low, high and extended fuses respectively.
Step 2: Configure Pi
I am using Raspbian developed for the Banana Pi for an OS. In order to configure the Pi to signal the power circuit two shell scripts need to be created. One will be called when the Pi boots and the other will be called by crontab to send the signal. An additional python script is used to set a second GPIO pin as an interrupt to shutdown the Pi. The power circuit will ground this pin before cutting the power to reduce the risk of damaging the SD card if the Pi is somehow still running. Startup_Script.sh is called when the Pi boots (as the name suggests). This script turns off the user controlled green led on the Banana Pi and initializes the GPIO1 pin as an output pin and sets it to high. Send_power_signal.sh is called by crontab to signal the power circuit that the Pi is still functioning correctly. When this function is called it grounds the GPIO1 pin and turns on the green led for 2 seconds. Power_signal.py is a python script that sets GPIO0 as an interrupt pin and calls "sudo shutdown -h now" when the pin is grounded. I saved all three files in the my home folder.
In order to call Startup_script.sh and run Power_signal.py in the background, PS_startup needs to be added to /etc/init.d and configured to be called during boot (make sure to change where it says [Your User Name] to your user name. Please use one of the many tutorials on the internet to help you set this up if you are unfamiliar with how to do this.
As I mentioned before, crontab is used to call the Send_power_signal.sh script on a set interval to indicate that the Pi is still running. I have my power circuit set to restart after 10 minutes if it does not receive a signal from the Pi, so I have set the Pi to send the signal every 8 minutes. To use crontab enter "sudo crontab -e" into the terminal and add the following line to the bottom of the file:
*/8 * * * * /home/[Your User Name]/Send_power_signal.sh >/dev/null 2>&1
This will set Send_power_signal.sh to be called every 8 minutes.
If you own a Raspberry Pi you can use these scripts, but you will need to make sure that you change the pin numbering since it is different than the numbering scheme used by the banana pi.
Step 3: Print Case
I am lucky enough to own a Prusa I3 3d printer to be able to print a case to hold my Pi and power circuit. If you own a printer or have access to one, I have attached the .stl files which you can use to print your own case. Unfortunately this will not fit the Raspberry Pi, so if you would like a case for it, you will need to design your own. I developed the case by altering a design published on thingiverse by Maddin80 (http://www.thingiverse.com/thing:646932). My design allows enough room for a heatsink on the cpu located on the bottom of the Banana Pi as well as enough room above it for the power circuit.
Step 4: Put It All Together
Once the case is printed, insert the Banana Pi into the case. Attach the power circuit to the top part of the case. I did this by drilling four holes and using zip ties to hold it in place. Make sure you position the circuit so that the power input plug is located right above the Ethernet and USB plugs so that you can plug it in easily (see picture). The power cord going from the output plug on the power circuit to the usb power connector on the Pi can be routed out the side above the the composite video out (see picture). Lastly connect the GPIO0 and GPIO1 pins (pins 11 and 12) to the jumper pins on the power circuit. Make sure GPIO0 connects to PB1 on the ATtiny and GPIO1 connects to PB2. With everything wired up, put the top on the case and plug it in anywhere you want without worrying about needing to reset it.
This is my first Instructable, so please forgive me if it is not very polished. If you notice and glaring mistakes please let me know and I will fix them as soon as possible. Also I very much an amateur when it comes to circuits, so I welcome any comments about how the layout of the circuit or the source code can be improved.