BINARY CLOCK #wendlersClock
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:
- Orange LEDs 3528 with brown wood-PLA case,
- 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:
- as a DIY package with all necessary components to solder,
- 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
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
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
Downloads
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);
}