Mesmerizing Magnetic Wall Clock

98,829

946

132

Introduction: Mesmerizing Magnetic Wall Clock

About: My name is Troy. I'm a Mechatronics and Aerospace Engineer. I make things out of wood and electronics and spend time outdoors (especially SCUBA diving).

Mechanical clocks have always fascinated me. The way all of the internal gears, springs, and escapements work together to result in a constant reliable timepiece has always seemed out of reach for my limited skill set. Thankfully modern electronics and 3D printed parts can bridge the gap to create something simple that doesn't rely on small precise metallic parts.

This minimalist wall clock hides a pair of 3D printed ring gears driven by inexpensive stepper motors that rotate magnets behind a classic walnut veneer.

Initially inspired by STORY Clock, I wanted a time piece that indicated the time of day using ball bearings only vs the digital readout and slow moving ball bearing their product uses.

Step 1: Tools and Materials

Materials:

Tools:

  • 3D Printer
  • Compass
  • X-acto Knife
  • Glue
  • Clamps
  • Circle Cutting Jig
  • Hack Saw
  • Disc Sander
  • Ratchet Clamp
  • Chisel
  • Ruler
  • Sander
  • Drills
  • Screwdrivers
  • Soldering Iron
  • Hot Glue Gun

Step 2: Glue Together Wood Frame

Glue together three pieces of wood that will form the frame of the clock. I used reclaimed particle board from an old bed frame.

Step 3: Cut Frame Using Circle Cutting Jig

Mark the center of the board and mount to a circle cutting jig. Cut five circles with the following diameters:

  • 12 in.
  • 11 1/4 in.
  • 9 1/4 in.
  • 7 1/4 in.
  • 5 3/8 in.

Step 4: Print and Assemble Gears

The ring gears are broken into segments so they can be printed on a small printer and snapped together. All parts were printed in ABS to aid in the fusing process shown in the next step. Sand all edges and surfaces of the parts.

Print the following quantities of parts found in step 22:

  • 1 - Hour Ring Gear Segment Magnet
  • 6 - Hour Ring Gear Segment Basic
  • 1 - Hour Retaining Ring Segment Stepper Mount
  • 6 - Hour Retaining Ring Segment Basic
  • 1 - Hour Hall Effect Sensor Holder
  • 1 - Minute Ring Gear Segment Magnet
  • 7 - Minute Ring Gear Segment Basic
  • 1 - Minute Retaining Ring Segment Stepper Mount
  • 6 - Minute Retaining Ring Segment Basic
  • 1 - Minute Hall Effect Sensor Holder
  • 2 - Spur Gear
  • 1 - Electronics Mount

Step 5: "Glue" Sections Together

In a glass bottle with some acetone, dissolve failed prints old support material, etc. Paint the acetone mixture on each seam to fuse the pieces together. Once cured, sand each seam flat.

Step 6: Cut Reliefs in Frame

Place the ring gears and retaining rings in the frame and cut out reliefs for the stepper motors. I measured and cut the inner ring too large so I shimmed it to size using some maple edge banding I had around the shop.

Step 7: Cut Clearance for Hall Effect Sensors

Cut a clearance hole through the inner ring for the minute hall effect sensor and slot for the hour hall effect sensor. I used a chisel, file, and small hand saw to cut these clearances.

Step 8: Glue Outer Ring

Glue and tape the outer ring the size of the minute retaining ring.

Step 9: Cut Hall Effect Sensor Adjustment Screws

Cut machine screws with a hack saw so they are just longer than the thickness of the retaining ring and hall effect sensor holder. Cut a slot in the threads so it can be adjusted from the threaded end with a flat screwdriver.

Step 10: Glue Rings to Hardboard

Cut a circle of hardboard just larger than the outer ring. Glue outer and inner ring to hardboard face. Use the minute retaining ring and ring gear to place the inner ring. Pay better attention than I did to not glue the inner ring on backwards. Image two shows a new slot cut for minute hall effect sensor.

Use a disc sander to trim the hardboard down to the size of the outer ring.

Step 11: Glue Inner Disc

Glue inner disc in place using the hour retaining ring and ring gear to place the inner disc.

Step 12: Attach Veneer

Cut a strip of veneer wider than the clock is deep and long enough to wrap around the clock (3.14 * diameter of the clock, will return the length needed. Add an inch to be sure that you have enough.) Dry fit the veneer to cut to length. Applying ample glue to the veneer and clamp in place with a strap clamp. Let dry a couple hours to ensure adhesion.

Step 13: Trim Veneer

Using a sharp chisel, trim the excess veneer from the front and back of the clock.

Step 14: Cut Veneer

My veneer had some cracks in it. To make it easier to work with, I applied painters tape to hold it together. Using an x-acto knife in a compass, cut the veneer just larger than the face of the clock.

Step 15: Glue Veneer

Use the off cut rings to spread out the pressure across the face of the clock. Apply ample glue to the non tape side of the veneer. Orient the grain vertically on the clock face and apply many clamps tightening each one a little at a time. This will ensure the veneer doesn't shift and has even pressure across the face.

I used a couple flat boards on the face side of the clock and some cauls on the back.

Step 16: Sand and Finish

Using sandpaper, carefully remove the excess veneer from the face of the clock and sand starting at 220 grit up to 600 grit.

Apply between 10 and 20 coats of lacquer. This will build up the surface that the ball bearing will ride along. Inevitably due to dust and other particles in the air, I think that lines will appear along the path of each ball bearing. Applying more coats of finish should delay this as long as possible. It will also make future refinishing easier. I will update this step if lines ever appear on my clock.

Step 17: Install Power

Using a 27/64 in. drill bit, drill a hole in the bottom of the clock and screw the power plug in place.

Step 18: Assemble Electronics

Attach stepper drivers and real time clock to the electronic board. I needed to find a way to secure the Arduino so holes were drilled and a slot was cut for a zip tie. These features have been added to the file found in step 22.

Step 19: Solder and Connect Electronics

Following the block diagram, solder all components together. Hot glue the rings in place and secure any stray wires with hot glue as well.

Step 20: Back Plate

Create the back plate by cutting another circle 1/2 in. larger than the face of the clock and a ring with the inner diameter the same as the back of the clock. Glue the ring and circle together with some spring clamps.

Once dry, scribe a line 1/8 in. larger than the inner ring and trim to size using the band saw or disc sander.

Cut a slot 1 in. long 1/4 in. wide at the top of the back using a router or drill bits. Countersink four holes to secure the back into the frame of the clock.

Apply black spray paint and attach to the clock once dry.

Step 21: Arduino Code

The arduino code is commented as well as possible. Keep in mind that I'm not a programmer, I have minimal arduino experience (be kind). The code runs continually checking to see if the current time matches the "Reset Time". Because I couldn't think of a way to translate the current time into steps, it only corrects itself once daily (midnight by default). At midnight the gears rotate to the midnight position then wait until 00:01 moving to that time then continues from there. As it currently sits, the clock only loses about 5 seconds over a 24 hour period.

You will need the Stepper and RTClib libraries installed.

I know the code can be optimized by someone with more experience than myself. If you are up to the challenge, please recreate this project for yourself and share your knowledge.

#include <Stepper.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#define oneRotation 2038 // the number of steps in one revolution of 28BYJ-48 stepper motor
Stepper hourHand(oneRotation, 3, 5, 4, 6);
Stepper minuteHand(oneRotation, 7, 9, 8, 10);
#define hourStopSensor 12
#define minuteStopSensor 11
int endStep = 0;

// Time dealy for speed of the clock.
int setDelay1 = 168;
int setDelay2 = 166;
int setDelay3 = 5;

// Current time to do math with. 
float hr = 0;
float mn = 0;
float sc = 0;

// Set the time of day to reset clock (24 hour format).
int resetHour = 0;
int resetMinute = 0;

// Variables to set correct time at startup and reset.
float setTimeStepHour = 0;
float setTimeStepMinute = 0;
float handDelay = 0;
float hourTest = 0;
float minuteTest = 0;


void setup() {
  Serial.begin(115200);

  // Setup real time clock and reset hall effect sensors.
  pinMode(hourStopSensor, INPUT_PULLUP);
  pinMode(minuteStopSensor, INPUT_PULLUP);
  rtc.begin();

  // Uncomment line below to set time.
  //  rtc.adjust(DateTime(2020, 2, 19, 23, 40, 30));
  //  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // Set top speed of stepper motors.
  hourHand.setSpeed(15);
  minuteHand.setSpeed(15);


  // Loop until minute and hour hand are at noon
  while (digitalRead(hourStopSensor) == LOW ||  digitalRead(minuteStopSensor) == LOW)
  {

    if (digitalRead(hourStopSensor) == LOW )
    {
      hourHand.step(2);
    }
    
    else
    {
      delay(3);
    }
    

    if (digitalRead(minuteStopSensor) == LOW)
    {
      minuteHand.step(3);
    }
    
    else
    {
      delay(4);
    }
  }

  while (digitalRead(hourStopSensor) != LOW || digitalRead(minuteStopSensor) != LOW)
  {
    if (digitalRead(hourStopSensor) != LOW )
    {
      hourHand.step(2);
    }
    
    else
    {
      delay(3);
    }
    
    if (digitalRead(minuteStopSensor) != LOW)
    {
      minuteHand.step(3);
    }
    
    else
    {
      delay(4);
    }  
  }

  // Get current time
  DateTime now = rtc.now();
  hr =  now.hour();
  mn = now.minute();
  sc = now.second();

  // Change to 12 hour format 
  if (hr >= 12)
  {
    hr = hr - 12;
  }

  // See what hand must travel across the face further and use that distance 
  // to adjust set time accordingly. 
  hourTest = hr / 12;
  minuteTest = mn / 60;

  if (hourTest > minuteTest)
  {
    handDelay = hourTest;
  }
  else
  {
    handDelay = minuteTest;
  }

  // Set current hour
  setTimeStepHour = (hr * 498) + (mn * 8.3) + ((sc + (handDelay * 36)) * .1383);

  // Set current minute
  setTimeStepMinute = (mn * 114) + ((sc + (handDelay * 45)) * 1.9);

  // Test which hand will need more steps and set that to the longest step count for the for loop. 
  if (setTimeStepHour > setTimeStepMinute)
  {
    endStep = setTimeStepHour;
  }
  else
  {
    endStep = setTimeStepMinute;
  }

  for (int i = 0; i <= endStep; i++)
  {
    if (i < setTimeStepHour)
    {
      hourHand.step(2);
    }
    
    else
    {
      delay(3);
    }

    if (i < setTimeStepMinute)
    {
      minuteHand.step(3);
    }

    else
    {
      delay(4);
    }
  }

  // Set clock running RPM
  hourHand.setSpeed(1); 
  minuteHand.setSpeed(1); 

}

void loop() {
  // Start clock running loop.
  for (int i = 0; i < 22; i++)
  {
    minuteHand.step(1);
    delay(setDelay1);

    // Test for reset time, if ready to be reset, break.
    if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute)
    {
      break;
    }
  }

  delay(setDelay3);

  for (int i = 0; i < 38; i++)
  {
    hourHand.step(1);
    delay(setDelay1);

    // Test for reset time, if ready to be reset, break.
    if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute)
    {
      break;
    }

    for (int i = 0; i < 20; i++)
    {
      minuteHand.step(1);
      delay(setDelay2);

      // Test for reset time, if ready to be reset, break.
      if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute)
      {
        break;
      }
    }
  }

  // Reset clock at reset time
  if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute)
  {
    // Change speed of clock
    hourHand.setSpeed(10);
    minuteHand.setSpeed(10);

    // Loop till minute and hour hand reach noon.
     while (digitalRead(hourStopSensor) == LOW ||  digitalRead(minuteStopSensor) == LOW)
  {

    if (digitalRead(hourStopSensor) == LOW )
    {
      hourHand.step(2);
    }
    
    else
    {
      delay(3);
    }
    
    if (digitalRead(minuteStopSensor) == LOW)
    {
      minuteHand.step(3);
    }
    
    else
    {
      delay(4);
    }
    
  }

  while (digitalRead(hourStopSensor) != LOW || digitalRead(minuteStopSensor) != LOW)
  {

    if (digitalRead(hourStopSensor) != LOW )
    {
      hourHand.step(2);
    }
    
    else
    {
      delay(3);
    }
    
    if (digitalRead(minuteStopSensor) != LOW)
    {
      minuteHand.step(3);
    }
    
    else
    {
      delay(4);
    }  
  }

    // Wait here until the reset time has passed.
    while (rtc.now().minute() == resetMinute)
    {
      delay(1000);
    }

    // Get current time
    DateTime now = rtc.now();
    hr =  now.hour();
    mn = now.minute();
    sc = now.second();

    // Change to 12 hour format
    if (hr >= 12)
    {
      hr = hr - 12;
    }

    // See what hand must travel across the face further and use that distance 
    // to adjust set time accordingly. 
    hourTest = hr / 12;
    minuteTest = mn / 60;

    if (hourTest > minuteTest)
    {
      handDelay = hourTest;
    }
    else
    {
      handDelay = minuteTest;
    }

    // Set current hour
    setTimeStepHour = (hr * 498) + (mn * 8.3) + ((sc + (handDelay * 36)) * .1383);

    // Set current minute
    setTimeStepMinute = (mn * 114) + ((sc + (handDelay * 45)) * 1.9);

    // Test which hand will need more steps and set that to the longest step count for the for loop.
    if (setTimeStepHour > setTimeStepMinute)
    {
      endStep = setTimeStepHour;
    }
    else
    {
      endStep = setTimeStepMinute;
    }


    for (int i = 0; i <= endStep; i++)
    {
      if (i < setTimeStepHour)
      {
        hourHand.step(2);
      }
      
      else
      {
        delay(3);
      }
  
      if (i < setTimeStepMinute)
      {
        minuteHand.step(3);
      }
  
      else
      {
        delay(4);
      }
    }

    hourHand.setSpeed(1); 
    minuteHand.setSpeed(1); 
  }
}

Step 22: STL Files

You will need to print the following quantities of the files:

  • 1 - Hour Ring Gear Segment Magnet
  • 6 - Hour Ring Gear Segment Basic
  • 1 - Hour Retaining Ring Segment Stepper Mount
  • 6 - Hour Retaining Ring Segment Basic
  • 1 - Hour Hall Effect Sensor Holder
  • 1 - Minute Ring Gear Segment Magnet
  • 7 - Minute Ring Gear Segment Basic
  • 1 - Minute Retaining Ring Segment Stepper Mount
  • 6 - Minute Retaining Ring Segment Basic
  • 1 - Minute Hall Effect Sensor Holder
  • 2 - Spur Gear
  • 1 - Electronics Mount

Step 23: Solidworks Files

These are the original Solidworks files used to create the STLs found in the previous step. Feel free to edit and change my files as you see fit.

Step 24: Conclusion

This clock turned out better than I had anticipated. Having minimal Arduino experience, I'm glad with how it turned out and how accurate it is. It looks great and functions just as I'd hoped.

Clocks Contest

Participated in the
Clocks Contest

5 People Made This Project!

Recommendations

  • Pi Day Speed Challenge

    Pi Day Speed Challenge
  • Trash to Treasure Contest

    Trash to Treasure Contest
  • Microcontroller Contest

    Microcontroller Contest

132 Comments

0
creutzy67
creutzy67

Question 9 days ago

I have a question about veneer: what thickness do you recommend? Too thick affects the magnetism, too thin is too fragile. Do you have any advice?
Moreover, is it really the veneer on the front side that holds the whole structure together? Thank you in advance.

