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
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?packagesrtctimekeepingshared-librariesds3231ShareEditFollowCloseFlagedited Apr 8 at 8:07asked Apr 6 at 21:41anonAdd a commentStart a bounty
It has taken a while for me to learn a small part of the answer to this question. I’m still working on a more complete answer, but “I’m not getting any younger” as they say – so I’ll post a partial answer here now, and try to augment it later:
Q: How to set an alarm that triggers the INT/SQW pin on the RTC (DS3231)?
If 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 two additional steps:
1. add the
wakeup-source parameter to the
2. write the alarm time to the file
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
And that’s it! The driver does all of the heavy lifting here, and your instructions to the driver are all contained in the
dtoverlay above. With this approach, you needn’t worry about using
i2c-tools to write to the DS3231’s internal registers – although they will allow you access to more of the DS3231’s functions.
Q: How Do I Use the Alarm to Accomplish Something Useful?
This will be covered in the next “installment” to this answer. If you’re still interested, you should get a copy of the spec sheet for the DS3231 (or the RTC you plan to use), and review it – at least briefly. Pay some attention to the
Block Diagram on page 8, in particular note the
INT/SQW open-drain output at pin 3.ShareEditFollowFlagedited 3 hours agoanswered 18 hours agoSeamus12.9k22 gold badges1616 silver badges3737 bronze badgesAdd a comment1This post is hidden. It was deleted last month by goldilocks♦.
How to write a Rpi4B/Pico Thonny Python program to talk to the DS3231 RTC (Real Time Clock) to do things such as the following:
- Detect interrupts,
- Trigger on chip square wave signals.
- I have searched my 3 year old posts (over 50) in rpi.org.forum to refresh my memory on how I messed around with DS3231, listening to its interrupts, and program/trigger the on chip 32kHz square signals etc.
- My old posts are messily scattered in a couple of forums and intermingled with other I2C devices such as MCP23017 IOX and ADS1115 ADC. Porting to Pico is a good opportunity for me to tidy them up.
- The OP would like to be able to set alarms to trigger the INT/SQW pin, so I am jumping start to this part. I would first paste the design parameters in Appendix A below, then show a python function on how to program this pin. This double function pin is a bit tricky to handle, you might need to choose SQW mode, program the square wave frequencies, then go back to enable INT, and when INT comes, you need to switch to SQW mode to trigger it. In short, it is a bit tedious and easy to go wrong, so I gave up and tried other workarounds, … 🙂
- DS3231 has two alarms, Alarm 1 and Alarm 2, as summarized in Appendix B. I am going to show how to set Alarm 1 for day, hour, min, sec.
- There are a couple of DS3231N moudles around in the market. For prototyping and evaluation, I would recommend to buy the most expensive, deluxe version, with a lot of pins to play with, address pins for multiple RTCs, and daisy chain I2C pins for easy extending signals. See Appendix C for more details
- Now I have written a little python program to detect the addresses of the devices on the two I2C buses of Rpi Pico. DS3231 and 24C32 EEPROM occupy addresses 0x68 and 0x57.
/ to continue, …
Long Answer (TL;DR)
/ to continue, …
/ to continue, …
Appendix A – DS3231 INT/SQ pin programming design notes
Appendix B – DS3231 Alarm programming design notes
Appendix C – Real Time Clock Module
Appendix D – Schematic and Pullups to remove to reduce capacitance to < 400pF
- I2C bus uasually has a capacitance limit of 400pF, exceeding which might cause I/O transmission errors.
- R4B I2C pins already have strong pullups of 1k8, so it is a good idea to remove the DS3231 and other devices’ on board pullups of usually 4k7, sometimes 10k
- It is also a good idea of keeping the I2C wiring short, less than 30cm if possible.
- It is also a good idea, especially during prototyping or troubleshooting, to use low frequencies for I2C, say 100kHz or even down to 50kHz, so that resulting impedance is less than 400pF.
Appendix E – Summary of MicroPython I2C I2C and RTC class and methods used to control DS3231
1. Example usage:
from machine import I2C i2c = I2C(freq=400000)
i2c.writeto(42, b’123′) i2c.readfrom(42, 4)
class machine.I2C(id, *, scl, sda, freq=400000)
3. General Methods
I2C.init(scl, sda, *, freq=400000) I2C.scan()
4. Standard bus operations
I2C.readfrom(addr, nbytes, stop=True, /) Read nbytes from the slave specified by addr. If stop is true then a STOP condition is generated at the end of the transfer. Returns a bytes object with the data read.
I2C.readfrom_into(addr, buf, stop=True, /) Read into buf from the slave specified by addr. The number of bytes read will be the length of buf. If stop is true then a STOP condition is generated at the end of the transfer. The method returns None.
I2C.writeto(addr, buf, stop=True, /) Write the bytes from buf to the slave specified by addr. If a NACK is received following the write of a byte from buf then the remaining bytes are not sent.
I2C.writevto(addr, vector, stop=True, /) Write the bytes contained in vector to the slave specified by addr. vector should be a tuple or list of objects with the buffer protocol. The addr is sent once and then the bytes from each object in vector are written out sequentially. The objects in vector may be zero bytes in length in which case they don’t contribute to the output.
class machine.RTC(id=0, …) Create an RTC object. See init for parameters of initialization
RTC.init(datetime) Initialise the RTC. Datetime is a tuple of the form: (year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
RTC.now() Get get the current datetime tuple.
Appendix F – Old Rpi python program for DS3231
The program list uploaded here yesterday is too long and hit the SE’s 30k words limit. The listing was ported from Chinese Windows 10 and edited to fit RpiSE format but stil has wrong formatting, funny charaters here is there. So I put the completed lising as a PenZu lab log, with this link:
- The program was written in pure functional programming style, with no global variables and no side effect. So it is easy to copy any DS3231 functions with their independent higher level variables, and paste as a module/package. In other words, never mind the pretty print, user menu, mux functions.
/ to continue, …
- 1FWIW, this is the module I need to program. – anon Apr 8 at 7:21
- Ah, your DS3231 RTC module is a “mini” version. It is small and therefore good if you want to save space. For prototyping, my module is better for the following reasons: (1) with address jumpers A0, A1, A2 to set 8 device address, so to use more than a DS3231 on the same bus. (2) With an EEPROM to store data. (3) Generously spaced components to easily modify circuits. eg. remove pullup resistors, modify battery charging options. See Ref 15 for more details. – tlfong01 Apr 8 at 14:47
- You recommended tutorial by All About Circuits is as good as mine. So I have included in to my reference list (Ref #18). Cheers. – tlfong01 Apr 9 at 13:44
- 1You still have
/ to continue, ...remarks in several places, but since it’s been over a week since your last edit, I assume you’re finished. I don’t understand how you mis-interpreted my question. It’s not a long, detailed question – but you even summarized it incorrectly. With no disrespect intended, this answer is not helpful. I’d like to delete my question. I don’t want to impact your efforts, so perhaps you could post your own question, and then copy & paste your answer there? – anon Apr 17 at 19:50
- Ah I did hesitate to update with this info. seeedstudio.com/…. I now have 6 or more Pico in hand, and 10 more are on their way from RS. I also have perhaps 10 Pico breakout boards in hand, mostly by perorder,. as soon as the morning I read the Google alert. I do have 3 Pico and 6 breadout boards from Seeed. RTS is not urgent for me, so I might just order them after I see the reviews. I also have more than 10 breakout boards from Piromori. Perhaps they have already been making RTC boards for Pico. – tlfong01 Apr 18 at 1:23
- There might be some misunderstand. I told you that your RTC breakout is a minimal version without terminals so not easy to extract the squarewave and 32k signal. So I thouht you either (1) gave up, because it was just a weekend fun project, (2) you have ordered the full version from Ebay, AliExpress, which I know might take 2 to 5 weeks to deliver. Recently I ordered MCP23S17 and the 4g LET box from AliExpress and it indeed take three weeks. / tonctinue, – tlfong01 Apr 18 at 1:30
- I usually order from TaoBao, and direct from Factory Flagship shop, and because I have a VIP account in most of the shops I regularly shop, and they can see my old orders are usually 10 times than the average clients, and almost pay my bill within 4 hours, so they usually give me special treatment and ship my goods within average 24 hours. – tlfong01 Apr 18 at 1:31
- I vaguely remember that I gave you a list of my old blog posts which include python programs on how to read DS3231 temperatue, ping a register, and include a program showing the dictionry struacure of the DS3231 registers (yes, borrowed from Arduino). I forgot if I told you that once you know how to read/write a DS3231 register, then the rest is easy. I know my python program in my blog is mingled with MCP23017 and mux with 8 DS3231 on the same I2C bus, so I thought you were able to handle it. Perhaps you are not experience in python.so if my program was in C, you could rewrte it in 1 hour. – tlfong01 Apr 18 at 1:37
- Anyway, perhaps I would try to search my old file directories and see if I can find a 3 year fold newbie friendly demo program for your reference. I will let you know perhaps in a couple of days. – tlfong01 Apr 18 at 1:39
- I am back. I have luck and quickly found from my messy old file box a year 2017 DS3231 program with the basic functions on read temperature, read DS3231 register, ping, set date, set alarms etc. They are all in functional programming style, ie no side effects, no global variable. So you can almost just copy an paste functions and their dependent functions upwards. PS – my old program is in last appendix. I did not upload the complete program listing, because I already hit the SE’s 30k word limit. – tlfong01 Apr 18 at 1:56
- So I actually cut the EEPROM part of the program. The original file in in Chinese Window file format. If you have problems or reading funncy charaters, I can try to compile a PenZu lab log for you. – tlfong01 Apr 18 at 1:59
- And because my program is actually a “package”, so I can import it to other programs. You see many of the mid level functions have parameters such as “demux number” and “device num”, because most of the low level stuff like device address, reg addr etc are also abstracted to numbers which can freely transfer among different levels of functions (but not “objects” which cannot flow up/down levels. If you have been doing functional programming in LISP, Scheme, ML, Haskell, LUA, Scala, Python, … you might find my programs very “expressive” and “self documenting”, with little/no comments. 🙂 – tlfong01 Apr 18 at 2:19
- This is not an answer to the question. – goldilocks♦ Apr 24 at 12:38
Comments disabled on deleted / locked posts / reviews