BINARY CLOCK #wendlersClock

by mefiur95 in Circuits > Clocks

264 Views, 3 Favorites, 0 Comments

BINARY CLOCK #wendlersClock

PXL_20221019_054253022.jpg
PXL_20221019_053719984.jpg
PXL_20221019_054116759.jpg

Hi, I wanted to share with you my recent project - DIY binary clock. My priority was the design and its simplicity to be true eye-catching.

The heart of binary clock is ATMega64 (programmed by ISP 6 pin connector) to control LEDs circuit and DS3231 as RTC.

I made a project of PCB in CircuitMaker and it was manufactured by JCLPCB in black color.

I have made two versions of final design:

  1. Orange LEDs 3528 with brown wood-PLA case,
  2. Blue LEDs 3528 with grey PLA case.

DS3231 is powered by CR2032 battery to "keep running time". Whole PCB is powered by micro-USB port.

When it comes to working principles - each digit in decimal representation of time (hours : minutes : seconds) is represented by a single LEDs column.

As design was my priority, I decided to choose only SMD components to avoid soldering pins on front part of PCB. The biggest problem I had was with micro-USB port - it had to be mounted vertical on PCB but I couldn't find it as SMD component. Finally, I had to bend THT pins of micro-USB port to solder it as SMD.

I am planning to post my binary clock on ebay in two variants:

  1. as a DIY package with all necessary components to solder,
  2. as a final and ready product seen on the photos

There are 3 buttons on the PCB - its functionality is described under programming section below. My binary clock has the functionality to display ambient temperature instead of seconds (temperature parameter is given by DS3231).

I am looking forward to your opinions and feedback :)

If you have any questions, please contact me: wendlersclock@gmail.com

Supplies

CircuitMaker_QiJV3rEOWN.png

Link to gerber files (.ZIP) of PCB:

https://www.dropbox.com/s/77lski6xfz8pmnj/wendlersClock_GERBER.zip?dl=0

List of components:

  • 1x ATmega64A-AU TQFP64
  • 1x DS3231 SOP-16
  • 1x crystal 16MHz 5032
  • 2x capacitor 22pF 0805
  • 4x capacitor 100nF 0805
  • 1x 6 pin male header 2x3 2.54mm
  • 20x LED SMD 3528
  • 22x resistor 4.7k 1206
  • 4x resistor 10k 1206
  • 1x vertical microUSB port
  • 3x tactile switch KSEK43GLFS
  • 1x CR2032 holder CH004-2032
  • 1x battery CR2032
  • 1x 3D printed case
  • 4x bolts to mount PCB M2x8



3D Printed Case

Slic3r_7FLJ0SOLJK.png
Slic3r_EjSJV5sfTJ.png
ApplicationFrameHost_DeLk3RStKH.png

Case of my wendlerClock is made of one piece to make things simple. I suggest printing the case with the front set down (see attached picture) with support material to make the front piece look nice and sharp.

You can also print the case with the back set down and then no support material is needed.

Nozzle: 0.5mm

Layer height: 0.25mm

Infill: 10%

Support material: YES

Programming Section

I wrote a programme using Arduino IDE v2.0.0 with MegaCore library that supports ATMega64. I used AVR Dragon and ISP interface (6 pin male header on the PCB) to programme microcontroller.

Working principles are pretty easy: microcontroller communicates with RTC DS3231 using I2C to get the current time in decimal format, then I had to display the time in the binary format.

You need to programme ATMega64 twice:

  • first programme is needed to set the current time to RTC DS3231 (you need to uncomment this line: //setTime(11, 00, 00, 21, 10, 2022);  // set the system time to 11h00m00s on 21Oct2022 and set it to current time)
  • second programme is needed to read the current time from RTC DS3231.

Libraries needed to compile the code:

  • MegaCore
  • DS3232RTC.h

There are 3 buttons on the PCB:

  • "+" -> increases current time +1min and resets seconds
  • "-" -> decrease current time -1min and resets seconds
  • "MODE" -> changes the function of displaying seconds to ambient temperature (parameter is given by RTC3231 to compensate temperature deviation. It is not very precise, but for this functionality is more than enough).

Arduino IDE programme:

#include <DS3232RTC.h>  // https://github.com/JChristensen/DS3232RTC

DS3232RTC myRTC;


#define buttonPlus 37   //przypisanie przycisku 1 do wejscia nr 37

#define buttonMinus 38  //przypisanie przycisku 2 do wejscia nr 38

#define buttonMode 39   //przypisanie przycisku 3 do wejscia nr 39


uint8_t ledPin[20] = { 28, 29, 30, 31, 32, 33, 35, 34, 24, 45, 14, 15, 25, 13, 16, 17, 46, 47, 48, 49 };  //tablica zawierajaca numery wyjsc na diody LED


int temperatureC = 0;


bool StateButtonPlus = 0;

bool StateButtonMinus = 0;

bool StateButtonMode = 0;

bool lastStateButtonPlus = 0;

bool lastStateButtonMinus = 0;

bool lastStateButtonMode = 0;

bool temp = 0, temp1 = 0, temp2=0;


void setup() {

  for (int i = 0; i < 20; i++)

    pinMode(ledPin[i], OUTPUT);


  pinMode(buttonPlus, INPUT);

  pinMode(buttonMinus, INPUT);

  pinMode(buttonMode, INPUT);


  myRTC.begin();

  setSyncProvider(myRTC.get);  // the function to get the time from the RTC

  setSyncInterval(900000);


  //setTime(11, 00, 00, 21, 10, 2022);  // set the system time to 11h00m00s on 21Oct2022

  myRTC.set(now());  // set the RTC from the system time

 

  testLeds();

}


void loop() {

  temperatureC = myRTC.temperature() / 4.0;

  if (temperatureC > 59)

    temperatureC = 0;


  //reading the states of buttons

  StateButtonPlus = digitalRead(buttonPlus);

  StateButtonMinus = digitalRead(buttonMinus);

  StateButtonMode = digitalRead(buttonMode);


  Hours2Leds(0);  //1. column

  Hours4Leds(2);  //2. column


  Minutes3Leds(6);  //3. column

  Minutes4Leds(9);  //4. column


  if ((StateButtonMode != lastStateButtonMode) && (StateButtonMode == 1) && (StateButtonPlus == 0) && (StateButtonMinus == 0))

    temp = !temp;


  if (temp == 1) {

    Temperature3Leds(13);

    Temperature4Leds(16);

  } else {

    Seconds3Leds(13);  //5. column

    Seconds4Leds(16);  //6. column

  }


  if ((StateButtonMinus != lastStateButtonMinus)  && (StateButtonMinus == 1) && (StateButtonPlus == 0) && (StateButtonMode == 0))

    temp1 = 1;

 

  if ((temp1 == 1)  && (StateButtonMinus == 1))

  {

      setTime(hour(), minute()-1, 00, day(), month(), year());

      myRTC.set(now());

      temp1 = 0;

  }

   if ((StateButtonPlus != lastStateButtonPlus)  && (StateButtonPlus == 1) && (StateButtonMinus == 0) && (StateButtonMode == 0))

    temp2 = 1;

 

  if ((temp2 == 1)  && (StateButtonPlus == 1))

  {

      setTime(hour(), minute()+1, 00, day(), month(), year());

      myRTC.set(now());

      temp2 = 0;

  }  


  //button state

  lastStateButtonPlus = StateButtonPlus;  // save the current state as the last state, for next time through the loop

  lastStateButtonMinus = StateButtonMinus;

  lastStateButtonMode = StateButtonMode;

  */

}


void testLeds() {

  for (int i = 0; i < 20; i++) {

    digitalWrite(ledPin[i], HIGH);

    delay(50);

  }

  delay(1000);

  for (int i = 19; i >= 0; i--) {

    digitalWrite(ledPin[i], LOW);

    delay(50);

  }

}

void Hours2Leds(int startLedPosition) {

  if (hour() < 10) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  } else if (hour() < 20) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

  } else if (hour() < 24) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  }

}

