i2c and a Dallas RTC Anyone??

So yeah.. I wish that the Wire lib didn't take as much space.. What are you using the straight C++ for?

No particular reason, just as a C hacker used to the command line, I like to get the GUI out of the way. I haven't really had a reason to optimize for space yet but may look into it if I get close to the limit.

I've thought about getting this to drive a Nixie tube clock that I plan on building and using the Arduino to control the tubes.

I liked the idea of the RTC, that way when I power the clock I will automatically have the time. Just wondering if it's worth the $15 or if I should just get some push buttons to increment the hour/minutes and set it every time.

I do think though using the RTC breakout board from Sparkfun would save me a lot of code when I can just pull the values from the RTC, convert to binary and send off to the 74141 IC that is driving the Nixie.

I like the RTC approach simply because it's less hassle. If you don't want to drop $15, you can get the DS1307 in a DIP package for $4 from Digikey (of course, then you still need the battery, the crystal, etc). You don't even have to convert the values from the RTC -- they are BCD just like the 74141 expects, but you do have to mask off the AM/PM bits, clock enable, etc.

My project is going to use four large LED-based 7 segment displays, but the clock functionality is kind of a side thing.

I like the RTC approach simply because it's less hassle. If you don't want to drop $15, you can get the DS1307 in a DIP package for $4 from Digikey (of course, then you still need the battery, the crystal, etc). You don't even have to convert the values from the RTC -- they are BCD just like the 74141 expects, but you do have to mask off the AM/PM bits, clock enable, etc.

My project is going to use four large LED-based 7 segment displays, but the clock functionality is kind of a side thing.

I like the RTC approach as well since it is only $15 and it would then mean I have a very accurate clock that I can move and not worry about resetting the time. Plus it will save me room for other logic (I might interface temperature and any other sensors I can find to generate information to display).

Plus this will most likely sit on my desk at work and I might put it away when I leave the office. So plugging it in each morning and have it automatically set the time will be great.

Thanks for the code as well up top! That will definitely come in handy.

Hi there, I have modified slightly the code to give me the full set of data the module outputs, and removed the code specific to the display.

the problem I'm getting is that the data returned doesn't seem to make much sense... :slight_smile:

/* 
 * A single-digit clock
 * (c) 2007 Bob Copeland <me at bobcopeland.com>
 */

#include <Wire.h>


void setup()
{

  Wire.begin();
  Serial.begin(9600);

  /*
    // program the time & enable clock
   Wire.beginTransmission(0x68);
   Wire.send(0);
   Wire.send(0x00);
   Wire.send(0x52);
   Wire.send(0x80 | 0x21);
   Wire.endTransmission();
   */
}

void loop()
{
  // reset register pointer
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.endTransmission();
  delay(100);

  Wire.requestFrom(0x68, 6);
  char secs = Wire.receive();
  char mins = Wire.receive();
  char hrs = Wire.receive();
  char day = Wire.receive();
  char date = Wire.receive();
  char month = Wire.receive();
  char year = Wire.receive();

  Serial.print("time is: ");
  Serial.print( hrs, DEC );
  Serial.print(":");
  Serial.print( mins, DEC );
  Serial.print(":");
  Serial.print( secs, DEC );
  Serial.print(" day, ");
  Serial.print( day, DEC );
  Serial.print(" date, ");
  Serial.print( date, DEC );
  Serial.print(" month, ");
  Serial.print( month, DEC );
  Serial.print(" year, ");
  Serial.print( year, DEC );
  Serial.println();

  delay(1000);

}

this what the module is outputting

time is: 34:49:66 day, 2 date, 5 month, 5 year, 0
time is: 34:49:67 day, 2 date, 5 month, 5 year, 0
time is: 34:49:68 day, 2 date, 5 month, 5 year, 0
time is: 34:49:69 day, 2 date, 5 month, 5 year, 0
time is: 34:49:70 day, 2 date, 5 month, 5 year, 0

I guess it has to do with the clock config, how do you go about configuring the module for your own time? I am a I2C newbie :-? and I'm not making much sense of the address map below:

Thanks.

Hi there, I have modified slightly the code to give me the full set of data the module outputs, and removed the code specific to the display.

the problem I'm getting is that the data returned doesn't seem to make much sense... :slight_smile:

time is: 34:49:66 day, 2 date, 5 month, 5 year, 0
time is: 34:49:67 day, 2 date, 5 month, 5 year, 0
time is: 34:49:68 day, 2 date, 5 month, 5 year, 0
time is: 34:49:69 day, 2 date, 5 month, 5 year, 0
time is: 34:49:70 day, 2 date, 5 month, 5 year, 0

Thanks.

Well first things first, you need to mask off a few bits on the second and the hrs. Note in the original code there was "hrs & 0x3f" when it was writing it, and "secs & 0x7f".. yes that should've been up there on the same line with Wire.receive() but oh well. This is because the 'clock halt' sits in the top bit of secs and there are all kinds of state variables in the top 3 bits of hrs.

