There are two fundamental choices for working with the DS3231 RTC. One is to write your own code for controlling the DS3231, the other is to use the DS1307 driver included in RPi OS.
If the alarm function is your only requirement (beyond basic timekeeping), the DS1307 driver will meet your needs. This driver is "assigned" to communicate with & control the DS3231 RTC via the dtoverlay
facility. It is the same dtoverlay
used for setting up the RTC as a time source - adding the alarm function requires only one additional parameter. Let's cover the specifics:
Q: How to set an alarm that triggers the INT/SQW pin on the RTC (DS3231)?
As you've already configured the DS3231, and it's keeping time, you're very close to having a functional alarm. In fact, you only need take two additional steps:
1. Add the wakeup-source
parameter to the dtoverlay
for i2c-rtc
in the /boot/config.txt
file:
FROM: dtoverlay=i2c-rtc,ds3231
TO: dtoverlay=i2c-rtc,ds3231,wakeup-source
Once you reboot your system, the DS1307 driver is prepared to set an alarm.
2. Write the alarm time to the file /sys/class/rtc/rtc0/wakealarm
As an example, let's assume you want to trigger an alarm 30 minutes from now - here's how to do that:
date '+%s' -d '+ 30 minutes' | sudo tee /sys/class/rtc/rtc0/wakealarm
That's all that is needed - the alarm is set. When the alarm "goes off" - that is to say when:
current time = alarm time set in /sys/class/rtc/rtc0/wakealarm
the RTC will assert INT#
(active low), pulling pin 3 of the DS3231 low. So - pin 3 of the DS3231 may be used as input to a GPIO, or used to trigger some external hardware.
3. Clear/reset the alarm (OPTIONAL)
Depending on your application & requirements, it may be necessary to release the assertion on INT#
(pin 3 of the DS3231), and allow it to return to its "HIGH" (pulled-up) state. If so (or if you're just tidy), this is easily accomplished by writing a new value to the sysfs. You may write a 0
to simply clear the alarm, or write a future time for the next alarm. For example, to clear the alarm, and de-assert INT#
:
echo "0" | sudo tee /sys/class/rtc/rtc0/wakealarm
Other alternatives
In the procedure outlined above. the driver does all of the heavy lifting. The only code you may need to create is an interrupt handler that defines what action to take when the alarm "goes off", and perhaps clear or reset the alarm. With this approach, you needn't worry about using python-smbus
, python-smbus2
or i2c-tools
to write to the DS3231's internal registers. However, the DS1307 driver - in its present configuration - is incapable of accessing many of the functions and options available in the DS3231 hardware.
You may wish to review the DS3231 spec sheet. Familiarize yourself with its functions and options, and decide if they're worth the extra code-writing effort. If so, you may modify the current driver, and its associated dtoverlay
- or you may write your own code. This is typically what Arduino users do (they have no driver), and there are libraries available that may be useful. The i2ctools
suite is another option - this document may help.