Archive

Archive for the ‘Chronodot’ Category

Chronodot library for Arduino

January 16th, 2011 1 comment

I wrote a library to talk to Chronodot real time clock based on DS3231 chip by Maxim. It is also possible to talk to the chip using Time library but it does not fully support the chip’s abilities and replicates the clock internally in Arduino, only updating the time from DS1307.

The library is in my git repository.

At this moment, it has functions to read and set date and time returning both decimal and BCD representation. It also controls SQW pin output. The next step is to implement setting and using both alarms that the chip supports. Take a look at the .h file and included example sketch for more info.

Categories: Arduino, Chronodot Tags:

Chronodot SQW and Arduino interrupts

January 11th, 2011 11 comments

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.

Categories: Arduino, Chronodot Tags:

Connecting Chronodot and setting the time

January 9th, 2011 10 comments

I want to build a clock, a precise one. For this purpose I got a Chronodot – extremely accurate and temperature compensated and battery backed real time clock module, based on the DS3231. The sample code on the website only shows how to read the time from the clock using Wire library. There is no info how to connect the thing to the Arduino. There is no code to show how to set the time. After reading the documentation and searching on-line I figured it out.

20110109-001

Chronodot uses I²C bus to talk to the outside world. Arduino accepts I²C connections on two analog intput pins. On most boards, SDA (data line) is on pin A4, and SCL (clock line) is on pin A5. Those are analog lines, not digital. So, connect pin A4 to Chronodot’s pin labeled SDA, and Arduino’s pin A5 to Chronodot’s pin SCL. Of course, +5V goes to VCC and GND to GND.

Based on the Time library and the DS3231 datasheet I wrote a library to talk to Chronodot, and a sketch with a Python script to set the time. Both are available in my git repository: Chronodot library, ChronodotSet sketch.

Load the ChronodotSet.pde into your Arduino and leave the unit connected to the PC. The set.py Python script will set the date and time over serial connection to either local PC time, time from a string, or time from NTP server (depends on Python serial library pySerial and NTP library for NTP functions). The time is rounded to the nearest second.

Without any options it sets the time to the local PC time and reads back the time reported by Arduino 5 times.

$ ./set.py  -h
Usage: set.py [options]

Options:
  -h, --help            show this help message and exit
  -d DEVICE, --device=DEVICE
  -s STRING, --string=STRING
  -n, --ntp
  --noreadback

$ ./set.py
Setting time from local time
Time has been set to 2011-01-16 18:31:38.503983
Reading time back
2011-01-16 18:31:38
2011-01-16 18:31:39
2011-01-16 18:31:40
2011-01-16 18:31:41
2011-01-16 18:31:42

$ ./set.py --device /dev/tty.usbmodem411 --string "2010-02-28 23:59:57"
Setting time from string 2010-02-28 23:59:57
Time has been set to 2010-02-28 23:59:57
Reading time back
2010-02-28 23:59:57
2010-02-28 23:59:58
2010-02-28 23:59:59
2010-02-29 00:00:00
2010-02-29 00:00:01

$ ./set.py --ntp --noreadback
Setting time from NTP server
Time has been set to 2011-01-16 18:33:39

Have fun. I’m getting to work on 7-segment displays.

Categories: Arduino, Chronodot Tags: