Chronodot SQW and Arduino interrupts
My Arduino clock is being built, but I have to share a cool feature of Chronodot. It has a INT/SQW output, merked SQW on the board. It’s programable to be either a square-wave generator or an alarm interrupt line. The chip has two alarms that can be set, and if one of them goes off, the INT/SQW line becomes active. It’s all documented in the datasheet. Let me concentrate on the sqare-wave generator.
My first clock’s main loop looked like this:
void loop() { displayTime(); delay(1000); }
I display the time and wait one second, then display the time, and so on, forever. But that one second wait is not very accurate and my displayTime() function reads the time from the RTC sometime in the middle of its second. This can be solved by the SQW and interrupts.
I set the Chronodot to generate 1Hz sqare-wave on its SQW output. That is one beat per second, and it’s gonna be accurate because I’m working with an accurate RTC. I feed that sqare wave into one of the Arduino digital inputs pins and register an interrupt function, that will be triggered every time the wave is at its falling edge (changing from high to low). Here is the setup code:
#define INTERRUPT_PIN 3 void setup() { Wire.begin(); set1Hz(); // register interrupt function to 1Hz line pinMode(INTERRUPT_PIN, INPUT); attachInterrupt(1, oneHzInterruptHandler, FALLING); } void set1Hz() { // Frequency is stored in register 0x0e in bit 3 and 4 Wire.beginTransmission(CHRONODOT_ID); Wire.send(0x0e); Wire.endTransmission(); Wire.requestFrom(CHRONODOT_ID, 1); uint8_t register0E = Wire.receive(); // clear bits 3 and 4 for 1Hz register0E &= ~(1 << 3); register0E &= ~(1 << 4); // put the value of the register back Wire.beginTransmission(CHRONODOT_ID); Wire.send(0x0e); Wire.send(register0E); Wire.endTransmission(); }
Right there, I configured the Chronodot’s generator to 1Hz and registered the handler. The frequency is stored in bit 3 and 4 of register 0x0E.
One word about interrupt handlers. They have to be quick. They should only set a flag or do a quick calculation. My handler sets a global flag that tells the main loop to display the time.
boolean displayNow = false; void loop() { if (displayNow == true) { displayTime(); displayNow = false; } } void oneHzInterruptHandler(void) { displayNow = true; }
That’s all. The clock is ticking more accurately now.