Introduction: SlapClock

If you replace a hard disc in your computer by a SSD drive don’t through away the old hard drive, but disassemble that drive.

You will discover then that there is an interesting internal component which is called “actuator”.

The standard function of the actuator is to move an arm across the disc, to read (or write) data from (or to) the hard disc.

The actuator in principle is a copper coil which moves between 2 strong magnets.

By setting a DC supply voltage on this coil I discovered that it is a very powerful construction swinging the arm fast and strong in one direction.

Reversing the polarity swings the arm in the other corner.

From that moment I was thinking “what can we do with this actuator” ….. which brought me on the idea to use it to drive a bearing ball across a sloping curtain rail …… and if possible over a distance depending on the time at that moment.

And that is where this Instructable is about.

Step 1: Video of SlapClock

Step 2: Is That a Clock ...... YES !!

Every 15 seconds the actuator slaps the ball with a power depending on the daytime.

So along the rail you see the numbers 1 thru 12 as the clock time.

Where the ball stops you find the day time ….. so simple is that !

How does it work ??

The whole operation is automatically running after initial startup.

This is realized by using a simple Arduino microcontroller and a small amount of electronic components.

Even the clock function is done by the Arduino with the function “Timer2”.

Initially you have to set once the clock at the correct clock time; to do that you find some pushbuttons as you can see on a picture below.

After that the system will “slap” the clock time every 15 seconds.

Being honest …. your wrist watch will give you a more accuracy time !!

Step 3: How Does This Clock Now the Time ??

Initially the system has no actual physical clock, but a microcontroller –even a simple one- … the Arduino type ProMicro (about $3,=) has sufficient functions that it can realize a clock too.

Using the Arduino function “Timer” you can make this clock; see the program listing for the details. It even is an accurate clock ….. up to a few seconds per day.

By default the clock is set at 6:00, so at about midscale.

At startup you much set the clock once at your time of the day.

For that prose I installed 5 pushbuttons on the control box.

Pressing the most left button you give a slap, and depending on where the ball stops you set the time 1 hour or 15 minutes later or earlier.

Step 4: Bill of Materials

- 1 Arduino model “Pro Micro”, any other Arduino/microcontroller

- 1 Actuator from a demolished hard drive

- 1 Power supply unit …. I used a unit 230V AC to 18 V DC (from an old printer)

- 1 Voltage regulator for the 12 V DC power supply of the Arduino

- 1 Power chip to drive the actuator … I used a NPN type D1481, 60 V, 2 Amp

- 1 Board to install the electronic stuff

- 1 Curtain rail, e.g. 1.6 meters long

- 1 Ball out of a bearing … I use one with a diameter of 19 mm

- Some small mechanical and electrical components

Step 5: Wiring Diagram

Step 6: Arduino Program

// SlapClock April 2020

// By : Gerrit van Zeijts

// Technical Details/Assumpions :

// - 1 Slap each 15 Seconds

// - Ball Diameter 19 mm

// - Length of rail in total 165 cm

// - Length of rail 0-12 Hours 135 cm

// - Slope of rail 5 mm each 1000 mm


int Hour; String HourStr;

int Minutes; String MinutesStr;

int Sec; String SecStr;

String Time;

String DPS; // "-" for displays

String SpaceS; // " " for displays

int Slapper=9; // Is the Actuator

int KnobHoursLater=19; // Button Hour Later

int KnobHoursEalier=14; // Button Hour Ealier

int KnobMinutesLater=18; // Button X Minutes Later

int KnobMinutesEalier=15; // Button X Minutes Ealier

int KnobSlap=16; // Button Give Slap

int MeasuredHourEarlier; int MeasuredHourLater; // Result of reading Knob

int MeasuredMinutesEalier; int MeasuredMinutesLater; // Result of reading Knob

int MeasuredKnobSlap; // Result of reading Knob

double DurSlapAct; // Duration power on Actuator Actual in microseconds

int DurHourSlap[13]; // Duration power on Actuator by current (xx)Hour in microseconds

double DurMinutesSlap; // Duration power on Actuator by current Minute in microseconds

double DurHourSlapInterval; // Duration of interval between current and next Hour in microseconds

double MinToHour; // Minute (current Time) to decimal Hours (e.g. 45 Min = 0.75 Hour