Looking at the diagram, note that date is split into two nibbles - the most significant holds '10 date'. The date is stored in BCD so for the 31st day of the month you'd see 0x31 instead of e.g. 0x1f if it were straight binary.

To program the clock (which you may not need to do after fixing the above) just uncomment the code at the top, and pick reasonable values for the time/date. It was originally set for 9:52pm. Make sure the CH bit is zero or the clock won't run. I also think there's a bug up there, 0x80 should've been 0x40 when setting the hours to 24 hour time.

HTH,
Bob

Bob thanks for your reply, the time display issue seems to be solved now.

What I am still struggling with is the module configuration. To set it to 17:31:00 Monday, 2-7-2007 I am doing the following on setup()

Wire.beginTransmission(104); // transmit to device #104, the ds1307
  Wire.send(0);
  Wire.send(0x00);
  
  Wire.send(0);  //sec
  Wire.send(31); //min
  Wire.send(17);  //hour
  Wire.send(2);  //day
  Wire.send(2);  //date
  Wire.send(7);  //month
  Wire.send(7);  //year
  Wire.endTransmission();    // stop transmitting

  delay(100); /* */

when printing back the values, I get:

21:05:32 Sunday, 2/2/2007

something its obviously not working.. :stuck_out_tongue:

Wire.beginTransmission(104); // transmit to device #104, the ds1307
Wire.send(0);
Wire.send(0x00);

You have an extra 0 in there I think. You just need to send one to set the register pointer.

yep, that's done the trick. One final thing if I'm setting the hour to be 6, how do I know if its am or pm? or how can I set it to be 18:00 instead of 6?

Many thanks,

yep, that's done the trick. One final thing if I'm setting the hour to be 6, how do I know if its am or pm? or how can I set it to be 18:00 instead of 6?

That's what the high bits of the hour are for. From the datasheet, you have in the top nibble: bit 2 selects 12 or 24 hour time, bit 1 is either the am/pm indicator or the high bit of the 24 hour time.

So use (0x40 | your_time) for 24-hour, or ( ((is_am) ? 0 : 0x02) | your_time) for am/pm mode.

I also thought about getting this to drive a clock and be very hands off, and for me that means adjusting for DST so once set I shouldn't have to touch it. I've written code that barely fits into an ATMEGA8 that adjusts automatically for DST in the US...granted that you can't set the time w/the code, the 1307 has to already have your standard time in it, but it's pretty neat I think nonetheless. Of course you could just use a in input and flip a switch to tell the arduino to adjust or not, but this is all in software and automagic.

So use (0x40 | your_time) for 24-hour, or ( ((is_am) ? 0 : 0x02) | your_time) for am/pm mode.

This is some really bad advice btw. I need to go back to bit shifting school.

24 hour mode: just use your_hour with no ORs (bit 6 - 0=24 hr, 1=12 hr)
12 hour mode: use -
0x40 | ((is_am) ? 0 : 0x20) | your_hour

your_hour should be binary-coded decimal (so 0x13 == 1pm in 24 hour mode).

I also thought about getting this to drive a clock and be very hands off, and for me that means adjusting for DST so once set I shouldn't have to touch it.

Nice!

So when using the Wire library you need to manually hook up a pull-up resistor. I was playing around with the digital lines trying to use the internal pullup resistors and get the I2C communication going myself. I could never even get the first ACK.

Why is the Wire library on the analog lines? Is there something I am missing in regards to the complexity of communication over an I2C interface with arduino?

Do any of you know of any successful attempts at a wire type library using the digital lines?

Thanks!
Lucas

I think to use I2C you have to use the analogue pins 4 and 5. if you look at the pin descriptions http://www.arduino.cc/en/Hacking/Atmega168Hardware you can see SCL and SDA are there. Maybe i'm wrong though and it is possible to use the digital pins.

yes - found out those pins you get hardware support.
I'm going to attempt to code it all myself on the digital pins because I wanna learn!

So when using the Wire library you need to manually hook up a pull-up resistor. I was playing around with the digital lines trying to use the internal pullup resistors and get the I2C communication going myself. I could never even get the first ACK.

Why is the Wire library on the analog lines? Is there something I am missing in regards to the complexity of communication over an I2C interface with arduino?

I2C requires the external pull up resistors. Its not a Arduino thing.

I'd advise against trying to do I2C manually. Its not simple especially when compared with SPI.

I2C uses the analog pins because thats just where the required hardware is.
The analog pins are actually normal digital pins with analog functionality. Elsewhere on these forums explains how to use them as digital I/O.

Arduino has internal pullup resistors! not on those pins tho. do they not work for I2C?

Not entirely sure how it works. Its not exactly difficult to throw in your own pull ups though so no reason not to.