Close
Binary Clock 3

Binary Clock 3

Well I finally soldered it all up after finalising the board layout and ironing out bugs in the software.

Final Schematic:

Final Board Layout:

Here are the parts:
BOM:
1 x Perfboard
1 x ATtiny44 MCU
17 x LEDs
2 x switches
2 x 10K resistors
2 x 7 pin female headers
2 x 12 pin female headers
1 x 10 pin female header
1 x 3 pin connector
Total cost is about £2.50 (if you buy the items in bulk just to have them available – it would probably cost a bit more if just buying the individual items as a one off for this project).
I added 3 additional strips of machined female header pins for the LEDs, (not shown in the above picture, so I could play about with what LEDs are used, rather than being stuck with what is soldered in place.

Here is the rear of the board showing the wiring, solid wires are legs from cut off LEDs soldered in other projects, the blue wire is Kynar 30awg wrapping wire.

I also had to strip out all of the debug code from the software as it was too big for the ATtiny44, it would be fine on an ATtiny84, I still wired up the TX connection should I decide to use an 84 and still want to see debug output via TinyDebugSerial.
I also had to renumber the output pins based on how Arduino numbers them for an ATtiny44:
Final version of the code (all of the previous debug messages have been removed):
#include <Bounce.h>

#define TONEPIN 3           // digital pin 3 (pa7) used as tone output
#define BUTTON1 1           // digital pin 0 (pb1) used to set clock
#define BUTTON2 4           // digital pin 6 (pa6) used to set clock

int masterClock = 0;
int lastsec = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
int hms = 0;
int sw1 = 0;
int sw2 = 0;
int both = 0;
boolean sw1on = false;
boolean sw2on = false;
boolean bothon = false;

const int nPins = 5;
const int pins[] = {6, 7, 8, 9, 10};
const int clock[17][2] = { {6, 7}, {6, 8}, {7, 8}, {8, 9}, {8, 10}, {9, 10},    // Seconds LEDs
                           {7, 6}, {8, 6}, {8, 7}, {9, 8}, {10, 8}, {10, 9},    // Minutes LEDs
                           {9, 6}, {6, 9}, {6, 10}, {10, 7}, {7, 10} };         // Hours LEDs

Bounce button1 = Bounce(BUTTON1, 5);  // set 5ms debounce for BUTTON1
Bounce button2 = Bounce(BUTTON2, 5);  // set 5ms debounce for BUTTON2

void setup() {
  attachInterrupt(0, tick, RISING); // call ISR on rising input to INT0 (digital pin 2)
  pinMode(TONEPIN, OUTPUT);  // setup tonepin for output
  tone(TONEPIN, 8000);       // generate 8000Hz tone on digital pin 4 to act as clock input for ISR
  pinMode(BUTTON1, INPUT);   // setup button1 for input
  pinMode(BUTTON2, INPUT);   // setup button2 for input
}

void tick() {                // Interrupt Service Routine to generate 1 second “tick”
  masterClock++;             // increment clock counter
  if (masterClock == 8000) { // 8000 reached (8MHz) 16000 (16MHz)
    seconds++;               // increment seconds
    masterClock = 0;         // reset masterClock
  }
}

void turnon(int led) {
  int Vcc = clock[led][0];
  int Gnd = clock[led][1];
  pinMode(Vcc, OUTPUT);
  pinMode(Gnd, OUTPUT);
  digitalWrite(Vcc, HIGH);
  digitalWrite(Gnd, LOW);
}

void alloff() {
  for (int i = 0; i < nPins; i++) {
    digitalWrite(pins[i], LOW);
    pinMode(pins[i], INPUT);
  }
}

void showtime(int Value, int Width, int Offset) {
  int mask;
    for (int i = 0; i < Width; i++) {
      mask = 1 << i;          // shift bit mask by current position
      if (HIGH && (Value & mask)) {      // check if LED should be lit
        turnon(Offset + i);   // turn on the LED
        alloff();
      }
  }
}

void loop() {
  // Check if buttons have been pressed  
  button1.update();                // update button1
  button2.update();                // update button2
  sw1 = button1.read();            // button 1 state
  sw2 = button2.read();            // button 2 state
  both = sw1 && sw2;               // both state

  if (sw1 == 0) sw1on = false;
  if (sw2 == 0) sw2on = false;
  if (both == 0) bothon = false;

  // toggle setup states if both buttons are pressed and then released together
  if (both && !bothon) {
    if (hms == 0) hms=1;       // toggle hours/minutes/seconds to hours if entering setup mode
    else hms = 0;              // toggle hours/minutes/seconds to off if leaving setup mode
    bothon = true;             // set flag for both buttons on
  }

  // set hours(1), minutes(2), or seconds(3)
  if ((hms != 0) && sw1 && !sw1on && !bothon) {
    hms++;                            // toggle hours/minutes/seconds
    if (hms == 4) hms = 1;            // reset back to hours if hms goes beyond seconds
  sw1on = true;
  }
  
  if ((hms != 0) && sw2 && !sw2on && !bothon) {
    if (hms == 1) {
      hours++;
      if (hours == 24) hours = 0;
    }
    if (hms == 2) {
      minutes++;
      if (minutes == 60) minutes = 0;
    }
    if (hms == 3) {
      seconds = 0;
    }
    sw2on = true;
  }
    
  // Adjust the time based on seconds passed
  if (seconds == 60) {
    minutes++;                // increment minutes when seconds reach 60
    if (minutes == 60) {
      hours++;                // increment hours when minutes reach 60
      if (hours == 24) {
        hours = 0;            // reset hours when hours reaches 24
      }
      minutes = 0;            // reset minutes when minutes reaches 60
    }
    seconds = 0;              // reset seconds when seconds reaches 60
  }
  
  showtime(seconds, 6, 0);   // Display seconds (LEDs 0-5)
  showtime(minutes, 6, 6);   // Display minutes (LEDs 6-11)
  showtime(hours, 5, 12);    // Display hours (LEDs 12-16)
}

Leave a Reply

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