Bus Pirate, I2C, ChronoDot

Around the same time that I acquired a Bus Pirate I also acquired a ChronoDoh which is just the same as the traditional ChronoDot but the pins are soldered to the wrong side of the printed circuit board (PCB). This small error saved me 50-percent on the purchase cost. With my Bus Pirate and ChronoDot in hand I set out to learn how to use both. This document introduces using the Bus Pirate with I2C decices such as the ChronoDot’s DS3231 real time clock (RTC).

The ChronoDot RTC is an extremely accurate real time clock module, based on the DS3231 temperature compensated RTC (TCXO). It includes a CR2016 battery which should last at least 8 years if the I2C interface is only used while the device has 5V power available. No external crystal or tuning capacitors are required.

Macetech Documentation

Getting Started

I’m using a Bus Pirate v3a running firmware v5.10 and bootloader v4.1. The ChronoDot appears to be a first generation unit, though no version is printed on the PCB though it does have a date of 2009. The ChronoDot is really just a break out board for a Dallas Semiconductor real time clock (RTC) module, so I’m just going to start calling it what it is, DS3231.

Resources (Very helpful links)

This is my first time to use either a Bus Pirate or a DS3231. Also, it has been some time since I last used the I2C protocol, the method by which communication with the DS3231 occurs, so I included some I2C resources as well.

Using nothing more than these links I was able to figure out everything I needed to use the Bus Pirate in I2C mode to communicate with the DS3231 (ChronoDot).

I’ve also attached my PDFs because I make annotations (highlighting, notes, etc.) in them.

Wiring Connections

For I2C communication with the Bus Pirate there are a few probe wires that need to be connected to the DS3231 breakout board.

Connect the Bus Pirate’s Ground (GND), +5V (VCC), Clock (SCL) and MOSI (SDA) to the breakout board. The parenthesis indicate the pin to connect to on the breakout board. VCC could be set to +3.3V if desired.

In addition, connect the Bus Pirate’s voltage pull-up (VPU) pin to the VCC pin on the breakout board. This sets the pull up voltage, otherwise you will get an error and the I2C will not work.

Testing the Bus Pirate and DS3231 Breakout

I’m not too concerned with using all the features of the DS3231 and as such I’m just going to set some values on the DS3231 and see if I can read them back. Specifically I am going to set the memory locations 00h through 06h to zero and then read them back a few seconds later to watch the time tick.

For more information on the what is stored at each register location on the DS3231 see figure 1 in the datasheet. My attached version of the datasheet and I2C specification include highlighted text on the information that was useful to me.

Grab your virtual terminal program like minicom, cu, screen, hyperterminal or some other to used to communicate with the Bus Pirate. I use screen on my Darwin system, minicom on Linux, Hyperterminal on Windows.

# Start serial terminal
screen /dev/tty.usbserial-A1004cjH 115200

# Should see HiZ> prompt, try '?' for help

# Change mode to i2c
# Choose I2C mode
# Standard mode (100kHz maximum clock rate)

# Turn power supplies ON

# Turn on pull up resistors, if you get an error check VPU pin.
# Check VPU is at or near +5V. Look at column 5 (VPU) and the fourth row 

# List available macros for I2C mode
# Use the address search macro to find ChronoDot address, use the 
# DS3231 datasheet to confirm or vise versa to test datasheet coolness.

# Write to seven registers starting at word address 00h
# See figure 3 of DS3231 datasheet, this follows that format exactly
# The Bus Pirate handles the acknowledge bit for you
# The brackets [,] are stop and start for the I2C protocol
I2C>[0xD0 0 0 0 0 0 0 0 0]

# Write the starting memory address (00h) in preparation to read
I2C>[0xD0 0]

# Read the seven registers we just wrote to, remember time is ticking
# See figure 4 of DS3231 datasheet for read format
# The r:7 notation means read 7 times, this is in the Bus Pirate documentation
I2C>[0xD1 r:7]

# Write and cue the memory is possible in a single line
I2C>[0xD0 0 0 0 0 0 0 0 0 [0xd0 0]

# Now just read
I2C>[0xD1 r:7]

# If reading repeatedly is something of interest it wouldn't
# work as expected if just repeating I2C>[0xD1 r:7]
# Instead try setting the memory address to start reading
# and then read all in one line. Try it and watch time tic.
I2C>[0xD0 0 [0xD1 r:7]

# Power down power supply when ready
# Check that voltage returned to 0

# Place the Bus Pirate back in high impedance mode

# Now back where we started

Possible Problems and Solutions

Warning: no voltage on Vpullup pin

Connect a voltage to the Vpullup pin of the Bus Pirate. In this case the +5V VCC of the ChronoDot will work well, especially with a nice header pin to connect to.

Converting between binary, hex, decimal, octal

Try the example Python3 one-liner or change the Bus Pirate’s display format using the ‘o’ command.

# convert 0x68 to base-10, base-16, base-8, base-2 formats using python3
"int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(int(’68’,16))


Interfacing the Bus Pirate with a DS3231 RTC using I2C is pretty straight forward when you have all the resources aggregated together. In the above terminal session I demonstrated how to prepare the Bus Pirate for reading and writing via I2C mode. In addition I demonstrated three variations of writing and retrieving information from the DS3231 RTC using the Bus Pirate’s menu interface.

The first time was a plain and simple write, set memory address, then read from that address using three expressions. This method doesn’t allow for quick successive reads as the memory address has to be set again before another read can occur.

I2C>[0xD0 0 0 0 0 0 0 0 0]
I2C>[0xD0 0]
I2C>[0xD1 r:7]

The second time wrote to the memory then cued it for reading using only two expressions. While fewer expressions were used it still requires the same amount of expressions for successive reads.

I2C>[0xD0 0 0 0 0 0 0 0 0 [0xD0 0]
I2C>[0xD1 r:7]

The third method performed the write in one expression and then set the read address and performed the actual reading in a second expression. This method allows successive reads just by reissuing the last expression.

I2C>[0xD0 0 0 0 0 0 0 0 0]
I2C>[0xD0 0 [0xD1 r:7]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s