int Tv1; // Used for Time delay()

int Tv2; // Used for Time delay()

void setup()

{ Serial.begin(9600);

MsTimer2::set(1000, flash); // Run flash() every 1000 mSec

MsTimer2::start(); // Start the Clock

pinMode(Slapper, OUTPUT); digitalWrite(Slapper, LOW);

pinMode(KnobSlap, INPUT); digitalWrite(KnobSlap, HIGH); // Internal Pull up

pinMode(KnobHoursLater, INPUT); digitalWrite(KnobHoursLater, HIGH); // Internal Pull up

pinMode(KnobHoursEalier, INPUT); digitalWrite(KnobHoursEalier, HIGH); // Internal Pull up

pinMode(KnobMinutesLater, INPUT); digitalWrite(KnobMinutesLater, HIGH); // Internal Pull up

pinMode(KnobMinutesEalier, INPUT); digitalWrite(KnobMinutesEalier, HIGH); // Internal Pull up

DPS="-"; // "-" for displays

SpaceS=" "; // " " for displays

DurHourSlap[1]= 4600; DurHourSlap[2]= 6800; DurHourSlap[3]=8700; DurHourSlap[4]=10560; // Duration in MicroSeconds of Slap for [x] Hour

DurHourSlap[5]= 12650; DurHourSlap[6]=14100; DurHourSlap[7]=15565; DurHourSlap[8]=17000; // Duration in MicroSeconds of Slap for [x] Hour

DurHourSlap[9]= 18100; DurHourSlap[10]=19085;DurHourSlap[11]=19600; DurHourSlap[12]=20520; // Duration in MicroSeconds of Slap for [x] Hour

DurHourSlap[13]=21000; // Duration in MicroSeconds of Slap for 13 Hour (interpolated value)

Hour=6; Minutes=0; // Default values during startup




void loop() //

{ MeasuredHourLater=digitalRead(KnobHoursLater); if (MeasuredHourLater==0) {Hour=Hour+1; // Set Clock 1 Hour Later

if (Hour>12){Hour=1;} delay(Tv1);}

MeasuredMinutesLater=digitalRead(KnobMinutesLater); if (MeasuredMinutesLater==0) {Minutes=Minutes+15; // Set Clock 15 Minutes Later

if (Minutes>60) {Hour=Hour+1; Minutes=Minutes-60;} delay(Tv1);}

MeasuredMinutesEalier=digitalRead(KnobMinutesEalier); if (MeasuredMinutesEalier==0) {Minutes=Minutes-15; // Set Clock 15 Minutes Earlier

if (Minutes<0) {Hour=Hour-1; Minutes=Minutes+60;} delay(Tv1);}

MeasuredHourEarlier=digitalRead(KnobHoursEalier); if (MeasuredHourEarlier==0) {Hour=Hour-1; // Set Clock 1 Hour Earlier

if (Hour<1) {Hour=12;} delay(Tv1);}

MeasuredKnobSlap=digitalRead(KnobSlap); if (MeasuredKnobSlap==0) {CalculateDurSlap(); GiveSlap(); delay(1000);} // Give Slap

if (Sec==1) {CalculateDurSlap(); GiveSlap();} if (Sec==15) {CalculateDurSlap(); GiveSlap();} // 1 Slap per 15 Seconds

if (Sec==30) {CalculateDurSlap(); GiveSlap();} if (Sec==45) {CalculateDurSlap(); GiveSlap();} // 1 Klap per 15 Seconds

// DisplayMonitor(); // Just for Testing


void GiveSlap()

{ Serial.print("From GiveSlap : ");

Serial.print("Time = "); Serial.print (Time); // Testing

Serial.print(" DurSlapAct = "); Serial.println(DurSlapAct); // Testing

Serial.println(" ");

digitalWrite(Slapper, HIGH);


delay(Tv2); // Voor later dan 10 Hour niet lineair en later dan 8 Hour lineair !!!!!??

digitalWrite(Slapper, LOW);



void CalculateDurSlap()

{ DurMinutesSlap=0;

MinToHour=100*Minutes/60; // Minutes to decimal Hours

DurHourSlapInterval=abs(DurHourSlap[Hour+1] - DurHourSlap[Hour]); // Interpolation between 2 values of DurHourSlap[x]

DurMinutesSlap=abs(MinToHour * DurHourSlapInterval /100); // Interpolation of Slap Duration caused by Minutes

DurSlapAct=(DurHourSlap[Hour] + DurMinutesSlap); // Total Duration of Slap

if (DurSlapAct>15000) {Tv2=15; DurSlapAct=DurSlapAct-15000;} else {Tv2=0;} // xxxxx in delay(xxxxx) is limited to about 15000 in Arduino program !!!!!!!!

Time=HourStr + DPS + MinutesStr + DPS + SecStr;

Serial.print("From CalculateDurSlap : ");

Serial.print("Time = "); Serial.print(Time);

Serial.print(" DurSlapAct = "); Serial.print(DurSlapAct);

Serial.print(" MinToHour = "); Serial.print (MinToHour);

Serial.print(" DurMinutesSlap = "); Serial.print(DurMinutesSlap);

Serial.print(" DurHourSlapInterval = "); Serial.print(DurHourSlapInterval);

Serial.println(" ");}

void flash() // Function is to realize a clock by using the internal function "Timer2" (Turns out to be very accurate .... some seconds/day !!!)

{ Sec++;

if (Sec>60) {Sec=0; Minutes++;} SecStr=String(Sec); if (Sec<10){SecStr = (SpaceS + SecStr);} // Updating Sec

if (Minutes>59) {Minutes=0; Hour++;} MinutesStr=String(Minutes); if (Minutes<10){MinutesStr = (SpaceS + MinutesStr);} // Updating Minutes

if (Hour>12) {Hour=0;} HourStr=String(Hour); if (Hour<10){HourStr = (SpaceS + HourStr);} // Updating Hours

Time=HourStr + DPS + MinutesStr + DPS + SecStr; // Updating variable "Time"


void DisplayMonitor() // Only for Testing the program

{ Serial.print("Time = "); Serial.print(Time);

// Serial.print(" Hour= "); Serial.print(Hour);

// Serial.print(" Minutes= "); Serial.print(Minutes);

// Serial.print(" Sec= "); Serial.print(Sec);

// Serial.print(" MeasuredMinutesLater= "); Serial.print(MeasuredMinutesLater);

// Serial.print(" MeasuredMinutesEalier= "); Serial.print(MeasuredMinutesEalier);

// Serial.print(" MeasuredHourLater= "); Serial.print(MeasuredHourLater);

// Serial.print(" MeasuredKnobSlap= "); Serial.print(MeasuredKnobSlap);

// Serial.print(" MeasuredHourEarlier= "); Serial.print(MeasuredHourEarlier);

// Serial.print(" MeasuredHourEarlier= "); Serial.print(MeasuredHourEarlier);

Serial.println(" ");}

Step 7: Notes to the Pargram and the Technical Setup


The program itself contains a lot of information and explication

- The different slaps given by the actuator at e.g. 1:00 or 10:00 o’clock are realized by “playing” with the length of time in which the actuator is activated.

At 1:00 o’clock the actuation time is 4600 microseconds and

At 10:00 o’clock the actuation time is 19085 microseconds

The calculation of this duration of time at e.g. 10:45 is as follows :

o for 10:00 o’clock take 19085

o for the 45 minutes make an interpolation between 11:00 and 10:00 o’clock,

so this slap must be 19085 + 0.75(19600-19085) = 19471 microseconds

So the actuator must be energized during 19471 microseconds

- For abovementioned duration of time I used the statement “delayMicroseconds(19471);”, but unfortunately this statement is limited to maximum of 16383 !!.

In the program this is solved by using “delay(15); delayMicroseconds(4471)”

- The coil of this type of actuators mostly have a resistance of 8 to 12 Ohms.

Using e.g. a supply voltage of 18 V DC this means that normally the coil will smoke within some seconds.

Using this voltage just for maximum 30 milliseconds in interval times of e.g. 15 seconds will not harm the coil.

Step 8: How to Get an Actuator ?

Disassemble a hard drive as used in desktop computers.

Remove the electronics and the disc(s) with their drives.

Saw the actuator base plate to get the green circled part free.

Carefully look for the 2 (very thin) wires of the coil on the arm of the actuator.

You will be astonished about the force delivered by this part !!

Step 9: Layout Control Box

Clocks Contest

Participated in the
Clocks Contest