MCP7940 – RTC with Pi

As I’m building my own IQ house control system, I need to have RTC in my system. So started playing with MCP7940N and i2c interface. I’m using Raspberry Pi for my experiments with i2c/SPI.

Construction is pretty simple, just use MCP7840N Datasheet.

mcp7940n-schema

 

Then you can start checking with Pi. In my case, I’m using RevB, so my bus has number 1 and RTC got 0x6f address.

root@pi:~# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 6f
70: -- -- -- -- -- -- -- --

what next? Check address 0x00, if the onboard oscilator is running

root@pi:~# i2cget -y 1 0x6f 0x00 b
0x00

0x00 means NO, it’s NOT running. So, turn it on

root@pi:~# i2cset -y1 1 0x6f 0x00 0x80

and check few times address 0x00

root@pi:~# i2cget -y 1 0x6f 0x00 b
0x87
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x88
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x89
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x90
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x91

Increments! Great. That means – our oscilator is working = our clock is working too. Next step is to set current time and date. But wait. How are values stored and read/written? RTC uses BCD encoding for values, that means, eg. number 94 is stored as 9 and 4, both in 4 bits = 9 is stored as 1001 and 4 as 0100, in hexadecimal 0x94. Easy? Eg. day is using 6 bits, upper two for 0123 values, bottom bits for 0-9, so 31th will be stored as 0x31. For more details please read the PDF – RTCC Memory map. So back to setting the date & time:

# 2nd Feb 2014
root@pi:~# i2cset -y 1 0x6f 0x06 0x14
root@pi:~# i2cset -y 1 0x6f 0x05 0x02
root@pi:~# i2cset -y 1 0x6f 0x04 0x19
# 00:02:00
root@pi:~# i2cset -y 1 0x6f 0x02 0x00
root@pi:~# i2cset -y 1 0x6f 0x01 0x02
root@pi:~# i2cset -y 1 0x6f 0x01 0x80

Fine. But if we’re setting ’00’ as seconds – address 0x00 – why value 0x80? 7th bit = ST – onboard oscilator enabled.

I’ve written simple Python code to read from RTC and print out the value:

from time import sleep
import smbus
import time
import signal
import sys

bus = smbus.SMBus(1)
RTC_ADDR = 0x6f

ADDR_SEC = 0x00
ADDR_MIN = 0x01
ADDR_HOUR = 0x02

def signal_handler(signal, frame):
  sys.exit(0)

def bcd2bin(x):
  return (((x) & 0x0f) + ((x) >> 4) * 10)

if __name__ == "__main__":
  signal.signal(signal.SIGINT, signal_handler)
  while True:
    sec = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_SEC) & 0x7f)
    min = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_MIN) & 0x7f)
    hour = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_HOUR) & 0x3f)
    print "%02d:%02d:%02d" % (hour, min, sec)
    sleep(0.9) # nearly 1 sec

Just run by

root@pi:~# python rtc.py
00:35:41
00:35:42
00:35:43
00:35:44
00:35:45
00:35:46

Voila! :) RTC is up and running. I’d like to check tomorrow (resp. today) morning, if everything is still working correctly, and can create next module for my IQ house control system :)