Project tutorial
DIY 3D Printed Single Digit Arduino Clock

DIY 3D Printed Single Digit Arduino Clock © GPL3+

One big digit, fully functional Arduino Nano clock.

  • 499 views
  • 0 comments
  • 3 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project


Another of a series of unusual clocks this time made with the help of a 3D printer.

To build this project we need the following components:

- Arduino Nano microcontroller board

- DS3231 Realtime clock module

- SMD5050 Led strip

- 8x 2N2222 or similar Transistors

- 8x 560 Ohm Resistors

- 2X buttons

- Led diode and 220 Ohm Resistor

I got the inspiration for making this clock from

http://8bitmicro.blogspot.com/2012/02/project-clock-two-single-digit-clock.html, but now with DIY 7-segment display made using a 3D printer and 5050 LED strip. The code is modified for DS3231 realtime clock which is also inexpensive but much more accurate thanDS1307. The LED strip can be cut on every third diode in series. In this case we should cut it on every second diode. For this purpose was made a small modification that you can see in the video. Each segment of the strip is driven by a 2N2222 or similar low power transistor.

For settings time we use two buttons. They are connected to digital pins eight and nine (with 10k pull-down resistors). The LED display segments a~g are connected to Arduino digital pins 0~6 respectively. The decimal point is connected to the pulse output pin of the DS3231 – which will be set to a 1Hz output to have a nice constant blinking LED to show the clock is alive and well.

Arduino and other electronics are housed in a convenient box with a 7-segment display above. Below is a link where you can download the code and.stl files for 3D print.

Code

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

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68 // the DS3231 RTC is 0x68

int timeDelay(3000); // 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 DS3231 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 DS3231
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock

// Assumes you're passing in valid numbers

void setDateDS3231(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(DS3231_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 DS3231
void getDateDS3231(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS3231_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.begin();   //TWI Bus is formed  
  Wire.beginTransmission(DS3231_I2C_ADDRESS); //device address and STSRT command are queued
  Wire.write(0x0E); //Control Register Address is queued  (or Wire.send)
  Wire.write(0x00); //Data for Control Register is queued (or Wire.send)
  Wire.endTransmission(); //queued information are transferred under ACK; STOP
}


// 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 DS3231

  hour = (h1*10)+h2;
  minute = (m1*10)+m2;
  if (hour<24 && minute <60) // in case user enters invalid time e.g. 2659h
  {
    setDateDS3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    sqwOn(); // turn on blinking decimal point again (setDateDS3231 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;
  getDateDS3231(&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
}

Custom parts and enclosures

3D files
3d_files_672RkoXRId.7z

Schematics

Schematic
Untitled sketch bb 24wsjsehrl

Comments

Similar projects you might like

DIY Gesture Controlled Talking Clock

Project tutorial by Mirko Pavleski

  • 1,040 views
  • 0 comments
  • 1 respect

3D Printed Lunar Phase Clock

Project tutorial by G4lile0

  • 7,736 views
  • 6 comments
  • 58 respects

Single LED Matrix Arduino Flip Clock

Project tutorial by Mirko Pavleski

  • 3,954 views
  • 2 comments
  • 16 respects

Analog, Digital Clock and Thermometer on 128x64 LCD

Project tutorial by Mirko Pavleski

  • 8,846 views
  • 11 comments
  • 29 respects

Digital Wall Clock

Project tutorial by Deep_Sky

  • 8,520 views
  • 5 comments
  • 24 respects

Arduino Nano "One Digit" Big LED Clock

Video tutorial by Mirko Pavleski

  • 1,781 views
  • 0 comments
  • 5 respects
Add projectSign up / Login