Featured PostsHackerspaceMain Stories

Clocks, I2C, Serial and You

I bought a bunch of parts awhile back with the good intention of building a bright, blue LED clock for my desk at work. Unfortunately, I got side tracked and the parts sat in my parts bin for a month or two. When I had a little too much caffeine in my system last weekend, I hit the parts box and built that clock. Needless to say it wasn’t as easy as it looked…

Parts List

  • 1x Arduino
  • 1x Sparkfun Serial 7-Segment Display
  • 1x Macetech Chronodot
  • 1x Solderless Breadboard

Wiring

  • SFE Display Slave Select to Pin 10
  • SFE Display MOSI to 11
  • SFE Display MISO to 12
  • SFE Display SCK to 13
  • SFE Display VCC to 5v
  • SFE Display GND to GND
  • Chronodot SDA to Arduino Pin 4
  • Chronodot SCL to Arduino Pin 5
  • Chronodot VCC to 5v
  • Chronodot GND to GND

Code

The code below is a modified version of the Chronodot demo code. If you uncomment the set_time() call, it will set the time to the HH:MM passed to the function.

#include 
#include 

int ss = 10; //csn
int mosi = 11;
int miso = 12;
int sck = 13;

void setup()
{
  //chronodot
  Wire.begin();
  
  //Display
  Serial.begin(9600);
  
  //Set baud
  Serial.write(0x7F);
  Serial.write(0x02);
  
  //Reset display
  Serial.write(0x7A);
  Serial.write(0x76);
  
  //Set brightness
  Serial.write(0x7A);
  Serial.write(0x01);
  
  //Set colon
  Serial.write(0x77);
  Serial.write(0x10);
  
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock
  // keeps running on just battery power. Once set,
  // it shouldn't need to be reset but it's a good
  // idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.send(0x0E); // select register
  Wire.send(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
  //set_time(23, 59, 00);
}
 
void loop()
{
  // send request to receive data starting at register 0
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.send(0); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3); // request three bytes (seconds, minutes, hours)
 
  while(Wire.available())
  { 
    int seconds = Wire.receive(); // get seconds
    int minutes = Wire.receive(); // get minutes
    int hours = Wire.receive();   // get hours
 
    seconds = (((seconds & 0b11110000)>>4)*10 + (seconds & 0b00001111)); // convert BCD to decimal
    minutes = (((minutes & 0b11110000)>>4)*10 + (minutes & 0b00001111)); // convert BCD to decimal
    hours = (((hours & 0b00100000)>>5)*20 + ((hours & 0b00010000)>>4)*10 + (hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
 
    //Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.println(seconds);
      
    displayTime(hours, minutes);
  }
  
  //Set colon on
  Serial.write(0x77);
  Serial.write(0x10);  
  delay(500);
  //Set colon off
  Serial.write(0x77);
  Serial.write(0x01);
  delay(1000);  
}

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

void displayTime(int hours, int minutes){
  String h_str = String(hours);
  if(h_str.length() < 2){
    h_str = '0'+h_str;
  }
  
  String m_str = String(minutes);
  if(m_str.length() < 2){
    m_str = '0'+m_str;
  }
  
  String timeStr = h_str;
  timeStr.concat(m_str);
  
  Serial.write(timeStr.charAt(0));
  Serial.write(timeStr.charAt(1));
  Serial.write(timeStr.charAt(2));  
  Serial.write(timeStr.charAt(3));
}

void set_time(int hours, int minutes, int seconds)
{
   Wire.beginTransmission(104);
   Wire.send(0);
   Wire.send(decToBcd(seconds));
   Wire.send(decToBcd(minutes));
   Wire.send(decToBcd(hours));
   Wire.endTransmission();
}

 

One thought on “Clocks, I2C, Serial and You

  • We need to see if we can grab the i2c pins on the ATMEGA328 that is on the back of that 7-segment display and have it talk directly to the chronodot – it would greatly reduce the parts cost…and be the basis for an awesome digital watch 🙂

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *