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.
Video of SlapClock
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 !!
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.
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
Wiring Diagram
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
#include
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
Tv1=300;
Tv2=0;
}
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);
delayMicroseconds(DurSlapAct);
delay(Tv2); // Voor later dan 10 Hour niet lineair en later dan 8 Hour lineair !!!!!??
digitalWrite(Slapper, LOW);
delay(1000);
}
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(" ");}
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.
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 !!