Introduction: Mechanical Seven Segment Display Clock
A couple of months ago I built a two digit mechanical 7 segment display which I turned into a countdown timer. It came out quite well and a number of people suggested doubling up on the display to make a clock. The problem was that I was already running out of PWM IO on my Arduino Mega and didn't have enough available for the second or third digits. I was then pointed in the direction of these PCA9685 16 channel PWM drivers which operates over an I2C interface. These made it possible to drive the 28 servos I needed all using the two I2C pins on an Arduino. So I got to work building a clock which now uses a DS1302 real time clock module to keep the time and two 16 channel servo drivers to control the 28 servos used to make up the display, all powered by an Arduino Uno.
If you enjoy this Instructable, please consider voting for it in the Clocks Contest
- Arduino Uno - Buy Here
- DS1302 Clock Module - Buy Here
- 2 x PCA9685 16Ch Servo Drivers - Buy Here
- 28 x Micro Servos - Buy Here
- Ribbon Cable - Buy Here
- Male Pin Header Strips - Buy Here
- Female Pin Header Strips - Buy Here
- 3mm MDF - Buy Here
- Black Spray Paint - Buy Here
- 5V 5A Battery Elimination Circuit - Buy Here
- 12V Power Supply - Buy Here
For this project you'll also need some 3D printed parts. If you don't already have a 3D printer and you enjoy making thing then you should definitely consider buying one. The Creality Ender 3 Pro used here is affordable and produces pretty good quality prints for its price.
Step 1: 3D Print the Plastic Components
I designed the 7 segment displays to be as simple as possible. The servo is also the support bracket to hold up the segment above it. There are two 3D printed components required for each segment, a spacer block to support the bottom side of the servo and the display segment which glues directly onto the servo arm.
Download the 3D Print Files - Mechanical 7 Segment Display Clock 3D Print Files
Print the servo segments and dots using a bright coloured PLA. I used translucent green, but red, orange or yellow should work well too. I used black PLA for the spacer blocks and dot supports so that they aren't visible when the segments are turned to the off position.
If you don't have access to a 3D printer, try out one of the online printing services. There are a number of affordable services available which will print out the components and deliver them to your door in a few days.
Step 2: Prepare Your Control Boards & Wiring
You'll need to use two PCA9685 16 channel PWM drivers to drive your 28 clock servos. I separated the servos into the hour and minute digits, with each pair of digits being driven by one board. So I have one board controlling the servos for the two hour digits and the second controlling the servos for the two minute digits.
To chain the two together, you'll need to make up a 6 wire ribbon cable connector and solder a second header strip onto the other end of the first servo control board. You'll also need to change the I2C address on the second board so that it is different to the first and uniquely identifiable.
You'll also need to make up the wiring harness to connect the three boards (two servo boards and the clock module) to your Arduino. You'll need 5V and GND to each board as well as the I2C connections to your Arduino pins A4 and A5 (I2C on Arduino Uno), and the clock module pins CLK, DAT & RST to pins 6,7 & 8 on your Arduino respectively.
Power is supplied to the Arduino directly from the 12V power supply and to the servos using the 5V 5A BEC which is then connected to the two terminals on the top of the PWM driver. You only need to connect one servo driver to power and it will feed power to the second through the 6 wire ribbon cable connection.
Step 3: Assemble the Servos
Once you've printed your segments you'll need to spray the back and sides black so that they're less visible when they're turned 90 degrees to the off position.
You then need to glue the segments onto your servo arms with hot melt glue. It helps to glue them onto the servo with the arm already on the servo, this way you can check that you're gluing them on straight and level.
You'll also need to glue a spacer block onto the bottom of each servo.
Assemble the dots by gluing a small dowel or kebab stick into the back of the dots and then into the base blocks. I sprayed these sticks black as well so that they're less visible if viewed from an angle.
Step 4: Set Up & Testing
I numbered all of the servos and wrote the number onto each lead so that it was easier to keep track of them. I started with the top segment on the units digit and worked around to the middle segment on the tens digit. This is also the order in which I plugged them into the servo control boards, remembering that the identifiers on the boards count from 0 to 13 and not from 1 to 14.
I then set the segments up on a table with enough space between them for testing so that they didn't move into one and other while getting the travel limits and directions set up. If you try set them up close together you'll likely have one or two try to move in the wrong direction or over travel at some stage and hit another which may damage the segment, servo arm or strip the gears on the servo.
Step 5: Uploading the Code
The code looks complicated at first glance, but it's actually relatively simple thanks to the two libraries used. There is also a lot of repetition because there are four different 7 segment displays needing to be updated.
Here's a summary description of the code, have a look at the full guide for a more detailed explanation and a link to download the code - Mechanical 7 Segment Display Clock
We start by importing two libraries, virtuabotixRTC.h for the clock module and Adafruit_PWMServoDriver.h for the servo drivers. The Adafruit library can be downloaded and installed directly through the library manager in the IDE.
We then create an object for each control board with the relevant address, one for the hour digits and one for the minute digits.
We then have four arrays to store the on and off positions for each servo. You'll need to make adjustments to these numbers in the coming steps to make sure that your servos are upright when on, turned 90 degrees when off and don't over travel.
A digit array stores the positions of each segment for each digit to be displayed.
We then set up the clock module and create variables to store the current and past individual digits.
In the setup function we start and set up the PWM control boards as well as update the clock time if required. We then run through a loop to set the display to 8 8 : 8 8 so that we know the starting position of all of the servos. This is also used to set up the servos so that they're all facing upwards correctly.
In the main loop we get the updated time from the clock module, spilt it into the four digits and then check whether the time has changed from the last check. If the time has changed then we update the display and then update the previous digits.
In the update display function, we first move the middle segments. This is done first because there is some logic required to move the two top segments adjacent to the middle segment out of the way a little before moving the middle segment, otherwise it will bump into them. Once the middle segments are moved then the remaining segments are moved the the correct positions.
Step 6: Assembling the Clock on the Back Board
Once I was done with the testing, I assembled the servos onto the back board using the above layout as a guide.
The white area is the overall board size, the lighter grey is the area surrounding each digit where the servo segments move into and the outline on the dark grey area is the centre line for the outer 6 segments for each digit.
I cut the board, marked up the layout and then glued the digits in place to make up the clock face.
I then drilled holes near each servo and fed the wires through to the back of the board so that they're less visible.
I mounted the electronics onto the back of the clock with double sided tape.
Step 7: Final Setup & Operation
Once the servos were all ready, I removed all of the servo arms for the final adjustments to the positions of the segments. You should power up the Arduino in this state so that 8 8 : 8 8 is displayed and then disconnect the power, this re-centres all of your servos so that you can put the servo arms back on with the segments facing as close to vertical as possible.
You'll then need to sequentially power up your Arduino and make adjustments to your segment on and off positions in your four arrays so that the servos are perfectly vertical when on and turn through 90 degrees when off without over travelling. This step is quite time consuming and requires a bit of patience but the end result is well worth it!
The clock can be left powered using the 12V power supply and 5V BEC connected to it. If the power goes down, the battery on the RTC module will keep the time so that when power is restored, the clock automatically resets to the correct time.
If you enjoyed this Instructable, please vote for it in the Clock contest and let me know of any improvements or suggestions you can come up with in the comments section below.
Second Prize in the