The PiWatcher is a very small board that helps you fully shut down or reboot a Raspberry Pi, in case of an incident or simply for power saving purposes. You can even program your PiWatcher to shut down and automatically reboot your Pi a few minutes or hours later. In essence, the PiWatcher is a programmable watchdog circuit for the Raspberry Pi, usable with the humble Pi Zero up to the power-hungry Pi 3. The new version released in January 2020 also works with the Raspberry Pi 4.

It currently does not work "out of the box" with the Raspberry Pi 5 due to a bug in the I2C implementation on the Pi 5. A bug fix corrects this issue, and we hope it will be available to the mainline kernel soon.

The Pi Watcher

The board must be fitted on the first 6 pins of the Raspberry GPIO header and plugged into a micro USB power supply suitable for the Raspberry Pi in use. The board will then switch on or off the power provided to the Raspberry Pi based on instructions it receives through I2C. The board also features a miniature tact switch to allow manual control.

A solution for Raspberry Pi power management

The PiWatcher is designed to solve 2 problems with power management on the Raspberry Pi.

First, if you shut down a Raspberry Pi through software, for example by issuing a shutdown or halt command, your Raspberry Pi will cease to operate, but it does not completely shut down. Instead, it enters a quiescent state where it continues to eat 30 to 50mA, sometimes more depending on connected peripherals. This is wasteful and can become an issue in battery-powered systems.

The PiWatcher can be programmed to fully cut power to the Raspberry Pi after a certain delay of inactivity. For For example, you can tell the PiWatcher to cut power 10 seconds after a shutdown command has been issued, giving the Raspberry Pi enough time to cleanly power off.

The second issue with power management has to do with the ability to recover from situations where a Raspberry Pi becomes stuck in an unrecoverable state. While in theory, this should not happen, a long-running Raspberry Pi can get 'stuck' or 'freeze', due to software or hardware failures or even environmental factors such as heat. In some cases the least unsatisfactory approach to deal with this issue is to simply switch off and on again the Raspberry Pi, enabling the application to continue and/or send out an alert.

The PiWatcher can be programmed to automatically power cycle a Raspberry Pi if it does not receive a 'heartbeat' from the device after a user-selectable delay. This can allow some critical applications to continue to operate without human intervention.

Furthermore, the PiWatcher can be programmed to "sleep" for a certain delay after a shutdown, ranging from a few seconds to about 36 hours, before rebooting your Raspberry Pi.

The table below summarizes the power consumption of a PiWatcher connected to a Raspberry Pi (measurements were done with a Pi Zero W).

Situation Current consumption
PiWatcher is running normally 7mA in addition to the power consumption of the Raspberry Pi (typically >130mA).
PiWatcher is "sleeping" until reboot 3mA
PiWatcher has fully shut down >0.5mA

It has an LED and a button too!

The PiWatcher has an LED. When the Raspberry Pi is powered on, the LED is continuously on. When the Raspberry Pi is "sleeping" for a certain delay, the LED blinks slowly. When the Raspberry Pi is powered off, the LED remains off.

The PiWatcher also has a useful micro tact-switch:

  • When your Raspberry Pi is running:
    • a long press (5 seconds) on the button, followed by a button release, will completely power off the Raspberry Pi.
    • a short press (half a second) on the button will send a software signal that can be exploited for user-defined purposes.
  • When your Raspberry Pi is shut down, a short press on the button will restart the Raspberry Pi.

Alternative model with terminal blocks

As an alternative to the classic PiWatcher described in this documentation, we have also released a special version called PiWatcher TB where the USB connector has been replaced with a 3-pin 2.54mm screw terminal block connector.

The PiWatcher TB depicted in the picture below offers 3 connections:

  • GND: power ground
  • 5V: 5V power source
  • BUTTON_ALT: optionally connect this terminal and GND to an external switch, which will act as an alternative to the on-board micro tact-switch.

The picture below illustrates a PiWatcher TB fitted on top of a Raspberry-Pi: power is provided through 2 wires, 5V (red) and GND (white). The USB-C power connector of the Raspberry-Pi is not used.

Using the PiWatcher

Setup

To start using the PiWatcher, follow these steps.

Plug the PiWatcher in the first 6 pins of the Raspberry-Pi GPIO header. For greater mechanical stability it is recommended to secure the PiWatcher to the Pi with a standard 11mm standoff (2.5mm).

Next, plug the USB power supply into the PiWatcher. In turn, this will boot the Raspberry Pi.

To use the PiWatcher on the Raspberry Pi, you will need to enable I2C on the Raspberry Pi. Use sudo raspi-config for this purpose (as described in this Adafruit tutorial for example).

First, download the piwatcher command line tool.

For 32-bit Raspberry Pi OS, you can download the tool as follows:

wget -N http://omzlo.com/downloads/piwatcher

For 64-bit Raspberry Pi OS, you can download the tool as follows:

wget -N http://omzlo.com/downloads/aarch64/piwatcher

Note: You can also compile the file yourself from source.

You'll need to make sure the file is executable and that it is located in a directory included in your PATH (e.g. /usr/local/bin on a Raspbian system).

chmod a+x piwatcher
sudo mv piwatcher /usr/local/bin/

The piwatcher tool can then be used to query and configure the PiWatcher.

Typing piwatcher status should return:

OK  0x00

On some systems, you may need to type sudo piwatcher status instead.

If you press the micro-switch on the PiWatcher and then re-run piwatcher status, you should see the following output:

OK  0x80    button_pressed

You can clear this button_press event, resetting the status of the PiWatcher by running piwatcher reset. Re-running piwatcher status will show again status 0x00.

Setup on older Raspberry-Pi models

The PiWatcher works on all recent Raspberry Pi models, except for the Pi 5 (see introduction). On older Raspberry-Pi models (e.g. The 2012 model B), you may encounter inconsistent behaviors with the piwatcher command because of I2C clock speed issues. To fix this problem on these older models, you will need to slow down the I2C clock from the default 100kHz to 50kHz, by editing the file /boot/config.txt and changing the following line:

dtparam=i2c_arm=on

to:

dtparam=i2c_arm=on,i2c_arm_baudrate=50000

After modifying the file, reboot your machine and you should be good to go.

Watchdog

We will now program the PiWatcher to shut off the Raspberry-Pi after 30 seconds if it does not receive any message from the Raspberry Pi, with the command piwatcher watch 30.

After this command has been issued, the PiWatcher will start a 30 second counter. If the counter reaches 0, the power to the Raspberry Pi will be cut off. However, this counter will be reset to 30 seconds each time the PiWatcher receives a 'read request' from the Raspberry Pi. A simple way to issue a 'read request' is to issue the command piwatcher status.

In this example, a simple way to keep the Raspberry-Pi form shutting down would be to run the following loop:

while true
do 
   piwatcher status
   sleep 25
done

The sleep 25 assures that the PiWatcher is called approximately every 25 seconds, taking a 5-second safety margin from our 30-second deadline. If this loop gets interrupted for any reason, the Raspberry-Pi will reboot after at most 30 seconds.

This feature can be exploited to completely shut off a RaspberryPi after a shutdown. Assuming the Pi takes at most 15 seconds to shut down, we can issue the following commands:

piwatcher watch 15
shutdown now

Automated rebooting

By default, the PiWatcher will shut off the Raspberry Pi until the user presses the button or until USB power is cycled.

We can program the PiWatcher to "wake" the Raspberry Pi after a certain delay (expressed in seconds).

To reboot the Raspberry-Pi 10 minutes after shutdown, we would simply type:

piwatcher wake 600

A clock under the hood

The PiWatcher is based on a Microchip attiny45 8-bit microcontroller, which runs with an 8Mhz internal oscillator.

An internal clock ticks about 25.04 times per second (8.000.000/(8192*39)). Watchdog and reboot time values are converted to internal clock ticks by multiplying their value by 25. Because of variations in temperature and voltage, the accuracy of these timings may be off by +/-10%.

You can view the actual value of the clock by issuing the command piwatcher ticks.

Running piwatcher automatically

In most cases, you don't want to type commands with piwatcher each time your Raspberry Pi boots up. Instead, you will want to run PiWatcher automatically each time the Raspberry Pi boots up, with the correct configuration. Fortunately, this is rather easy thanks to systemd.

