Arduino Clock

bm005 real time clock

An Arduino clock and calendar is easy to build using the BM005 clock module.  The heart of the module is Microchip’s MCP79400 I2C RTCC.  The MCP79400 has a number of cool features, including leap year compensation, battery back-up (with an external battery), time/date storage on power failure, 12 or 24 hour format, and even some extra RAM if you need it.  Our BM005 puts it all in an easy to use module for a retail price of $12 (BM005 datasheet).

Interfacing the BM005 clock module to an Arduino is simple affair.  The A4/A5 pins are used for SCL/SDA I2C lines, and the module can be powered directly from the Arduino.  If you want a battery backed system you need to provide a battery at pin 4, VBAT, and set a bit in the MCP79400 register #3.

image

As for the code to initialize a clock/calendar, it’s pretty simple as well.  I’ve got a lot of comments embedded in it, but if you strip those away it takes 25-30 lines of code to write the time and date and read it back.  The code also uses the “wire” library which incorporates functions for I2C communication.  Here’s a link to the zipped up code file…

BM005_Arduino_read_write_time_date.zip

Below are screen captures of pieces of the code with some explanations.  Some of the comments are cut off in the screen grab,  the code linked above has all of comments if you need them.

You only need a few hardware connections (power, ground, SCL, SDA) and I used the Wire.h library for the I2C functions.  A serial port is opened to allow the code to use the Arduino serial monitor functions.   This code uses a 7-byte array to read and write clock and calendar data, and I’ve declared a single variable for use with for…next loops.  Pretty basic.

The TimeDate[byte] array is filled with values setting the date and time to 11/28/12 (November 28th, 2012) and 20:10:23 (8:10:23PM).  You have to set the highest bit of the seconds register to enable the clock’s oscillator.  In fact, one thing I don’t really like about the MCP79400 is the fact that the date and time registers tend to have useful bits located in their unused portions of various registers.  One example is the highest bit of register 0, which enables the onboard oscillator turning on the clock.  Another example is in register 3, the day of the week register.  Bit 3 of that register is used to enable battery back-up mode.  It would have been better if Microchip put all of these bits into a separate register.  But since that’s not the case you just have to know where they are and account for them.

Once the array is populated you just write to registers to the clock module using the I2C interface.

image

Once those registers are written the clock is off and running.  To read the current contents of the MCP79400 registers you use the I2C interface and read the values into the TimeDate[byte] array.

The data is in binary coded decimal (BCD).  So hexadecimal 0x28 is encoded so the upper nibble carries the 10’s digit, and the lower nibble the 1’s digit.  To convert this to a decimal value you can…

Get the upper nibble by dividing the byte by 16 –>  Upper Nibble = Byte/16 (I used a “>>4”, which in C is rotate 4 times to the right, the same as dividing by 16).

Get the lower nibble by clearing the upper nibble of the byte –> Lower Nibble = Byte AND 0x0F

Then multiply the upper nibble by ten and add the lower nibble to it –> decimal value = Upper Nibble*10 + Lower Nibble

As mentioned earlier some of the registers use bits to indicate or maintain certain functions.  These are all in the upper nibble of each register.  For this reason the upper nibble of each register is masked to clear these bits before I rotate it.

image

When you enable the serial monitor you should see the text below.  A new line shows up each second.

image

Comments

  1. When I tried the code it says that wire was not declared in the scope. Do you now why?

  2. Good morning Tom,

    If you download the linked version of the code you’ll find that the Wire.h library is included above the setup() function. The code below is right above setup().

    #include

    byte TimeDate[7]; // an array used to write and read time date data
    byte i;

    If that’s not your issue then make sure that the Wire.h library is included in your Arduino software installation. It was included in mine, and should be part of any recent installation.

    Lon

    • Oops, looks like the blog interface sees the C code as html and strips text that follows the #include. The include should be…

      #include (less than symbol)Wire.h(greater than symbol)

      You can see it more clearly if you download the code example.

      Lon

Speak Your Mind

*