0
tomatoskins
tomatoskins

Reply 9 days ago

I used a 3 pack of 12. in x 12 in. walnut veneer from Woodcraft. I looked online and couldn't find any information on the thickness. The veneer doesn't hold everything together, the clock is held together by the hardboard that the veneer is attached to. I think it's about 1/8 in. thick.

0
creutzy67
creutzy67

Reply 7 days ago

Thanks. 👍🏻

0
Art_Lieberman
Art_Lieberman

Question 16 days ago

To set or correct the time... Do we have to edit and recompile the program whenever we need to set the time (twice a year)? Or is it grabbing the current time from the Internet? Or ...?

0
tomatoskins
tomatoskins

Reply 9 days ago

All you need to do is uncomment this line:
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
then upload the code, then recomment it and upload the code again.
That line will pull the time and date from your computer.

0
creutzy67
creutzy67

26 days ago

This project is my favorite for months. I recently bought a 3D printer mainly for this project.
I have just started the manufacturing in association with my brother: he takes care of the wood part and I take care of the 3D parts and electronics.
I have a question about veneer: what thickness do you recommend? Too thick affects the magnetism, too thin is too fragile. Do you have any advice?
Moreover, is it really the veneer on the front side that holds the whole structure together? Thank you in advance.

0
T o m
T o m

2 months ago

Can't find printing info such as resolution or infill % for printed parts. Can you provide?

0
tomatoskins
tomatoskins

Reply 2 months ago

I don't remember what resolution I used but nothing needs to be very strong. 20% infill should suffice.

0
T o m
T o m

Reply 8 weeks ago

Thank you!

0
Art_Lieberman
Art_Lieberman

2 months ago

Instead of building it from wood, how about 3D printing each of the pieces?
If anyone does this, please post. THANKS!

0
tomatoskins
tomatoskins

Reply 2 months ago

That can definitely be done.

2
idamtnboy
idamtnboy

2 months ago

What role do the hall effect sensors play?

0
tomatoskins
tomatoskins

Reply 2 months ago

They are used to index the 'home (noon) position because stepper motors don't know where they are. When the program starts it moves to this home position then calculates the position it needs to move to depending on what time it is.

I hope that helps!

0
rudyauction509
rudyauction509

Reply 2 months ago

They allow the Arduino to sense when each “hand” is at 12:00

0
rudyauction509
rudyauction509

2 months ago

This has to be the coolest clock project I’ve ever seen.

0
tomatoskins
tomatoskins

Reply 2 months ago

Thanks! It's definitely one of my favorite projects I've ever made.

0
big-bill3
big-bill3

2 months ago on Step 1

I’d love to make one of these but I don’t have access to the woodwork equipment.

0
chubflounder
chubflounder

Question 2 months ago on Introduction

wow, that's cool! i'm envious because i've been thinking about doing something like that for years, but i didn't really know how to make it work. i was going to use an old analog clock, and replace the hands with aluminum tube arms terminating in magnetic wheels, the inner hand being smaller and nested in the clearance of the outer hand. but i figured that the balls would have to be hollow to reduce weight, and i didn't really have the skills to make it. your implementation looks great! i also looked at the STORY clock, which i didn't know existed either, and was impressed by the floating ball. how do you think they keep it both levitating and captive? is there a strong magnet directly underneath, with a weaker ring of magnets around the perimeter?

0
sheldor
sheldor

Answer 2 months ago

That was actually my 1st though: buy a cheapo wall-lock, glue a magnet to the end of each handle, put wood-foil all over, attach 2 metall balls and you are done. In 30mins. max and below 10 bux w. the same "mesmerising" effect :)

0
bjm1950
bjm1950

2 months ago

Great work mate, it looks fantastic!
If you coat the veneer with two pack varnish, it will never show a mark where the ball runs. Besides, I doubt the balls would ever leave a mark, as they are rolling and not skidding.