Mirko Pavleski
Published © GPL3+

Arduino Nano "One Digit" Big LED Clock

As you can see in my videos, I have previously made several types of unusual clocks such as anHDD POV clock, IN1 Nixie clock, and others.

Arduino Nano "One Digit" Big LED Clock

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
DS1307 64 x 8, Serial, I²C Real-Time Clock
Maxim Integrated DS1307 64 x 8, Serial, I²C Real-Time Clock
×1
Linear Regulator with Adjustable Output
Linear Regulator with Adjustable Output
×1
General Purpose Transistor NPN
General Purpose Transistor NPN
×8
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×2
led 8mm warm white
×29
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×1
Resistor 220 ohm
Resistor 220 ohm
×8
560 ohm resistor
×8
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 10k ohm
Resistor 10k ohm
×2

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

schematic_pyTaHkpi7a.jpg

Code

Untitled file

Arduino
// Clock Two
// tronixstuff.com/projects > Clock Two
// John Boxall - February 2012 - March 2013
// Use Arduino v23 | CC by-sa-nc

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 // the DS1307 RTC is 0x68

int timeDelay(15000); // duration in ms between displaying time

// digits' PORTD representation. 0~9, A~F, "-"
byte segments[]={
  B00111111,B00000110,B01011011,B01001111,B01100110,B01101101,B01111101,B00000111,B01111111,B01100111,B01110111,B01111100,B00111001,B01011110,B01111001,B01110001, B01000000};

// usual DS1307 time functions
// See tronixstuff.com/tutorials > chapter twenty  for more information
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock

// Assumes you're passing in valid numbers

void setDateDs1307(byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7
byte dayOfMonth,    // 1-28/29/30/31
byte month,         // 1-12
byte year)          // 0-99
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));     
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.write(00010000); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
  Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void sqwOn() // turns on 1Hz output for decimal point blinking
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07); // move pointer to SQW address
  Wire.write(0x10); //  sends 0x10 (hex) 00010000 (binary)
  Wire.endTransmission();
}

void sqwOff()
// turns off decimal point blinking
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07); // move pointer to SQW address
  Wire.write(0x00); // turns the SQW pin off
  Wire.endTransmission();
}

// for information on "PORTD" etc see tronixstuff.com/tutorials > chapter 43

void loopNumbers() // for testing
{
  for (int a=0; a<16; a++)
  {
    PORTD = segments[a]; // digital 4~7 HIGH, digital 3~0 LOW
    delay(100);
  }
}

void blankLED()
// blanks LED display by setting all pins LOW
{
  PORTD = B00000000;
}


void displayTime1(int a, int b, int c, int d)
{
  int del=750; // delay between digits
  int bdel=100;
  PORTD = segments[a];
  delay(del);
  blankLED();
  delay(bdel);  
  PORTD = segments[b];
  delay(del);
  PORTD = segments[16]; // display hyphen
  delay(del);
  PORTD = segments[c];
  delay(del);
  blankLED();
  delay(bdel);  
  PORTD = segments[d];
  delay(del);
  blankLED(); // clear display
}

void setTime()
// user presses button A (digital 8) to enter 'set time' mode while time being displayed
// then user presses A to advance value, B to lock in. Repeat for four digits of time
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;  
  int h1=0;
  int h2=0;
  int m1=0;
  int m2=0;
  boolean set=false;
  blankLED();
  int debounce=200;

  do // get first digit of hours from user
  // press digital 8 button to change from 0>1>2>0>1...
  // press digital 9 to set value
  {
    PORTD = segments[h1];
    if (digitalRead(8)==HIGH)
    {
      delay(debounce);      
      h1++;
      if (h1>2)
      {
        h1=0;
      }
      PORTD = segments[h1];
    }
    if (digitalRead(9)==HIGH)
    {
      delay(debounce);      
      set=true;
    }
  } 
  while (set!=true);
  blankLED();
  set=false;  
  delay(500); 

  do // get second digit of hours from user
  // press digital 8 button to change from 0>1>2>...9>0...
  // press digital 9 to set value
  {
    PORTD = segments[h2];
    if (digitalRead(8)==HIGH)
    {
      delay(debounce);      
      h2++;
      if (h2>9)
      {
        h2=0;
      }
      PORTD = segments[h2];
    }
    if (digitalRead(9)==HIGH)
    {
      delay(debounce);      
      set=true;
    }
  } 
  while (set!=true);
  blankLED();
  set=false;    
  delay(500); 

  do // get first digit of minutes from user
  // press digital 8 button to change from 0>1>..5>0..
  // press digital 9 to set value
  {
    PORTD = segments[m1];
    if (digitalRead(8)==HIGH)
    {
      delay(debounce);      
      m1++;
      if (m1>5)
      {
        m1=0;
      }
      PORTD = segments[m1];
    }
    if (digitalRead(9)==HIGH)
    {
      set=true;
      delay(debounce);      
    }
  } 
  while (set!=true);
  blankLED();
  set=false;    
  delay(500); 

  do // get second digit of minutes from user
  // press digital 8 button to change from 0>1>..9>0..
  // press digital 9 to set value
  {
    PORTD = segments[m2];
    if (digitalRead(8)==HIGH)
    {
      delay(debounce);
      m2++;
      if (m2>9)
      {
        m2=0;
      }
      PORTD = segments[m2];
    }
    if (digitalRead(9)==HIGH)
    {
      set=true;
      delay(debounce);
    }
  } 
  while (set!=true);
  blankLED();
  set=false;    
  delay(500); 

  // now convert the user time data to variables to write to DS1307

  hour = (h1*10)+h2;
  minute = (m1*10)+m2;
  if (hour<24 && minute <60) // in case user enters invalid time e.g. 2659h
  {
    setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    sqwOn(); // turn on blinking decimal point again (setDateDs1307 seems to turn it off...
    PORTD = segments[16]; // display hyphen
    delay(500);
    blankLED();
    delay(500);
    PORTD = segments[16]; // display hyphen
    delay(500);
    blankLED();  
  }
}

void setup()
{
  DDRB = B00000000; // set d13~d8 as inputs for buttons
  DDRD = B11111111; // set d7~d0 as outputs for LED display
  Wire.begin(); // fire up I2C bus  
  blankLED();  // blanks display. 
  sqwOn(); // turn on blinking decimal point 
}

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  int h1, h2, m1, m2;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  h1=int(hour/10);
  h2=hour%10;
  m1=int(minute/10);
  m2=minute%10;
  displayTime1(h1,h2,m1,m2); // displays the time on the display
  if (digitalRead(8)==HIGH)
  {
    setTime();
  }
  delay(timeDelay); // arbitrary delay until next time display
}

Credits

Mirko Pavleski

Mirko Pavleski

150 projects • 1283 followers

Comments