As an example, we will consider the case where you want the Raspberry-Pi to fully shut down automatically after 30 seconds of inactivity, either because you've halted it or because it got 'stuck'.

For simplicity, we will assume you are running a recent version of Raspbian Linux and that you have installed the piwatcher binary in the directory /usr/local/bin/.

It takes 3 steps to implement our scenario.

STEP 1. Create a monitoring script

Use your favorite editor to create the file /home/pi/piwatcher.sh with the following content.

#!/bin/bash

/usr/local/bin/piwatcher watch 30

while true;
do
    /usr/local/bin/piwatcher status >> /dev/null
    sleep 15
done

This will essentially set a 30-second watchdog, and start an infinite loop that sends a message to the piwatcher every 15 seconds to assure that the watchdog is not triggered.

We need to make this script executable as follows.

chmod a+x /home/pi/piwatcher.sh

STEP 2: Create a new systemd service

Now we will create a systemd service for the previously created script. As we need 'root permission' to create the script, we will use sudo:

sudo vim /etc/systemd/system/piwatcher.service

You can replace vim with nano or your favorite editor in the line above.

The content of the file should look as follows.

[Unit]
Description=PiWatcher Service
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=pi
ExecStart=/home/pi/piwatcher.sh

[Install]
WantedBy=multi-user.target

STEP 3: Activate and start the service

Finally, we will activate the service.

sudo systemctl enable piwatcher

This will typically output the following message: "Created symlink /etc/systemd/system/multi-user.target.wants/piwatcher.service → /etc/systemd/system/piwatcher.service."

We will also start the service, as follows.

sudo systemctl start piwatcher

The activation (and start) only needs to be performed once. The piwatcher will now be launched automatically each time the machine boots up.

Applying a default watchdog for extra security

What happens if your Raspberry-Pi halts or crashes before you get a chance to configure a watchdog timeout with the PiWatcher?

Most users will never have to worry about this risk. If you have created a systemd service as described above, this is uniquely to happen, but it's not completely impossible. To address this issue, we have added the ability to configure a set of default watchdog timeout and wakeup values that is stored in the EEPROM of the PiWatcher. You can configure this feature with the command piwatcher defaults <watchdog timeout> <wakeup timer>, replacing <watchdog timeout> and <wakeup timer> with the watchdog duration in seconds, and the wakeup delay in seconds, respectively.

For example, running the command piwatcher defaults 120 10, will store 120 seconds and 10 seconds in EEPROM as defaults for the watchdog timeout and reboot delay respectively. These values become active at the next restart. Running piwatcher defaults 0 0 disables this feature.

This command should be used with caution because you can lock yourself out, for example by selecting a watchdog timneout that is too short. There is a procedure to manually clear the EEPROM: simply hold the button on the PiWatcher down, then plug the USB power, while keeping the button pressed down for more than 10 seconds.

This features is only available in PiWatcher released after June 2021. To check if the firmware on your PiWatcher offers this feature, type piwatcher defaults to see if you get an error message or not.

I2C specification

The PiWatcher uses an extremely simple communication protocol based on I2C. The board essentially features an 8-byte register array that can you can read to or write from, at I2C address 0x62.

This register array is structured as follows:

Register Description
0 Status byte
1 Watchdog timeout in seconds, 0=disabled.
2-3 Wakeup delay in seconds divided by 2 (5 means 10 seconds). LSB first. 0=disabled.
4-7 Internal clock. LSB first.

The status byte has the following structure:

Position Name Description
Bit 7 BUTTON_PRESSED A 1 indicates that the PiWatcher button has been pressed. Writing a 1 will clear the bit.
Bit 6 TIMER_BOOT A 1 means that the PiWatcher rebooted the Pi after a wake-up period. Writing a 1 will clear the bit. This is unreliable however since the PiWatcher may have reset.
Bit 5 BUTTON_BOOT A 1 means that the PiWatcher rebooted the Pi because the user pressed the button. Writing a 1 will clear the bit. This is unreliable however since the PiWatcher may have reset.
Bit 4-0 unused

The command ./piwatcher dump will print the raw content of all registers.

The content of the registers can be manipulated with i2c-tools as well (see instructions here for example). For example, you can get the status byte with the command i2cget -y 1 0x62 0.

Resources