Sverd Industries
Published © GPL3+

Binary Wrist Watch

Stylish wrist watch that shows time in binary code.

ExpertFull instructions provided10 hours1,993
Binary Wrist Watch

Things used in this project

Hardware components

LED 0603
×13
8 MHz ceramic resonator
×1
ATmega328P-AU
×1
0.1uF 0806 capacitor
×2
4.7uF tantalum capacitor
×1
10k ohm 0806 resistor
×1
DS3231 RTC
×1
51k ohm 0806 resistor
×3
CR2032 SMD battery clip
×1
Coin Cell Battery CR2032
Coin Cell Battery CR2032
×1
4.5 mm push button
×1
200 ohm 0806 resistor
Choose values according to LED color. I had success with the red LEDs with values between 39 ohm and 2k ohm
×4
PCB
0.8mm thich, produced with a black solder mask or the color of your choice. GERBER files to make your own PCB are provided in step 6
×1
20 mm watch band
×1
Watch band spring bar
×2
38 mm crystal watch glass
×1
Thin wrapping wire
5 cm or 2 in
×1
M2 6 mm flat head screws
×2
M2 hex nut
×2

Hand tools and fabrication machines

USB TTL adapter
Soldering iron (generic)
Soldering iron (generic)
Liquid solder flux
Rubbing alcohol
Flush cutters
Tweezers
Small torx screw driver
High quality 3D printer
I prototyped on a home desktop printer and had the end result professionally made. 3D files provided in step 11

Story

Read more

Custom parts and enclosures

3D Online Viewer

https://myhub.autodesk360.com/ue29e385f/shares/public/SHabee1QT1a327cf2b7acc0a5ffa5d99b4da?mode=embed

3D Files STL - Thingiverse

https://www.thingiverse.com/thing:3006456

Schematics

Schematic

GERBER files

Code

Arduino Code - Binary_Wrist_Watch.ino

Arduino
//-----------LED Settings-----------
const int row[4] = {3, 4, 5, 6};    //pins for A, B, C, D rows in the LED matrix. see drawing in instructions
const int col[4] = {7, 8, 9, 10};   //pins for 1, 2, 3, 4 columns in the LED matrix
byte rowByte[4] = {0, 0, 0, 0};     //table that stores and indexes the bytes used to display
int rowCount = 0;       //index used while looping through bytes to display on matrix
int delayTime = 300;    //microseconds. delay time between each row beeing displayed in LED matrix. scanning display

//-----------Sleep Settings-----------
#include "LowPower.h"               //library for deep sleep
unsigned long onTime = 20*1000;     //time display stays on before going to deep sleep
unsigned long sleepTimer = 0;   //used to time how long the watch has been awake
volatile bool woke = false;   //AF
int pushBtn = 2;    //pin for push button used to interrupt sleep
bool awakened = false;

//-----------Time Settings-----------
#include <Wire.h>       //i2c library
#include "RTClib.h" 
#include <EEPROM.h>     //library for reading/writing to eeprom
RTC_DS3231 rtc;         //name of attached RTC
bool DST = 1;    //used to signal if daylight savings time is active
int timeOrDate = false;      //indicates which display option to show. time or date
int counterDST = 0;    //counts number of button presses since awakening. used to toggle DST mode
DateTime now;

//-----------Other Variables-----------
volatile unsigned long prevInterrupt = 0;   //used for debouncing push button

void wakeFunction();
void displayRow(int, byte);

void setup() 
{
  //do you want to set the time? uncomment this line after first upload and time has been set
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  //rtc.adjust(DateTime(2018, 7, 5, 15, 51, 0));   //year, month, day, hour, minute, second

  pinMode(pushBtn, INPUT_PULLUP);
  for(int i = 0; i < 4; i++)    //turns all LEDs completely off
  {
    pinMode(row[i], OUTPUT);
    pinMode(col[i], OUTPUT);
  }
  allOff();

  delay(40);
  attachInterrupt(0, wakeFunction, FALLING);
  DST = EEPROM.read(0);   //gets the current DST settings
}

void loop() 
{
  if(woke)
  {
    if(millis() - prevInterrupt > 100)    //if button has been pressed for 100ms
    {
      if(!digitalRead(pushBtn))
      {
        awakened = true;    //flag to start led matrix
        timeOrDate = !timeOrDate;     //toggle between time and day being shown
        counterDST++;             //increment button counter each time button is pressed after waking
        sleepTimer = millis();    //start the sleep countdown 
        woke = false;
        now = rtc.now();     //gets the current time from DST 
        now = now + TimeSpan(0, DST, 0, 0);   //adds DST variable to time
      }
      else
        woke = false; 
    }
  }

  if(awakened)
  {
    if(millis() - sleepTimer < onTime)     //if display has been on for less than 30 sec
    {
      if(timeOrDate)      //loads the current time into bytes to be displayed
      {
        rowByte[0] = now.hour() / 10;     //hour second digit
        rowByte[1] = now.hour() % 10;     //hour first digit
        rowByte[2] = now.minute() / 10;   //minute second digit
        rowByte[3] = now.minute() % 10;   //minute first digit
      }
      else              //loads the day and month into bytes to be displayed
      {
        rowByte[0] = now.day() / 10;      //day first digit
        rowByte[1] = now.day() % 10;      //day second digit
        rowByte[2] = now.month() / 10;    //month first digit
        rowByte[3] = now.month() % 10;    //month second digit
      }
    
      displayRow(rowCount, rowByte[rowCount]);    //shows one byte at the time on the matrix
      delayMicroseconds(delayTime);  
      rowCount++;   //increments byte to be shown on matrix
      if(rowCount > 3)
        rowCount = 0;
  
      if(counterDST > 15)       //if the push button has been pressed 15 times since wakeup
      {
        DST = !DST;             //toggles DST hour added to time shown
        EEPROM.write(0, DST);   //save DST state in eeprom
        counterDST = 0;         //reset button counter
      }
    }
    else    //when display has been on for 30 sec
    {
      timeOrDate = false;   //set to false so time is first thing being shown on wakeup
      counterDST = 0;       //reset button counter
      woke = false;
      awakened = false;
    }
  }

  if(!woke && !awakened)
  {
    allOff();
    delay(30);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  //zzzz
  }
}

void wakeFunction()   //interrupt function when button is pressed
{
  woke = true;    //flags the microcontroller as just woken up
  prevInterrupt = millis();     //saves millis for debouncing
  //goes to main loop
}

void displayRow(int inRow, byte inByte)   //handles one row to display on the matrix at the time
{
  //turns off all rows and columns
    for(int i = 0; i < 4; i++)
    {
      digitalWrite(row[i], LOW);
      digitalWrite(col[i], HIGH);
    }
  
  digitalWrite(row[inRow], HIGH);   //turns on the selected row
  for(int i = 0; i < 4; i++)
    digitalWrite(col[i], !bitRead(inByte, i));  //turns on the selected columns
}

void allOff()   //turn all IO off before going to sleep to save power
{
  for(int i = 0; i < 4; i++)    
  {
    digitalWrite(row[i], LOW);    //rows must be set low to turn off
    digitalWrite(col[i], LOW);   //columns must be set high to turn off
  }
}

MiniCore Bootloader - Github

https://github.com/MCUdude/MiniCore

Credits

Sverd Industries

Sverd Industries

3 projects • 4 followers

Comments