Astronomer's Watch

This project is a pocket watch with a hidden twist: inside, it holds a miniature solar system. At the press of a button, the Astronomer’s Watch wakes up and calculates the positions of the six major planets using real orbital math (Kepler’s laws). The planets then spin into place, aligning with the zodiac ring engraved in the lid. After a short performance, the watch quietly returns to sleep until the next time you call on it.
High-end watchmakers like Van der Klaauw sell astronomical watches that cost upwards of $50,000. I wanted to capture some of that same wonder in a DIY project that you can actually build yourself for a fraction of the price.
The watch body started as a regular pocket watch, but I extended the case with a 3D-printed ring to make room for the motor, battery, and two PCBs. The mechanism itself is surprisingly simple: a single stepper motor drives drives Saturn around using a small gear. The other planets are put into place with little push tabs.
At the heart of the build is a Seeed Studio ESP32-C6 microcontroller paired with a low-voltage stepper driver. Together, they keep the system small enough to run inside the compact case. The result is not a clock in the usual sense, but a pocket-sized solar system and one you can make yourself.
Supplies

- a tiny stepper motor (aliexpress)
- stspin220 low voltage stepper motor controller (Pololu)
- small battery 3.7V 100mAh (I bought from a different seller but I believe these are the same: aliexpress)
- Seeed XIAO esp32C6 (seeedstudio)
- sheet of 0.2 mm brass
- sheet of 0.1 mm brass
- pocket watch (aliexpress)
- two 10kΩ resistors
- 2 mm brass tube (for the axle)
- tiny reed switch (aliexpress)
- earrings for the planets (6 x 2 mm) and the sun (1 x 2.5mm) (aliexpress)
- super thin disk magnet 10mm in diameter (reclaimed from some packaging of my phone)
You'll need a 3d printer, M2 tap set, soldering iron, super glue, wires and a cnc or jigsaw for cutting disks out of the brass sheets
The Casing

Start by opening up the pocket watch. Unscrew the crown, then remove the back and take out all of the original contents. The glass should come out as well. Since the crown and button are no longer connected to anything, glue the crown back onto the housing with a small drop of super glue. Be careful here: the button still needs to move freely, because its pin will be used as the switch.
With the case prepared, print the provided STL files. For the housing extension I used silk green filament, which pairs nicely with the brass of the original watch. I printed with a 0.2 mm nozzle, but a 0.4 mm nozzle will also work fine.
The second STL file is the internal frame — this part keeps all of the electronics securely in place.
This is a good moment to scroll ahead and check the photos in the following steps. They show how the internal frame fits inside the watch case. The frame doesn’t need screws or glue — it snaps into place with a slight twist. The same goes for the 3D-printed housing extension; a gentle turn is all it takes to lock it securely. Give it a try.
Brass

The planets are made from earrings and mounted on 0.2 mm brass disks. Each disk has a round center hole so it can rotate freely on a 2 mm brass tube axle. I used tube instead of solid rod because it makes mounting the Sun in the center easier. The top of the tube is filed into a rectangular shape, and at the other end I cut an M2 thread. With an M2 nut and a drop of super glue, the tube stays firmly in place.
Between the planet disks are separator disks cut from 0.1 mm brass. These are slightly smaller in diameter and have a rectangular center hole. The hole must fit tightly on the filed section of the tube, so the separator disks stay fixed and do not rotate.
To make a planet disk, cut it from brass (0.2 mm for most, 0.1 mm for Saturn). Drill a 2 mm hole in the center for the axle, and a 0.7 mm hole near the edge for the planet. Push the planet pin through the small hole, secure it with a drop of super glue, then trim the back and file it smooth. I airbrushed my disks with a blue gradient, though the bare brass looks good as well.
The Saturn disk can be made from 0.1 mm brass since it is glued directly to the main gear for extra rigidity. For reference, Saturn’s disk is 33 mm across.
You can cut the disks with a jigsaw or strong scissors. I used my Snapmaker with the CNC head.
The little tabs on the planet's disks are important as only Saturn is driven by the motor and at some point Saturn will push against the tab on Jupiter's disk, and Jupiter will push against the tab on the disk of Mars, etc. It's a clever trick that makes the planets move without adding a complex gearing mechanism.
Gears

3D print the included gears. An FDM printer with a 0.2 mm nozzle will work fine, but a resin printer produces a sharper tooth profile. Glue Saturn’s disk onto the main gear, then glue the ultra-thin magnet in the large center hole. Mount the small gear onto the motor shaft with the hollow side facing the motor, and secure it with a drop of super glue.
Wiring the Electronics



