Aleph Clock

Designing and building a clock from scratch

Gears
It took me a while to get my head around the concepts behind making a gear train. During a bout of sleeplessness, I tried to get back to sleep by focusing on gear ratios, and how I could make a gear train. I finally got past my mental block (and got back to sleep), and the next day I diagrammed out a gear train.

In CAD I started to make gears, and tried to mesh them together.

I got the necessary values that I needed for the gears, but after a while, I realized I needed a different way to visualize the overlapping gears because they started running into each other. I made this map in Inkscape:

After a few more iterations, I realized that I needed a spreadsheet to keep track of the gears and their relationships.

I found that I could import a CSV file into Fusion 360, so that made it a lot easier to work on the gear train. After more iterations I came up with a couple of possible plans.

Right now, I’m working on trying to compact the gear train down rather than make it one long line of gears.

Motor
At first I thought I’d use a stepper motor. I got an Arduino and a motor shield and a small stepper motor just to see what it would take. It seemed overly complex, so I started casting around for a simpler solution. I thought I could use a synchronous AC motor that I could just plug into the wall, but I bought one that was supposed to be 1 RPM and it wasn’t even close to 1 RPM when I measured it. So, I went back to the idea of using a stepper motor.

I have a collection of electronic junk, and I found a power supply that has both 12 VDC and 5 VDC output, and enough amperage to power the motor and Arduino. I ordered a DS3231 RTC (real time clock) because I read that the Arduino’s internal time keeping is not really accurate enough for a clock.

Right now I’m working on programming the Arduino to advance the stepper and check the RTC to correct any inaccuracy.

//set Board to Arduino Uno
//set Port to SLAB_USB to UART

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <arduino-timer.h>
#include "RTClib.h"

RTC_DS3231 rtc;
auto timer = timer_create_default();


// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 

// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);

long target_minute;
long target_minute_steps;
long target_hour;
long target_hour_steps;
long target_day;
long target_day_steps;
long total_steps = 0L;
long start_steps;
int interval = 150;

bool one_step(void *) {
  DateTime now = rtc.now();

  myMotor->onestep(FORWARD, INTERLEAVE);   
  total_steps++;

  if (now.unixtime() == target_day) {
    target_day = now.unixtime() + 86400L;
    target_hour = now.unixtime() + 3600L;
    target_minute = now.unixtime() + 60L;
    time_check(target_day_steps);
    target_day_steps = total_steps + (86400000/interval);
  }  
  if (now.unixtime() == target_hour) {
    target_hour = now.unixtime() + 3600L;
    target_minute = now.unixtime() + 60L;
    time_check(target_hour_steps);
    target_hour_steps = total_steps + (3600000/interval);
  }
  if (now.unixtime() == target_minute) {
    target_minute = now.unixtime() + 60L;
    time_check(target_minute_steps);
    target_minute_steps = total_steps + (60000/interval);
  }

  return true; // to repeat the action - false to stop
}

void time_check(int expected_steps) {
  int x;
  int steps;
  
  Serial.println("time check!");
  Serial.print("expected ");
  Serial.println(expected_steps);
  Serial.print("steps    ");
  Serial.println(total_steps - start_steps);

  steps = total_steps - start_steps;
  start_steps = total_steps;
  
  if (steps < (expected_steps)) {
    for (x = steps; x < (expected_steps); x++) {
      myMotor->onestep(FORWARD, INTERLEAVE);
    }
  }
  if (steps > (expected_steps)) {
    for (x = steps; x > (expected_steps); x--) {
      myMotor->onestep(BACKWARD, INTERLEAVE);
    }
  }
}

void setup() {
  Serial.begin(9600);  // set up Serial library at 9600 bps
  Wire.begin();
  rtc.begin();
  AFMS.begin();  // create with the default frequency 1.6KHz
 
  DateTime now = rtc.now();

  // following line sets the RTC to the date & time this sketch was compiled
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // call the one_step function every n millis
  timer.every(interval, one_step);

  target_minute = now.unixtime() + 60L;
  target_minute_steps = total_steps + (60000/interval);
  target_hour = now.unixtime() + 3600L;
  target_hour_steps = total_steps + (3600000/interval);
  target_day = now.unixtime() + 86400L;
  target_day_steps = total_steps + (86400000/interval);

  delay(3500);
}

void loop() {
  timer.tick();
}

This is all still a work in progress. 🙂