void Hours4Leds(int startLedPosition) {

  if (hour() % 2)

    digitalWrite(ledPin[startLedPosition + 3], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 3], LOW);

  if ((hour() % 10 == 2) || (hour() % 10 == 3) || (hour() % 10 == 6) || (hour() % 10 == 7))

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  if ((hour() % 10 >= 4) && (hour() % 10 <= 7))

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  if ((hour() % 10 == 8) || (hour() % 10 == 9))

    digitalWrite(ledPin[startLedPosition], HIGH);

  else

    digitalWrite(ledPin[startLedPosition], LOW);

}

void Minutes3Leds(int startLedPosition) {

  if (minute() < 10) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (minute() < 20) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (minute() < 30) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (minute() < 40) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (minute() < 50) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (minute() < 60) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  }

}

void Minutes4Leds(int startLedPosition) {

  if (minute() % 2)

    digitalWrite(ledPin[startLedPosition + 3], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 3], LOW);

  if ((minute() % 10 == 2) || (minute() % 10 == 3) || (minute() % 10 == 6) || (minute() % 10 == 7))

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  if ((minute() % 10 >= 4) && (minute() % 10 <= 7))

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  if ((minute() % 10 == 8) || (minute() % 10 == 9))

    digitalWrite(ledPin[startLedPosition], HIGH);

  else

    digitalWrite(ledPin[startLedPosition], LOW);

}

void Seconds3Leds(int startLedPosition) {

  if (second() < 10) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (second() < 20) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (second() < 30) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (second() < 40) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (second() < 50) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (second() < 60) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  }

}

void Seconds4Leds(int startLedPosition) {

  if (second() % 2)

    digitalWrite(ledPin[startLedPosition + 3], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 3], LOW);

  if ((second() % 10 == 2) || (second() % 10 == 3) || (second() % 10 == 6) || (second() % 10 == 7))

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  if ((second() % 10 >= 4) && (second() % 10 <= 7))

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  if ((second() % 10 == 8) || (second() % 10 == 9))

    digitalWrite(ledPin[startLedPosition], HIGH);

  else

    digitalWrite(ledPin[startLedPosition], LOW);

}

void Temperature3Leds(int startLedPosition) {

  if (temperatureC < 10) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (temperatureC < 20) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (temperatureC < 30) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (temperatureC < 40) {

    digitalWrite(ledPin[startLedPosition], LOW);

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  } else if (temperatureC < 50) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  } else if (temperatureC < 60) {

    digitalWrite(ledPin[startLedPosition], HIGH);

    digitalWrite(ledPin[startLedPosition + 1], LOW);

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  }

}

void Temperature4Leds(int startLedPosition) {

  if (temperatureC % 2)

    digitalWrite(ledPin[startLedPosition + 3], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 3], LOW);

  if ((temperatureC % 10 == 2) || (temperatureC % 10 == 3) || (temperatureC % 10 == 6) || (temperatureC % 10 == 7))

    digitalWrite(ledPin[startLedPosition + 2], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 2], LOW);

  if ((temperatureC % 10 >= 4) && (temperatureC % 10 <= 7))

    digitalWrite(ledPin[startLedPosition + 1], HIGH);

  else

    digitalWrite(ledPin[startLedPosition + 1], LOW);

  if ((temperatureC % 10 == 8) || (temperatureC % 10 == 9))

    digitalWrite(ledPin[startLedPosition], HIGH);

  else

    digitalWrite(ledPin[startLedPosition], LOW);

}