The wiring is straightforward, but it does require some care because of the tight space. The ESP32-C6 and the STSPIN220 are joined through a 7-pin header supplied with the motor driver. First, slide the STSPIN220 onto the header pins, but leave the ENABLE pin unconnected. Then slide the ESP32 board onto the same header as shown in the diagram. Solder the ESP32 in place, flip both boards over, remove the plastic spacer from the header, and solder the STSPIN220. Once everything is secure, trim the excess header pin length.
On the STSPIN220 you will also need to remove the pull-up resistor on the STDB pin, otherwise it forces the driver out of standby. Instead, add an external pull-down resistor to STDB. This ensures that when the watch is idle, the motor driver stays in low-power standby. With the ESP32 also going into deep sleep, the total standby current should be in the 7–8 μA range (based on the datasheets).
The stepper motor connects via a small solder pad. Do not remove the pad; it also links the internal coil wiring. Solder your wires directly to the contacts on the pad. If you’re unsure which wires belong to each coil, use a multimeter to measure resistance between pad points: the two points that show continuity belong to the same coil.
The case switch is made from two small brass parts, visible in the photo. The lower brass strip connects on its left end to one side of the reed switch (the reed switch itself fits in the rectangular slot). The right end of this strip sits between the spring of the case and the case itself, and is tied to 3.3 V. The upper brass piece has a thin finger that protrudes through the 3D-printed housing; when assembled in the case, its right end sits just in front of the watch’s crown. Pressing the crown connects 3.3 V from the lower brass strip, through the case and knob, onto the upper brass piece. Solder a short wire from this upper brass part to the MTDO pad on the back of the ESP32.
Don’t forget to add the two external pull-down resistors as shown in the wiring diagram.
Finally, connect the battery: solder it to the power pads on the back of the ESP32. Also connect VMOT on the STSPIN220 to the battery’s positive terminal. This way, both the ESP32 and the motor driver draw directly from the same source.
For testing, I preferred not to keep the battery connected all the time. Instead, I left the battery out and powered the driver by linking VMOT to the 5V pin on the ESP32. This setup made it easier to experiment without having the battery permanently supplying the circuit.
Programming

With the wiring complete, the next step is to program the ESP32-C6. If you have not worked with ESP32 boards before, don’t worry — it only takes a few minutes to get the Arduino environment set up.
1) Install Arduino IDE
2) Download and install the latest Arduino IDE from the Arduino website.
3) Add ESP32 support
- Open Arduino IDE.
- Go to File > Preferences.
- In the field Additional Board Manager URLs, paste the ESP32 package link:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
- Press OK.
4) Install the ESP32 board package
- Go to Tools > Board > Board Manager…
- Search for “esp32”.
- Install the latest package from Espressif Systems.
5) Select your board
- Go to Tools > Board > esp32 > ESP32C6 Dev Module.
- Select the correct port under Tools > Port (it will usually show up after you plug the board in with USB).
6) Upload the code
- Download the sketch from this link.
- Open it in Arduino IDE.
- Click the Upload button (the right arrow).
- The code will compile and transfer to the ESP32-C6.
Once uploaded, the watch is ready to run. When you power it up, it will initialize and wait for input from the case button or through the usb connection.
Important: Once the code is running, the ESP32 will eventually go into deep sleep to save power. If you want to upload new code later, you’ll need to wake it first by pressing the watch’s button. If the watch is not assembled yet, you can simulate the button press by briefly touching a wire between 3.3 V and MTDO.
Depending on how you wired the motor, it might turn in the opposite direction as shown in the video. When that happens change the "deg < 0" to "deg > 0" in the code for the rotate function at line 253.
Mounting

When everything seems to work, it is time to mount it together. Unfortunately I couldn't find a good way to mount the motor in a removable way, so you'll have to super glue that in place. The battery goes next to it (it doesn't need glue), the reed switch goes in the small rectangular hole (where it can detect the magnet of Saturn's disk) and the combo of esp32 and stspin220 goes on top. On the other side you mount the planets and the separator disks. Use a bit of superglue to mount the sun in the center. This also holds the disks in place. In order to do a better job of keeping the other disks in place I glued a tiny 0.2mm disk with a 0.7mm hole to the sun before mounting it on the tube.
When you put the whole thing in the case, make sure the brass part goes between the spring of the lid and the casing. You should then twist it in place. The larger housing you printed in the first step covers the electronics and also twists in place. But before you close it, it needs to be calibrated so the position of the planets matches the zodiac on the lid. You can do that by adjusting the value in planets[0].touchValue (the sixth number on line 121 of the code). First connect the watch through USB. Wake it up and use the h command for getting help, then the d command for setting the date. press p to let the watch align all the planets. Simply compare with some online solar system and adjust the value accordingly.
In the definitions op planets[] at line 121 there is a column with slack values. Ideally those are 0, but if a separator disk and the planet above it move a little, you can put the amount it rotates in this column, to compensate for it.
Usage

When you open the watch, the motor makes a quick left–right movement to show that it is awake. Double-tap the button, and all the planets rotate into their correct positions. It is a fascinating sight.
The watch needs to know the current date in order to place the planets correctly (you already did that in the previous step so you can skip this). You can set the date in two ways:
- Through USB: connect the watch and press h for help.
- Through the button: hold the button for 5 seconds to enter date entry mode. You then “tap out” each digit of the date. Short taps give the number, and a long tap ends that digit.
For example, to enter the date 24-01-2025:
- 2 → tap, tap, long tap
- 4 → tap, tap, tap, tap, long tap
- 0 → long tap
- 1 → tap, long tap
- 2 → tap, tap, long tap
- 0 → long tap
- 2 → tap, tap, long tap
- 5 → tap, tap, tap, tap, tap, long tap
If you make a mistake, simply stop tapping. After 10 seconds the watch cancels date entry mode, and you can start again by holding the button for 5 seconds.
Once a day, the watch wakes up on its own to advance the date. If the battery runs out, it remembers the last date you entered and continues from there once recharged.
By looking at the position of the earth in the zodiac, you can always tell which time of the year it is.