Home › Forums › Clocks and Scientific Instruments › DIY Pendulum Timer – GPS-Synced Beat Analyser
Hi all,
After completing a long-term project building a miniature Tower Clock, I wanted to take it a step further and look into the accuracy of the pendulum and more importantly, try and get it in time. Maybe I was over complicating things, but the closer I got to good time keeping, the harder it was to measure the error accurately and I had to leave it a long time to do so. I never built the clock to be a regular but I`d like to have it running as accurately as I can.
I saw a post a little while ago by SillyOldDuffer and got in contact with him. He was kind enough to show me a code he had used with Ardunio to do some beat analysing. I built a working version of this and did a few other functions and it kind of escalated, inspired by commercial systems like the MicroSet and eTimer, but built from low-cost components and Arduino IDE. I also switched from Arduino to ESP32 as it allows wifi and bluetooth but still used the Arduino IDE.
The timer uses an ESP32, GPS module (with PPS output), a IR sensor on interrupt, and a BME280 environmental sensor to measure beat intervals with microsecond precision. Data is logged to an SD card, displayed on an OLED and more importantly streamed to a live web dashboard (BPS, BPM, drift, asymmetry, temp, pressure, humidity). All the controls are from the dashboard.
My goal was initially just to give me something to show how accurate my clock was running and to help tune it… but the code quickly spiralled!
I have posted to see if anyone is interested in building this or even testing it! I`m sure there are loads of bugs in the code. I whipped the main functions up myself but then not embarrassed to say that I used some AI to code the dashboard! It seems to work quite well.
I`m really keen to know how commercial timers compare to this homemade version. What functions are missing that I could incorporate?
I would appreciate your input and opinions. As I say, I only did it for fun and all the code is available for free and I am just trying to put together a little PCB to package it a bit better.
Comments welcome…. video below showing how it works and the web based dash controls.
https://www.youtube.com/watch?v=zK1QvNsMGSk&t=99s
Thanks a lot
Chris
Hi Chris, congratulations on your nice clock, and welcome to the world of clock timing! I’m afraid I can’t offer any comparisons with the commercial products – actually the main comparison would be with the Microset. I know a couple of people in the UK who have these if you have any questions.
As I understand it you are using the ESP32 to do the time measurement against its internal crystal clock, but calibrating the latter against the 1pps from the GPS, which seems very sensible. One thing I am not sure about with the ESP32/Arduino IDE is the native timing resolution. “Traditional” Arduinos like Uno and Nano with a 16 MHz clock have a time resolution in the micros() function of 4 uS which isn’t great. Dave’s code I think may use the hardware counters directly so give better resolution even on a 328-based Arduino. ESP32 I think has an ARM core probably clocking much faster, I don’t know if its micros() resolution is better, they may have kept it “compatible”. My current clock project uses an RPi Pico which has 130MHz clock, I’m also using the Arduino IDE.
I’ve taken a different approach using a “picPET” http://www.leapsecond.com/pic/picpet.htm, which was developed by Tom Van Baak who kindly supplied a few to me a while back – Dave has one. This is a PIC processor to which you supply a 10MHz signal from an OCXO and trigger pulses from your clock, and it outputs time stamps to 400ns resolution for each edge on a serial port. The code is fully synchronous so there is no jitter as might result from other background software processes or interrupts. The code is somewhere on Tom’s site. I use a Pi to log the serial data to a file for offline analysis. Your dashboard is interesting – for a lot of things long-term data is what I want but for setting a clock up having real-time diagnostics is very useful, so I would be very interested in your code.
You mention an IR sensor – is this a slotted opto? I have had problems with these due to ambient light, and it can be very difficult to “keep them in the dark” sufficiently if you want to see very small time changes. But there isn’t anything much better unfortunately! There are also some subtleties about interpreting the results especially if the sensor is not quite on centre. If you really want to go down a rabbit hole on this you might look at https://groups.io/g/Horological-Science-Newsletter/topics and have a browse. In particular threads by Joe Noci (well known here) who is doing some fascinating pendulum stuff. And there is a newsletter which is published 3 or 4 times a year
Hello John,
I really appreciate you taking the time to share your experience and suggestions. It’s great to connect with someone who’s worked hands-on with the picPET and Tom Van Baak’s design.
Yes, you’re absolutely right — my setup is based on an ESP32 DevKit board, and I’m using it to measure pendulum beats against its internal clock, while also using the 1PPS signal from GPS to calculate and correct for clock drift in real time. This gives me a fairly stable and accurate reference, without needing external frequency standards or specialist timing chips. Although I’m not adjusting the hardware clock directly, I’m applying a live drift correction based on the PPS interval to keep the timing accurate over long runs — so I’m essentially working with a self-correcting timebase, and it’s proven to be fairly stable so far as I can tell!
On timing resolution: you’re right that traditional Arduinos are limited, but the ESP32 offers 1 µs resolution with micros(), and my code uses interrupt-driven capture with portMUX locking to keep jitter low. That’s proven accurate enough to detect fine variations in beat intervals and asymmetry. I haven’t implemented direct cycle counter access yet, but it’s something I may explore later to push the precision even further. I need to do a bit more reading about this.
I’d like to think the system holds its own in terms of timing precision. I think the sensor needs more work. The IR sensor I’m using is a reflective type (TCRT5000) rather than slotted. I did not look for long, but I could not find anything that would provide a deep enough slot to accept the pendulum and be central. Like you said, ambient light can be a challenge but I`ve only really noticed any effect on a very bright sunny days with direct sunlight coming in through the window (coincidently over the last few days).
I really appreciate the recommendation to check out the Horological Science Newsletter group – I hadn’t seen the Joe Noci threads before, and they sound a good read.
Cheers
Chris
The sensor I use is the Sharp GP1A57HRJ00F, which has a 10mm gap and 12mm depth. I improved it a lot by cementing an IR filter over the receiver side but there is still some sensitivity which shows itself as timing errors in sunlight. I have been using electromagnetic impulsing and experienced such strong effects that the clock would actually stop in the early morning when it was in the low sun. Thanks for the info on the ESP32 – actually looking at numbers coming out of the Pico it looks like that must have microsecond resolution too.
Nice job Chris, and I’m particularly interested in the ESP32, which I’d previously rejected, perhaps unwisely!
What follows isn’t criticism, more a pointer to what can be done to achieve yet higher accuracy and precision, and what might limit them!
Microcontrollers can be characterised into two main groups. Those where the electronics and instructions are clocked synchronously at the same rate, and those that go faster by clocking instructions and the electronics asynchronously.
Moving on:
the Pressure, Temp and Humidity Sensor, and ideally the ESP32 as well, should all be inside the pendulum case. (Partly to protect against draughts, partly to measure what the pendulum is experiencing rather than the room!)
John’s already mentioned the need to protect the IR proximity sensor from sunlight. Very much so! I found light entering the back of the opto-diode alters its sensitivity, causing noticeable variations to when the pendulum was detected. (Several microsconds). I found it mounting the IR emitter so that the pendulum breaks a beam rather than using the ‘as sold’ module to detect a reflection was more time stable. Also improved by fitting slits to narrow the beam. Fix one problem, cause another! A beam makes the IR signal too strong, causing trouble due to reflecting off the structure of the clock. I blackened shiny surfaces and put in some black cardboard shielding.
The Arduino IR Proximity detector can be improved too. It’s a simple beast, using an OpAmp rather than a Comparator. (Op Amps can be wired as comparators but their internals are optimised for linear applications. Comparators are optimised for digital work, and flip between ON/OFF rather faster. The performance of the module can be improved by adding a resistor shown in RED below. A touch of positive feedback helps protect against noise and trigger slow rising signals more consistently. (Can’t find my notes: to keep the modification simple the resistor was determined experimentally from a dash of theory, and I can’t see the real one without taking the clock apart. About 100k I guess.) To reduce beam power, the 100ohm resistor ringed in red was increased to 330.
Even better, if money is no object buy a purpose made beam break detector. They come with a built in comparator, beam form with a lens, and protected optics. They don’t have to be wide enough to straddle the pendulum; detect a narrow flag mounted on the rod, above or below the bob.
The way the microcontroller measures time events may make a difference. Tom van Baak’s PiCPET and my ArdPET (inspired by Tom) both work in the same way. A counter/timer peripheral built into the chip does the timing. It counts independently of the CPU and it isn’t affected by other goings on. Nor does it depend on micros(), which ticks at 4µS and jitters.
I don’t think the ESP32 Counter/Timer hardware supports the PIC/Atmel method. (Might be wrong!!!) I think similar could be achieved by:
Though less accurate than a hardware counter, timing based on micros() at 80MHz might also be acceptable; depends on the application.
Like Chris I started by building a Arduino pendulum analyser corrected by GPS, the idea being a portable black box that would quickly detect rate and other mechanical clock errors – like a Microset but faster and user programmable. The problem I smacked into was getting a reliable GPS signal. Accurate timing requires 12+ satellites in view, which is only possible next to windows in my house. The unit worked perfectly in my garden but not inside, where a faulty grandfather clock is likely to be. Getting a GPS signal indoors was too awkward – not portable!
My clock project is stalled. Major changes needed fit the vacuum enclosure and plumbing, plus battery backup and several minor improvements. Strictly speaking I’m not supposed to operate machinery, but on a good day I’m very tempted!
Final hint. Worth logging the data and analysing it statistically over months or years. Have fun with Allan Deviation. Expect to see vibration due to passing traffic and domestic activity, the house moving due to thermal and maybe tidal effects, and earthquakes. Curiously, I didn’t detect the Turkish quake picked up by John, but the Libyan one was obvious. Not sure why, possibly due to the direction the pendulum swings relative to the epicentre.
Well done you, but beware, measuring time is addictive!
Dave
Having finally caught up with summertime and corrected the church clock this morning I am tempted to look into monitoring it. It would be interesting to see how much bellringing and other activities affected it. I’m more attuned to errors expressed as minutes per week.
Coincidentally we had a club member talk about his lantern clock last meeting and as he mentioned tower clocks in passing I popped into a local church yesterday to photograph their ex-clock now mothballed and on public view.
Pendulum was 4m.
Having finally caught up with summertime and corrected the church clock this morning I am tempted to look into monitoring it. It would be interesting to see how much bellringing and other activities affected it. […]
Despite its somewhat questionable first-impression … you may find this App useful:
https://apps.apple.com/gb/app/cuckoo-clock-calibration/id1171487289
MichaelG.
Having finally caught up with summertime and corrected the church clock this morning I am tempted to look into monitoring it. It would be interesting to see how much bellringing and other activities affected it. […]Despite its somewhat questionable first-impression … you may find this App useful:
https://apps.apple.com/gb/app/cuckoo-clock-calibration/id1171487289
MichaelG.
I have just paid the 99p for this only to find that the minimum BPM is 61…. I need 60 and it says I need value bigger than 60 and won’t let me enter it! 😂
Nice job Chris, and I’m particularly interested in the ESP32, which I’d previously rejected, perhaps unwisely!
What follows isn’t criticism, more a pointer to what can be done to achieve yet higher accuracy and precision, and what might limit them!
Microcontrollers can be characterised into two main groups. Those where the electronics and instructions are clocked synchronously at the same rate, and those that go faster by clocking instructions and the electronics asynchronously.
- Synchronous computers like the PIC used by Tom van Baak and the Arduino Nano/Uno/2560/Leonardo used by me are time predictable, but slow, say 16MHz. Accuracy is limited by the quality of the oscillator, which can be improved by compensating it with GPS or an Atomic Clock. The programmer doesn’t have to worry much about what else the machine might be doing!
- Asynchronous computers like the Raspberry Pico, Nucleo, xtensa etc are likely to be fast (ESP32 is 80MHz), but multi-threaded/multi-core, so not time predictable. The programmer has plenty to worry about. For example, the ESP32 runs a website over a WiFi transceiver, so timings depend on what the website and WiFi network happen to be doing at the time. Shows up as jitter. I suggest calibrating the ESP32. Rather than timing the pendulum, time the GPS module’s 1 second output. In a perfect system, the ESP32 will measure about 1.0000000s, but nothing is perfect! The standard deviation, will show how much jitter is in the ESP and therefore its ± accuracy. I don’t know how good or bad the result will be! On the plus side the ESP is provided with a ±10ppm 40MHz TXCO, which is massively better than the ceramic resonator in an Arduino Nano! On the negative side, I don’t know how long an ESP32 interrupt takes. The chip has to save the state of the web server by copying everything on the stack into RAM first: pretty quick if the web-server is idling, much longer if it was doing something complicated. Another potential complication is that fast microcontrollers prioritise interrupts, so there’s a risk receiving a WiFi packet might interrupt your interrupt, causing jitter. One way of detecting if this is a problem is to code the ESP32 to toggle an IO pin flat out, and to watch the waveform on an oscilloscope. Any gaps are due to the processor interrupting the toggling to do something else. What exactly goes on under the bonnet matters more as the desire for accuracy increases!
Moving on:
the Pressure, Temp and Humidity Sensor, and ideally the ESP32 as well, should all be inside the pendulum case. (Partly to protect against draughts, partly to measure what the pendulum is experiencing rather than the room!)
John’s already mentioned the need to protect the IR proximity sensor from sunlight. Very much so! I found light entering the back of the opto-diode alters its sensitivity, causing noticeable variations to when the pendulum was detected. (Several microsconds). I found it mounting the IR emitter so that the pendulum breaks a beam rather than using the ‘as sold’ module to detect a reflection was more time stable. Also improved by fitting slits to narrow the beam. Fix one problem, cause another! A beam makes the IR signal too strong, causing trouble due to reflecting off the structure of the clock. I blackened shiny surfaces and put in some black cardboard shielding.
The Arduino IR Proximity detector can be improved too. It’s a simple beast, using an OpAmp rather than a Comparator. (Op Amps can be wired as comparators but their internals are optimised for linear applications. Comparators are optimised for digital work, and flip between ON/OFF rather faster. The performance of the module can be improved by adding a resistor shown in RED below. A touch of positive feedback helps protect against noise and trigger slow rising signals more consistently. (Can’t find my notes: to keep the modification simple the resistor was determined experimentally from a dash of theory, and I can’t see the real one without taking the clock apart. About 100k I guess.) To reduce beam power, the 100ohm resistor ringed in red was increased to 330.
Even better, if money is no object buy a purpose made beam break detector. They come with a built in comparator, beam form with a lens, and protected optics. They don’t have to be wide enough to straddle the pendulum; detect a narrow flag mounted on the rod, above or below the bob.
The way the microcontroller measures time events may make a difference. Tom van Baak’s PiCPET and my ArdPET (inspired by Tom) both work in the same way. A counter/timer peripheral built into the chip does the timing. It counts independently of the CPU and it isn’t affected by other goings on. Nor does it depend on micros(), which ticks at 4µS and jitters.
- The counter is clocked continuously by the system clock. PicPET ticks at 10MHz (100nS), Arduino at 16MHz (62.5nS). An Arduino can be modified with soldering iron to tick at 50nS with an external 20MHz OCXO.
- When an special input pin changes (RISING), the counter copies the count to a save register, issues an interrupt, and carries on. It doesn’t stop or miss any counts.
- The Interrupt Service Routine reads the saved count and determines elapsed time by comparing it with the previously saved value. Provided the ISR is fast enough to do the subtraction before the next event, the measurement will always be tick correct within the limits of the computer’s clock oscillator.
I don’t think the ESP32 Counter/Timer hardware supports the PIC/Atmel method. (Might be wrong!!!) I think similar could be achieved by:
- Setting an IO pin to interrupt on RISING.
- Have the ISR read the current value of the counter, and calculate elapsed time from the previous value, then zero the counter. The time taken to process the pin interrupt and to zero the counter will cause jitter. Though inferior in theory it may be acceptable! The ESP32 ticks at 80MHz, 5x faster than a PicPET, and might deliver comparable accuracy. I’d have to test it to see!
Though less accurate than a hardware counter, timing based on micros() at 80MHz might also be acceptable; depends on the application.
Like Chris I started by building a Arduino pendulum analyser corrected by GPS, the idea being a portable black box that would quickly detect rate and other mechanical clock errors – like a Microset but faster and user programmable. The problem I smacked into was getting a reliable GPS signal. Accurate timing requires 12+ satellites in view, which is only possible next to windows in my house. The unit worked perfectly in my garden but not inside, where a faulty grandfather clock is likely to be. Getting a GPS signal indoors was too awkward – not portable!
My clock project is stalled. Major changes needed fit the vacuum enclosure and plumbing, plus battery backup and several minor improvements. Strictly speaking I’m not supposed to operate machinery, but on a good day I’m very tempted!
Final hint. Worth logging the data and analysing it statistically over months or years. Have fun with Allan Deviation. Expect to see vibration due to passing traffic and domestic activity, the house moving due to thermal and maybe tidal effects, and earthquakes. Curiously, I didn’t detect the Turkish quake picked up by John, but the Libyan one was obvious. Not sure why, possibly due to the direction the pendulum swings relative to the epicentre.
Well done you, but beware, measuring time is addictive!
Dave
Hi SillyOldDuffer,
Thank you for taking the time to write such a detailed post, it’s genuinely appreciated. It’s clear you have a vastly superior understanding of the underlying timing electronics than I do, and I’ve learned a lot just from reading your message and our original correspondence. I did use the Uno and your code to get me going!
You’re absolutely right about the ESP32 not being as time-predictable as something like a PIC or Uno. The dual-core, RTOS-driven nature of it — plus Wi-Fi, web server, etc. — introduces plenty of potential for jitter and latency. But I’ve done my best to mitigate this:
• Pendulum ticks are detected via a dedicated interrupt, and I’ve taken care to keep that ISR tight and safe (with portMUX guarding, no delay()s, etc.).
• Timing is measured using micros(), so yes, there’s inherent jitter, but I now have full PPS correction from the GPS module. The system continuously calculates ESP32 drift vs GPS time, so I can at least monitor how far off the internal clock is. Your idea of logging PPS-to-PPS intervals to get the standard deviation of jitter is excellent, I’ll definitely add that.
As for your point about the IR sensor, completely agree! I’ve already had some light interference issues when it is bright outside, and I know the reflection method is inherently less stable than a proper beam-break setup. I’ve got plans to test a slitted emitter/detector arrangement next, or potentially just bite the bullet and get a proper commercial beam-break sensor with a comparator as you suggested. The current “as sold” IR module is… let’s just say convenient, but not ideal.
On the environmental side — you caught me out there! I’m fully aware the BME280 should be in the case, but for now it’s attached to the PCB simply for ease. It will definitely be enclosed with the pendulum for proper readings soon — promise!
The point about using hardware counters rather than relying on micros() is a good one too. I’ve read that the ESP32 does have some capture capabilities in the PCNT or MCPWM units, but they’re poorly documented and quite involved. Something I might play with eventually, especially if I get the jitter under control and want to push things further.
Anyway, thanks again for your incredibly helpful post. You’ve definitely given me some things to investigate further. And you’re absolutely right, once you start measuring time like this, it gets very addictive!
All the best,
Chris
Just to put the App through its paces:
I would be tempted to enter 060001
… which gives a period of 999.983ms and BPH: 3600.06
Sorry, can’t play tonight … I have an early hospital appointment tomorrow.
MichaelG.
Nice job Chris, and I’m particularly interested in the ESP32, which I’d previously rejected, perhaps unwisely!
What follows isn’t criticism, more a pointer to what can be done to achieve yet higher accuracy and precision, and what might limit them!
…Well done you, but beware, measuring time is addictive!
Dave
Hi SillyOldDuffer,
Thank you for taking the time to write such a detailed post, it’s genuinely appreciated. It’s clear you have a vastly superior understanding of the underlying timing electronics than I do, and I’ve learned a lot just from reading your message and our original correspondence….
All the best,
Chris
You are too kind Chris. This is as much team work as me. Although I have ancient form as a Software Engineer, I never did embedded work, so microcontrollers were a retirement project. Much of what I do is built on my extensive but haphazard technical library, supplemented heavily by advice received on this forum. A multitude of posts helped develop my metalworking skills, and several clockmakers provided information and advice about pendula, escapements and other clock marvels! On the software, maths, and theory side, Joe Noci, John Haines, Duncan Webster, Michael Gilligan, and Martin Kyte have all helped. (Plus many others, apologies if I’ve forgotten a major player – I’m a bit fuzzy headed today.) Many leads provided, for example John put me on to Tom van Baak’s work. And now you’ve added to the mix with an ESP32, which I ought to investigate further.
Back to your effort, and the statistics. As you know there are lies, damn lies and statistics! Not a problem as long as you’re honest, and not misled by misunderstanding them. Averages and rolling averages can help identify trends like an underlying change of rate, due to something mechanical like the pendulum stretching or a sticky escapement, but they also cover up noise that might be relevant too. For example, precision mechanical clock makers twigged after several years that new made Invar is intermittently unstable, causing pendulum rods to alter length spontaneously, and muck up the timing. Though the effect is tiny nanoseconds matter in a precision clock. Cure was to find an Invar alloy that was more stable, and to age it before making pendulum rods from it. At that point, research into mechanical clocks stopped as electronics took over, leaving the possibility that a hobbyist today could make the best mechanical clock ever.
The Invar problem was detected by analysing statistics over a long period, comparing the clock with astronomical time. We have GPS time. I’d use python/matplotlib/numpy, but R, matlab, SciLab, Octave, Mathematica, and others are available. They can also be used to detect correlations between temperature, pressure, humidity and period. Most spreadsheets do histograms.
Standard Deviation is a good start, but I suggest you implement a Histogram. The easiest way is to analyse the log on a PC with software that does histograms. The idea is to count timings into, say 1uS, buckets and then look at the shape of the resulting curve. No reason apart from effort why you shouldn’t implement your own histogram on the ESP32. This reveals the Q of the pendulum, ideally a sharp peak, and distortions. These can be due to mechanical issues and noise and mangling due to sensor and computer problems. When measuring in the microsecond region, you should see noise, that is a broad histogram curve rather than a sharp one. Then hunt down the sources and reduce them – if possible! The goal is to sharpen the histogram.
This could ruin your life…
🙂
Dave
I would be tempted to enter 060001
[…]
You haven’t wasted your £0.99 Chris
I’ve just laid my ‘phone on an ordinary Quartz wall-clock movement and the App is displaying nicely.
MichaelG.
Home › Forums › Clocks and Scientific Instruments › Topics
Started by: brucemc777
in: Beginners questions
brucemc777
Started by: vic newey
in: Workshop Tools and Tooling
Diogenes
Started by: nevillet
in: Workshop Tools and Tooling
JasonB
Started by: Chris Raynerd 2
in: Clocks and Scientific Instruments
Michael Gilligan
Started by: JasonB
in: Stationary engines
JasonB
Started by: PutneyChap
in: Electronics in the Workshop
Stuart Smith 5
Started by: t1krt
in: Introduce Yourself – New members start here!
t1krt
Started by: parovoz
in: Locomotives
mike robinson 2
Started by: Andrew Tinsley
in: General Questions
Neil Wyatt
Started by: ell81
in: Beginners questions
Bazyle
Started by: roger61
in: Workshop Techniques
Brian Baker 2
Started by: Sonic Escape
in: General Questions
Clive Foster
Started by: Ian Parkin
in: Workshop Tools and Tooling
Tony Pratt 1
Started by: michaeljf93
in: Introduce Yourself – New members start here!
Taf_Pembs
Started by: Pete.
in: General Questions
Clive Foster
Started by: Keith Matheson
in: Workshop Tools and Tooling
Pete.
Started by: Vic
in: The Tea Room
Vic
Started by: old mart
in: Materials
Greensands
Started by: Tony Martyr
in: General Questions
bernard towers
Started by: JasonB
in: Stationary engines
Jim Nic
Started by: pjbiker
in: Beginners questions
Juddy
Started by: rjenkinsgb
in: Manual machine tools
rjenkinsgb
Started by: ell81
in: Beginners questions
old fool
Started by: Stuart Cox 3
in: General Questions
john halfpenny
Started by: old mart
in: Hints And Tips for model engineers
Robert Atkinson 2