I've just obtained a DS3231 real time clock (RTC), and added it to my RPi 3b. It seems to work as far as keeping time, but I wanted more.

I'd like to be able to set alarms to trigger the INT/SQW pin on the chip (while retaining the basic timekeeping function I currently have), but I've been unable to find any way to do that with the toolset in RPi. I've installed python-smbus and i2c-tools as part of the RTC configuration. Have I overlooked something? - how should I go about reading & writing the DS3231's internal registers to set up the alarm function on my RPi 3b?


1 Answer 1


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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.