loading

No matter what Deepak Chopra tells you, time is linear. Hopefully this clock is a little closer to reality than the circular ones we're all used to. The five minute intervals feel less neurotic than being precise down to the minute, and each number is magnified, reminding you to focus on the present.

I made this using just about every machine at Pier 9 (waterjet, sand blaster, laser cutter, 3D printer, electronics lab, etc.). It's made of 6061 aluminum, steel hardware (screws, nuts, bearings), 3D printed gears, an Arduino Uno, and the hour and minute panels are laser cut / etched plywood.

Of course I know this project isn't accessible to almost everyone who doesn't have the insanely good fortune of having access to a shop like this, but hopefully you'll find it inspiring.

Fusion 360 is free for students and hobbyists, and there's a ton of educational support on it. If you want to learn to 3D model the kind of work I do, I think this is the best choice on the market. Click the links below to sign up:

Student/Educator

Hobbyist/Startup

I also led a series of webinar classes related to 3D modeling projects with moving parts. In these webinars, you will learn Fusion 360 features like advanced mechanical assemblies (meaning two or more joints interacting) and rendering. The last webinar focused on modeling this clock design in Fusion 360. You can watch the entire video here:

If you're interested, check out the other two webinars in this series where you will learn to design a Giant Knob Lamp and a Perpetual Clock with Arduino.

Step 1: Design & 3D Model

The video above is a recording of a webinar I did for the rack and pinion design part of the project.

The hardest part of the design to figure out was the rack and pinion gear assembly. The math for gear design can get pretty complicated (in fact, there are engineers who basically only design gear assemblies for this very reason), but based on a great Youtube tutorial by Rob Duarte, I made my own template that works with the latest version of the Spur Gear add-in for Fusion.

The video above walks you through the process of making the rack and pinion assembly, but if you want a more thorough tutorial, please join me for the Design Now Hour Of Making in Motion webinar on April 5. If you miss the webinar, it'll be recorded and I'll post the video here.

The template (link below) has all of the parameters shown above already entered. I won't get into the math here, but if you follow the instructions, it should work for you.

Use the Spur Gear add-in by going to ADD-INS > Scripts and Add-Ins... > Spur Gear > Run. When you get the window shown above, enter the parameters. Number of Teeth won't let you use a parameter for the value, so just make sure it matches the teethNum value if you change it. You also have to multiply the named parameters by 1 as shown above.

Keep in mind that once the gear is made, you can edit it just like any other object in Fusion.

As shown in the video demo, this is an example of how you'd construct a tooth profile using the parameters.

Here are the links to the template you can use to make your own rack and pinion in Fusion:

Template with parameters:http://a360.co/2oeT5El

After the rack and pinion gear was figured out, I spent a lot of time modeling motors, switches, and other electronic parts, then figuring out all the details. With the motion link described above, I was able to get a good picture of how it would look in motion.

You can access the file through the link below, and play around with it or even try to make your own version out of the file. There was quite a bit of tinkering and alteration after the parts were made, so don't expect to be able to just laser cut all the parts and have a finished product. This project was expensive and took a lot of time! If you're really serious about making it and need some help, just comment below and I'll do my best to get you going.

Finished Clock Design: http://a360.co/2nk51nw

If you aren't already a Fusion 360 user, sign up for my free 3D Printing Class. It's a crash course in Fusion for making, and Lesson 2 has all the info you need to get Fusion for free.

Step 2: Hardware

Step 3: Electronics & Programming

The electronics are all done with an Arduino Uno and an Adafruit Motor Shield.

Here's the basic idea of how I want it to work:

  1. When the unit is turned on, the steppers run the racks back until the limit switches on the left side are triggered. This sets the position to zero. The steppers then run the racks forward until 1 is centered on the hour panel and 00 is centered on the minute panel.
  2. Once the hour and minute is centered, the racks move forward in time. A full position move on the bottom at full speed every 5 minutes, and a full position move on the top every hour.
  3. The momentary switches (pins 6-7) to move the racks forward by one position (about 147 steps), then continue with the clock counting.
  4. The hour and minute movements have counters that send the bars back to the left limit switches and reset them to zero once hour has gone past 12, and the minutes have gone past 55.

I'm still not clear on what exactly I need to do with the code. I've got it working in theory with the code below that got from Randofo. This code moves the minute bar forward one step every 200 ms (I think) once one of the limit switches is triggered. It works, but I'm pretty quickly out of my depth past the basic work I've done here. This seems like a pretty easy problem for a savvy Arduino user, but I only do a project with one maybe once a year, and every time I do, I've basically forgotten everything I learned in the last project.

<p>/*************************************************************</p>
Motor Shield Stepper Demo
by Randy Sarafan
For more information see:
<a href="https://www.instructables.com/id/Arduino-Motor-Shield-Tutorial/">
https://www.instructables.com/id/Arduino-Motor-Shi...</a>
*************************************************************/
#include <wire.h>
#include <adafruit_motorshield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"</adafruit_motorshield.h></wire.h>
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 
// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor1 = AFMS.getStepper(300, 1);
Adafruit_StepperMotor *myMotor2 = AFMS.getStepper(300, 2);
int delaylegnth = 7;
void setup() {
    //start serial connection
  Serial.begin(9600);
  //configure pin2 as an input and enable the internal pull-up resistor
  pinMode(2, INPUT_PULLUP);
  //  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Stepper test!");
  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  myMotor1->setSpeed(100);  // 10 rpm   
  
}
void loop(){
  
 //read the pushbutton value into a variable
  int sensorVal = digitalRead(2);
  sensorVal == LOW;
  int delayL = 200;
  
  if (sensorVal == LOW) {
  
  Serial.println("Minutes ++");
  //myMotor1->step(1640, BACKWARD, DOUBLE);
  for (int i=0; i <= 10; i++){
      myMotor1->step(147, BACKWARD, DOUBLE);
      //analogWrite(PWMpin, i);
      delay(delayL);
   } 
   
  Serial.println("Hours ++");
  myMotor1->step(1615, FORWARD, DOUBLE); 
  //myMotor2->step(1600, BACKWARD, DOUBLE);
  myMotor2->step(220, FORWARD, DOUBLE); 
  //delay(delayL);
  
  }
  else {
  //Serial.println("Double coil steps");
  myMotor1->step(0, FORWARD, DOUBLE); 
  myMotor1->step(0, BACKWARD, DOUBLE);
    
  }
}

Step 4: Assemble the Base

The base is made of two plates with spacers holding them together. The screws fasten to the plate through tapped holes. Part number 6 on this drawing is another 3D printed part- a spacer that's also a cradle for the power terminal for the stepper motors.

Step 5: Add Momentary Switches

The momentary switches, Arduino, and limit switches all fasten to the front plate, so accessing the electronics to make changes is easy- just take the back plate off and you can reach everything.

Step 6: Add Mounting Plate and Limit Switches

The mounting plate holds the limit switches and the bearing assembly for the racks. This part can also stay together when editing the electronics.

Step 7: Add Stepper Motors & Gears

The stepper motors fasten to the panel with M4 screws through threaded holes, and the 3D printed gears are press-fit onto the motor posts. I used a trigger clamp to get them snug and flush.

Step 8: Add Racks

The racks have slots cut into them that bear on the two ball bearings. There's a small gap (.1mm) between the bearings and the slots, which allows the rack to move freely.

The bearings are sandwiched between custom 3D printed spacers to get the exact fit I needed. There's a rack plate on the front that acts as a washer holding the racks in place.

Step 9: Add Hour and Minute Bars

The hour and minute bars fasten to the racks with 12mm spacers creating a gap that allows clearance between the bars and the racks.

Step 10: Add Magnifiers

The magnifiers are cheap pocket magnifying glasses I found on amazon. They're offset from the front of the bars with 25mm spacers.

Step 11: Lessons Learned

I learned a lot about linear motion with this project. The tolerance I used between the bearings and slots on the racks was a bit too much, so if I were to make it again I think I would probably cut it in half. The gap on the sides of the gaps was also a bit too big.

The motors work, but the longer the cantilever gets, the more they have to work. I'd probably go with 12V steppers instead of 5V ones.

The backlash also should have been greater, maybe 0.25mm. The gears were bearing down on the racks too tightly with the first gears I tried.

<p>ooooo... very nice! - as an aside, in the a360 link, did you create the first story board step by step by moving each component seperately? or did you find a quicker way? I'm driving myself crazy trying to animate a similar mechanism to a360! </p>
<p>Yeah, the animation environment needs a lot of work. The developers know that though, and they're working on it. </p><p>I basically moved groups of parts individually in the timeline to make that animation.</p>
What about this is perpetual? Am i missing something?
<p>I admit, it's the wrong title. I was referring to the perpetual calendar, which it borrows its shape from. I should have called it "linear clock", since all clocks are essentially perpetual.</p>
ooOOOoo very neat!<br><br>If its not against your design ascetics, <br>Could revision II of this clock have numbers bubbles in a circular shape instead of linear? Then you have a perpetual clock! <br><br>Better still, you could add seconds(if someone wanted neuroticism) and put the three loops in a triangle shape(just offset by 120&deg; ) or those three number circles nested inside one another, that would be also neat I think!
<p>Good idea! Should be easy enough to pull off, though a round rack turning would need a different kind of liner motion- maybe they could be on lazy susans...</p>
<p>Very nice design, though I like my clocks to be easily read to the minute. Love the effect of the magnifier. This fairly begs for a steampunk aesthetic.....</p>
<p>It might work with minute-by-minute numbers, I haven't tested it.</p>
<p>Wow, impressive and really beautiful.</p><p>Would love to make one with brass and copper to have a nice steampunk look!</p>
<p>Great idea, though I think black oxide body with copper fixings and cogs would look just as good.</p>
Such an amazingly well presented instructable! As an engineer, I've got a lot of time for those exploded views!!
Man after my own heart!
<p>i love clocks this is brilliant concept just keep inspering and please make them to sell would defo buy</p>
<p>Already working on it!</p>
<p>Just a suggestion. </p><p>I recently made a nixie tube clock, and I added a ESP8266 and my clock gets the time directly from the web. <br>when it starts and every 5 hours, just in case it misses some minutes. </p><p>Quite simple code, I can provide it in case you need. </p><p>great work </p><p>Jose Machado</p>
<p>Oi Jose,</p><p>I'm interested in your ESP-code! Is it written in Arduino?</p><p>Steve Vellinga</p>
I never got it to work with the NTP, so I found this way of doing it.<br> I try to access some fake page on google, that will return 404 not found,<br> and I extract the date and time from the reply HTML header.<br> This will be UTC time, you can adjust them to your own time zone<br> I believe the code is clear, but I am available to assist:<br> <br> #define SSID &quot;Mama Dina&quot;<br> #define PASS &quot;********&quot; // My luggage has the same combination!<br> #define DEST_HOST &quot;google.com&quot;<br> #define DEST_IP &quot;216.58.210.228&quot;<br> #define TIMEOUT 10000 // mS<br> #define CONTINUE false<br> #define HALT true<br> #include SoftwareSerial<br> <br> Serial1 = SoftwareSerial(3, 2);<br> char lf=10; //line feed character<br> String readString, readString1;<br> int x=0; //for counting line feeds<br> <br> // ******** SETUP ********<br> <br> void setup() {<br> <br> Serial.begin(9600); // Communication with PC monitor via USB Serial1.<br> begin(9600); // Communication with ESP8266 via 5V/3.3V level shifter //<br> <br> Serial1.setTimeout(TIMEOUT);<br> Serial.println(&quot;ESP8266 Demo&quot;);<br> delay(2000);<br> Serial.println(&quot;AT+RST&quot;);<br> Serial1.println(&quot;AT+RST&quot;);<br> show();<br> Serial1.println(&quot;AT+GMR&quot;);<br> show();<br> Serial1.println(&quot;AT+CWMODE=1&quot;);<br> show();<br> Serial1.println(&quot;AT+CIPMUX=0&quot;);<br> show();<br> String cmd=&quot;AT+CWJAP=\&quot;&quot;;<br> cmd+=SSID;<br> cmd+=&quot;\&quot;,\&quot;&quot;;<br> cmd+=PASS;<br> cmd+=&quot;\&quot;&quot;;<br> Serial1.println(cmd);<br> show();<br> Serial.println(&quot;Finished!!!&quot;);<br> Serial1.println(&quot;AT+CIFSR&quot;);<br> show();<br> cmd = &quot;AT+CIPSTART=\&quot;TCP\&quot;,\&quot;&quot;;<br> cmd += DEST_IP;<br> cmd += &quot;\&quot;,80&quot;;<br> Serial1.println(cmd);<br> show();<br> cmd = &quot;GET /1.txt&quot;; // this is the fake page that does not exist in Google<br> cmd += DEST_HOST;<br> cmd += &quot;\r\n\r\n&quot;;<br> Serial1.print(&quot;AT+CIPSEND=&quot;);<br> Serial1.println(cmd.length());<br> show();<br> Serial1.println(cmd);<br> show();<br> }<br> <br> void loop(){ }<br> <br> //Shows the output from the ESP directly to the serial monitor. This is helpful for debugging<br> <br> void show(){<br> &nbsp; &nbsp; &nbsp;String keyword=&quot;Date:&quot;; //this is the keyword we are searching on the response HTML header<br> &nbsp; &nbsp; &nbsp;byte current_char = 0;<br> &nbsp; &nbsp; &nbsp;byte keyword_length = keyword.length();<br> &nbsp; &nbsp; &nbsp;long deadline = millis() + TIMEOUT;<br> &nbsp; &nbsp; &nbsp;int temp=0; &nbsp;<br> &nbsp; &nbsp; &nbsp;readString=&quot;&quot;; &nbsp;<br> &nbsp; &nbsp; &nbsp;while(millis() &lt; deadline){<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Serial1.available()) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char ch = Serial1.read();<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.write(ch);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (temp&lt;200){<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;temp++; readString += ch; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ch == keyword[current_char])<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (++current_char == keyword_length) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.println(&quot;Found it&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.println(current_char);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp;int aux = readString.indexOf(&quot;Date: &quot;);//Find the position of the word &quot;Date:&quot;<br> &nbsp; &nbsp; &nbsp;/*translations:<br> &nbsp; &nbsp; &nbsp;dia=day<br> &nbsp; &nbsp; &nbsp;Mes=month &nbsp;<br> &nbsp; &nbsp; &nbsp;Ano=year<br> &nbsp; &nbsp; &nbsp; Hora=hour<br> &nbsp; &nbsp; &nbsp;minuto=minutes<br> &nbsp; &nbsp; &nbsp;segundo=second<br> &nbsp; &nbsp; &nbsp;*/<br> &nbsp; &nbsp; &nbsp;if (aux&gt;0){<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String dia=readString.substring(aux+11,(aux+13));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String mes=readString.substring(aux+14,(aux+17));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String ano=readString.substring(aux+18,(aux+22));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String hora=readString.substring(aux+23,(aux+25));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String minuto=readString.substring(aux+26,(aux+28));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String segundo=readString.substring(aux+28,(aux+31));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.print(&quot;Dia:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.println(dia);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.print(&quot;Mes:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.println(mes);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.print(&quot;Ano:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.println(ano);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.print(&quot;Hora:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.println(hora);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.print(&quot;Minuto:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.println(minuto);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.print(&quot;segundo:&quot;);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.println(segundo);<br> &nbsp; &nbsp; &nbsp; }<br> } //___________________________________________________________________________________________________<br> // Read characters from WiFi module and echo to serial until keyword occurs or timeout.<br> boolean echoFind(String keyword) {<br> <br> &nbsp; &nbsp; &nbsp;byte current_char = 0;<br> &nbsp; &nbsp; &nbsp;byte keyword_length = keyword.length(); // Fail if the target string has not been sent by deadline.<br> &nbsp; &nbsp; &nbsp;long deadline = millis() + TIMEOUT;<br> &nbsp; &nbsp; &nbsp;while(millis() &lt; deadline) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (Serial1.available()) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char ch = Serial1.read();<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.write(ch);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ch == keyword[current_char])<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (++current_char == keyword_length) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.println(); return true;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; return false; // Timed out<br> }
<p>thats a nifty solution.<br>I didnt have that much trouble getting it from an ntp server but more as a gimmick, never put it to work yet.<br>time can be gotten from many places, also from several weatherstation api's such as weatherunderground</p>
<p>Hello, </p><p>Can you explain what you mean by nifty solution ? </p><p>JMaxado</p>
<p>Oi Jose,</p><p>Muito obrigado!!!</p><p>Steve</p>
<p>You deserve a medal, just for sheer awesomenes</p>
<p>Thanks man! Any advice on the programming?</p>
<p>It seems you are already quite far with using Randolfo's code.<br>For a clock I would not rely on an NTP server, but take an RTC.<br>I have not completely figured out the mechanics of your clock but if the bars/sliders work independently all you need to do is for the seconds do 1 sec steps and then either after 60 set a change flag for the minutes, or keep checking for the minute (and ofcourse the hour) to change.<br>A slightly more mechanical solution ofcourse would be the momentary switch being pressed by the seconds rail, triggering a minute advance and the same for a momentary switch triggered by the minute slider etc</p><p>Now how great would it be if the seconds rail would just mechanically advance the minute rail :-)</p>
<p>how to get these harwares pease jon</p>
<p>This is really great, awesome build! Would love to give this a go sometime</p>
<p>This is fantastic! This is creativity at its best!</p>
<p>Thanks for saying so! You guys have some really cool projects too. I like the weather station especially.</p>
<p>wwwwaaaaaa????</p><p>THAT is impressive! Love it.</p>
<p>Thanks!</p>
<p>Hi!<br><br>This is an amazing project!<br><br>Could you tell me what motor driver did you use? And what stepper motors exactly?<br><br>Also, I'm not gonna use a lazer cut machine, so could you tell me measurements of the racks and hours/minutes bar? And if it is possible, the measurements of the base and the plate as if it was a square.</p><p>Thank you! :)</p>
<p>I've just added a Hardware step with this info. The base is about 8"x8" and the racks are about 22" wide. Good luck!</p>
<p>Alright thank you!</p>
this is out of the world ideal .. beautiful .. haven't seen anything like this ...
<p>Thanks for saying so!</p>
<p>That's great. Have you published it somewhere?<br>Or can you post it here?</p>
<p>Nice work JON! I love clocks! :)</p>
Thanks Durk!
<p>Awesome! I was just looking how to make gears in Fusion360. Thanks a lot! The design is great. I am not a big fan of the burn marks from the laser cutter, but otherwise I think it is perfect.</p>
Yep, color me lazy! I should have sanded those down before taking the pictures.
<p>Hey Jon, this is such a beautiful thing...I've just checked out Pier9 and blimey you have access to some super cool kit, though I think by using other materials and tools I think this project is really achievable. Cool.</p>
<p>I was thinking the same thing. If you made the aluminum parts with plywood on a laser cutter (or even a scroll saw), you could probably make it work just as well with maybe $1000 worth of tools.</p>
<p>Okay, now you need to make them and sell one to me !!</p>
<p>We shall see!</p>
<p>Awesome job!</p>
<p>thanks Christa!</p>

About This Instructable

36,647views

366favorites

License:

Bio: I'm a full-time Designer at the Instructables Design Studio (best job ever). My background is in residential architecture, film set design, film animatronics, media ... More »
More by JON-A-TRON:Zoetrope Fidget Spinner Learn to Draw Perpetual Clock With Arduino 
Add instructable to: