Uncategorized
alphamike-1612  

Using the RTC on Raspberry Pi 5.

The all-new Raspberry Pi 5 has an onboard RTC clock. This means that the Pi will keep time even when shutdown. It can keep time with either the 5v power supply or an additional CR2032 battery that is connected to the J5 connector. The advantage of adding the CR2032 battery is that it keeps time even when the power supply is disconnected.

To use the RTC to wake up, we need to edit the eeprom so that in halt mode the Pi is in low power mode. This is not a required change. Without this, the Pi in shutdown state will consume upto 1-1.5 W of power. This was noted by Jeff Geerling in his blog post here. This is also documented in the Raspberry Pi forum in this post.

To do this, we need to runhttps://forums.raspberrypi.com/viewtopic.php?t=356991

sudo -E rpi-eeprom-config --edit

The default in my case was:

[all]
BOOT_UART=1
POWER_OFF_ON_HALT=0
BOOT_ORDER=0xf41

Edit such that POWER_OFF_ON_HALT is set to 1.

[all]
BOOT_UART=1
POWER_OFF_ON_HALT=1
BOOT_ORDER=0xf41

Once you edit this, reboot the system so that the changes are applied. You can then check that it has been updated with rpi-eeprom-config. It will output the current config which is as seen above. (Yours might be different based on your setup. Just make sure that POWER_OFF_ON_HALT is set to 1.

Now we are ready to test the RTC. We can write to /sys/class/rtc/rtc0/wakealarm, the number of seconds to wait before booting the system again.

echo +300 | sudo tee /sys/class/rtc/rtc0/wakealarm

The above command tells the RTC to wait for 5 minutes since the command* to start the Pi again. After this, we shutdown the system and wait for it to start automatically.

*since the command – This means that if you gave the above echo command at 00:35, the system will reboot at 00:40, irrespective of whether the system was shutdown at 00:35 or 00:39. If the system was not shutdown at all, nothing happens, the value is ignored. (but not reset, until a reboot).

We can check that the value is set by running

user@hostname:~$ cat /sys/class/rtc/rtc0/wakealarm
1703385355
user@hostname:~$

How this works, is that the number of seconds specified is added to the current linux epoch time (number of seconds since Jan-1-1970). When that value is hit, the RTC asks the system to switch on.

sudo shutdown now

Upon booting, you will see that /sys/class/rtc/rtc0/wakealarm is reset to 0 or null. Running cat will not give any output.

cat /sys/class/rtc/rtc0/wakealarm

The above example might be useful if you shutdown and reboot the Pi at fixed times every day. For example, The system automatically shuts down at 5 PM everyday and starts again at 9 AM the next day. You can then use the following script.

nano rtc-time-set.sh
#!/bin/bash
#Script to shutdown the system and set RTC for waking up.

echo +57600 | sudo tee /sys/class/rtc/rtc0/wakealarm
#57600 is the number of seconds from 5:00 PM to 9:00 AM

sudo shutdown now

Note – The above script is running a command as root. Take due precaution on permissions such that no other user is able to modify or execute this file. ( I recommend 700 permissions)

Save the above script and make sure it’s executable (chmod u+x rtc-time-set.sh) and create a systemd service file that calls this script. Finally create a timer that calls the service file at 5:00 PM every day.

sudo nano rtc-wake-alarm.service
[Unit]

Description = Execute the rtc-time-set script.

[Service]

Type = oneshot

User = alphamike-1612

ExecStart = /home/alphamike-1612/rtc-time-set.sh

Restart = on-failure

RestartSec =5

[Install]

WantedBy = multi-user.target

Create a timer file that calls this service file.

sudo nano /etc/systemd/system/rtc-wake-alarm.timer
[Unit]

Description = Timer for executing rtc-wake-alarm.service at 17:00 everyday.

[Timer]

Unit = rtc-wake-alarm.service

OnCalendar = *-*-* 17:00:00

Persistent = false

[Install]

WantedBy = timers.target

Finally, reload the daemon and enable and start only the timer.

sudo systemctl daemon-reload
sudo systemctl start rtc-wake-alarm.timer
sudo systemctl enable rtc-wake-alarm.timer

The above example is useful only when the system is shutdown automatically at a particular time. Sometimes, we might want the system to wake at a specific time everyday, but we may not be able to shut it down at the same time everyday. In this case, we cannot add a constant number of seconds to the epoch value since it will vary, instead we directly mention the epoch second value at which the system is to be woken up.

The correct epoch time can be calculated by the following script:

nano rtc-time-set.sh
#!/bin/bash
#       This is a script for the RTC clock of the Raspberry Pi 5, such that it wakes up at 09:00 local time everyday, irrespective of when it shuts down.
#       This works by an if-else model.
#       It first sets the value of /sys/class/rtc/rtc)/wakealarm to 0 so that any previous value is purged.
#       It calculates 3 values.
#       The current epoch to the variable $current_epoch.
#       The same day's epoch at 09:00 to the variable $same_day_epoch
#       The next day's epoch at 09:00 to the variable $next_day_epoch

#       If the current_epoch is less than the same_day_epoch,then it writes the value of same_day_epoch to final_epoch.

#       Else if the current_epoch is more than the same_day_epoch, but less than next_day_epoch, it writes the value of next_day_epoch to final_epoch.

#       There is also a redundancy that in any other condition (example - current_epoch > same_day_epoch but also more than next_day_epoch), it will write 0 to the RTC alarm and perform a panic action (like sending an e-mail)

#       In the end, final_epoch is written to /sys/class/rtc/rtc0/wakealarm

#       This way if the system shuts down at 02:00, it will still be woken up at 09:00 on the same day instead of 09:00 on the next day.

#       All times are local. 

echo 0 | sudo tee /sys/class/rtc/rtc0/wakealarm

current_epoch=$(date +%s)

same_day_epoch=$(date -d '09:00' +%s)

next_day_epoch=$(date -d 'tomorrow 09:00' +%s)


if [[ $current_epoch < $same_day_epoch ]]

then
        final_epoch=$same_day_epoch

elif [[ $current_epoch > $same_day_epoch  &&  $current_epoch < $next_day_epoch ]]

then
        final_epoch=$next_day_epoch

else

        final_epoch=0
#       $panic_action_here

fi

        echo $final_epoch | sudo tee /sys/class/rtc/rtc0/wakealarm

How the script works:

First we take 3 values, the value of the same day 9:00 AM epoch, the value of the next day 9:00 AM epoch and the value of the current epoch (when the script is run). If the time that the script is run is after 9:00 AM on the same day, the current_epoch will be higher than that of the same_day_epoch. This will trigger the next_day_epoch value to be written to wakealarm. If the script is run before 9:00 AM on the same day, the current_epoch value will be lower than that of same_day_epoch. This will trigger the same_day_epoch to be written to wakealarm.

Ensure that the script is executable (chmod u+x) and permissions are set such that only the user is able to access the file, since it contains sudo commands. (chmod 700)

Then we create a service file, that calls this script just before shutdown.

sudo nano /etc/systemd/system/rtc-wake-time.service
[Unit]

Description = Execute a script, before shutdown or reboot that sets the RTC Alarm to wake at a particular time.

DefaultDependencies = no

Before = shutdown.target

[Service]

Type = oneshot

User = alphamike-1612

ExecStart = /home/alphamike-1612/rtc-wake-time-set.sh

TimeoutStartSec = 0

[Install]

WantedBy = shutdown.target

I am unable to find a reliable source as to why DefaultDependencies is to be set to ‘no’. man systemd.service says that it is by default set to no when using Before, but when I tried this, it did not work.

After this, reload the daemon, and enable the service but don’t start it.

sudo systemctl daemon-reload
sudo systemctl enable rtc-wake-time.service

You can verify the service and script work by rebooting the system and checking the value of /sys/class/rtc/rtc0/wakealarm. It will give an epoch value in seconds that can be converted to human readable command with the date command. See below for the list of commands.

sudo reboot now
# After the reboot
date -d @`cat /sys/class/rtc/rtc0/wakealarm`
#This will return the value
Sunday 24 December 2023 09:00:00 AM TIME_ZONE

Congratulations. You have successfully setup the RTC to wake up the system at 9:00 AM everyday irrespective of when the system is shut down.

Note – If the system was rebooted before 9:00 AM but not shut down again, the value in /sys/class/rtc/rtc0/wakealarm would be set. But nothing will happen when this time is crossed. When shutting down again, the system will automatically reset the value to the correct one.

Leave A Comment