This week has been another very productive one! Let’s dig in and check out the progress!
Building
As you might recall, I left off last week with the inlays drilled to lay the stepper motors in. On Monday I jumped straight in where I left off by sanding down these inlays. My goal here was to help promote a better fit as well as easier adjustment. Below is a photo of these inlays.
After cleaning up the inlays, I was able to add some legs to the back of the clock face, acting as a support to keep it upright. I was also able to add adjustable rubber feet onto these to ensure the clock’s stability.
After I had this done, I attached a spacer to the front clock face (displaying hours). Lifting it from the rest of clock, this allows for the 2nd clock face (displaying minutes) to be accessible from the stepper motors. Pic below
After I was able to get the main pieces of the clock’s frame assembled I moved on to the remaining parts. I fitted the stepper motors in their inlays, and attached the pulleys to the motors. I then attached some rope to the gears I’m using to display the time. This brought it all together and allowed a peak into the final product.
After I got everything assembled, I quickly tore it back apart. I had stained the wood already but now it was time to add a top coat. I went with a semi-satin finish to bring the grain out without making it too glossy. Unfortunately, there’s a 24 hour drying period between coats so from Friday forward I had to put a hold on things while applying coats and waiting for them to dry.
I’m happy to say I hit my goal for the week, and even added onto it with the top coat I didn’t originally factor in (use protection kids!). This upcoming week, I’m hoping to fit all the electronics to the model, and get a start on translating that code from my first render into C+. Thanks for reading, stay posted 🙂
I kept very busy this week and I am excited to share the progress with you all. I mostly focused on the physical clock, so this article should be a little bit more palatable.
Design
So, going into this week, I was planning to create the first fully functioning prototype. With that, I clearly needed a design to base all of this off of. I started brainstorming how both the minute and hour could be displayed on the same clock without interacting. If they were on a flat face, they would collide with each other. After a while I came up with the design below.
With this design, I created a very rough model using the previous prototype that I would be replacing.
Creation
Now, I had the design smoothed out, and was ready to get working. I ran to the store, and got all the supplies I thought I needed (keyword: thought) and got straight to work! I began by cutting out the outer clock face, and sanding it up to 600 grit for a nice finish, I also did this to the base of the clock after cutting the 12×12 panel out.
I realized I didn’t have all the tools needed, and kept running into this issue. Each step seemed to require a new tool, so this delayed progress by quite a bit. While I was making these runs, I found some very fascinating antique mechanical gears. I found this perfect to help the style of the clock. I let the gears soak in a mixture of vinegar, salt, and hydrogen peroxide. This promotes oxidization of the gears, and gave them the patina look I wanted.
Now, with more equipment, I was able to start drilling out the inlays for the stepper motors to set in. To my surprise, this idea worked, I was certain I would end up drilling through and having to deal with blemishes on the front.
The furthest my progress got this week was left at the motor inlays. I have all the supplies I need (I’m hoping) and all the plans made. All that remains is connecting the dots and getting it done.
Thanks for checking in, and make sure to stay posted.
I would like to preface this by acknowledging the delay of this entry. I’ve been developing this project for the past 4 weeks, but have not had the chance to enter any updates. With that out of the way, let’s catch up to speed.
Concept
I cannot take credit for the initial Idea behind the clock, it was proposed to me by my brother and colleague, Travis Adsitt. He prompted me initially with a task, to write a function that would represent the length of two strings, attached to either side of a weight, that would move the weight in a circle. In this model, the weight would be the indicator of time, as it would move in a circular motion on a clock face, and wherever it lay is the current time. To help visualize this, I have attached a rough render of this idea.
Now with this concept, it clearly needs a lot to bring it to life. I began by creating functions for the length of the string using the following steps:
Locate the point of the rotor
Locate the point it meets the circumference of the circle
Find the distance between the points
This was relatively simple to do, and I was able to create a working script in Python. This script was relatively simple, it used parsArgs to take user input of the position of the rotors, as well as the diameter and position of the clock face. I then used a “For Loop” in this script, and had it output a render of each value that was put in, or create an image for each hour and minute on the clock. I was able to compile these images into an animation, which is below.
Supplies
Now with this render completed, and knowing I had gotten the math stapled, the next step was to begin working with some hardware. Most of the materials are readily available, and I will list below for reference.
Other – Thread, Simple thread spool, Cardboard for body, and a ring, working as the weight
Single Motor Testing
With these positioned using a cardboard frame, the first prototype was created. Of course, it still needed to be developed and functioning. To start with this, I downloaded the Arduino IDE and plugged into my ESP32, and got straight to working. I began with using the myStepper library, just at an attempt to get a single stepper motor moving, as it is the most basic, yet important piece of the project. Below is the initial code snippet, using the myStepper library.
void setup() {
//Set Stepper Speed
myStepper.setSpeed(5);
//Begin Serial Monitoring
Serial.begin(115200);
}
void loop() {
// Run stepper motor, with steps set
myStepper.step(stepsPerRevolution); //move clockwise 1 rotation
delay(1000);
myStepper.step(-stepsPerRevolution); //move counter-clockwise 1 rotation
delay(1000);
while(true){};
}
Above the visible segment attached, I defined stepsPerRevolution as 2048, the number of steps for a full revolution, which is specific to the 28BYJ-48 Motor. Upon uploading this segment, the single motor connected should do 1 full rotation clockwise, followed by 1 full rotation counter-clockwise. It then ends with a while(true) loop, so that the program can continue to run without looping endlessly.
Two Motor Application
Now, the next step in this process is to get two stepper motors, with individual control. Since this is not supported in the myStepper library, I switched to the accelStepper library, as it is designed for multiple stepper motors.
void setup()
{
// Set Maximum Speed, Acceleration
stepper1.setMaxSpeed(300.0);
stepper1.setAcceleration(200.0);
// Repeat for stepper2
stepper2.setMaxSpeed(300.0);
stepper2.setAcceleration(200.0);
}
void loop()
{
stepper1.moveTo(2048); // set target forward 2048 steps
stepper2.moveTo(2048); // set target forward 2048 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(0); // set target back to 0 steps
stepper2.moveTo(0); // set target back to 0 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
}
With this segment, I was able to get both motors to do a full rotation clockwise, or move forward 2048 steps, before moving counterclockwise a full rotation, back to the original position.
Controlling String Lengths
With the ability to move both motors, now all I needed to do was control the rotations and move the weight to specific positions. To begin with this, I positioned the weight at the bottom of the circle I wanted to use as my clock face. From now on, this is position zero. From position zero, I moved the left motor Counter-Clockwise, and the right motor clockwise, moving the weight upward. I repeated this in 500 step increments, until I reached the top of the clock face. I took careful note of how many steps it took to go from top to bottom of the face, and how much the string length changed. My documentation of these changes is below.
Testing a Sample Set
With this information, I knew how to adjust the string length in centimeters, by changing the number of steps on either motor. I had observed and then verified that rotating one motor a full rotation, or 2048 steps, resulted in the correlating string length changing by 10 centimeters, dependent on the direction of rotation. To move forward from here, I then did the calculations given the motor positions as well as the position and specifications of the clock face, to find a sample set of points around the clock. I took each hour and found the string lengths needed, and then converted those lengths and converted them into the steps for each motor. Once I got these values verified I made a table of the values and where each motor needed to be for each hour.
I then put these values into my Arduino IDE, and was able to format it in a manner that the motors would move to the positions specified, at the same time, with the same rate of change. The code for this is very similar to the test values, just extended for each of the hours. The code is attached below.
void setup()
{
// Set Maximum Speed, Accelleration
stepper1.setMaxSpeed(300.0);
stepper1.setAcceleration(200.0);
// Repeat for stepper2
stepper2.setMaxSpeed(300.0);
stepper2.setAcceleration(200.0);
}
void loop()
{
stepper1.moveTo(-3200); // set target forward 500 steps
stepper2.moveTo(-3200); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-4190); // set target back to 500 steps
stepper2.moveTo(-1966); // set target back to 0 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-4506); // set target forward 500 steps
stepper2.moveTo(-817); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-3842); // set target forward 500 steps
stepper2.moveTo(80); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-2670); // set target forward 500 steps
stepper2.moveTo(391); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-1415); // set target forward 500 steps
stepper2.moveTo(252); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(0); // set target forward 500 steps
stepper2.moveTo(0); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(252); // set target forward 500 steps
stepper2.moveTo(-1415); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(391); // set target forward 500 steps
stepper2.moveTo(-2671); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(80); // set target forward 500 steps
stepper2.moveTo(-3842); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-817); // set target forward 500 steps
stepper2.moveTo(-4506); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
stepper1.moveTo(-1966); // set target forward 500 steps
stepper2.moveTo(-4190); // set target forward 500 steps
while (stepper1.distanceToGo() != 0 || stepper2.distanceToGo() != 0)
{
stepper1.run();
stepper2.run();
}
}
You will notice this segment is extremely inefficient and lengthy, but that’s alright, as it is just a test set, and will not be used in the final iteration of the project. After writing these values in, I was able to upload the script, and watch the first working version of the clock. The video is attached below.
Conclusion and Final Thoughts
Now, as you may notice, these number sets only apply to the specific clock diameter, motor position, and pulley diameter that relate to this specific model. My goal now, is to allow this script to be fully adjustable, so the user can simply input the measurements of the specific clock being used, and it will perform the necessary functions to find the string lengths needed. This process is still under-way but can be expected soon. I will cover the creation of these functions as well as go into detail on the physical clock prototype in my next entry. Stay posted.