I think in the end a contact microphone will be necessary. A slot sensor is the dream but tough to do without having something bigger and more visible. I also am not opposed to using multiple swings in the end and know if i look just at one it will swing a lot, but am going for measuring each individually for now and can scale back if needed
Yep, I know it won't be regular which is part of why I want to measaure each one, mostly this is just from curiosity for now and might be scrapped later. But yeah, in the end measuring more will clearly give more accurate readings so i probably will
The time it takes to get that GPS multi-byte data⦠from one swing to the next will be the same but be aware that āget the timeā takes time.
It would be easier to use MCU time and soft-calibrate that by checking a long period (10 min to hour) interrupt against elapsed micros (Arduino micro is 4 usec granular), the two numbers can be used to multiply-then-divide scaling of MCU-to-real time⦠donāt use floats and factors, itās slower and loses more precision where with integers you can chose how close you get.
Just curious, how long / big is the pendulum?
Is it a Foucault one?
I did a project to calibrate the DS3231 RTC's Aging register to a GPS PPS signal. Using an Atmega328P-based Arduino, you can set Timer1 running at the full 16 MHz, and then use the capture function to read the timer count when an event triggers the capture. So you could have the PPS signal start the timer at a count of zero, and then have the clock's "tick" trigger the capture. The difference between the two would remain constant if the clock is keeping perfect time.
I ended up having to average 16 readings to get a reasonably stable value. I don't know exactly where the jitter was. It could be the Nano's resonator, the RTC's crystal, or even the PPS signal. Anyway, I don't think a single reading is going to give you a very reliable value at the microsecond level, but it might be ok at 100us.
Well, here's the project in case some of it may be useful:
One easy solution would be to use one of the MKR series Arduino boards. These use the ARM SAMD processor. The micros() function has 1us resolution straight out of the box. The 48Mhz frequency locked loop clock that generates the ticks for micros() has an onboard crystal as its reference clock. I have found it is accurate to about 30s per day, and itās consistent for a specific board if the temperature stays fairly constant.
30 sec per day might sound like a lot but itās only fractions of a percent and you can easily run it for say 24 hours and work out a correction factor. Because the error is consistent you can just correct your calls to micros() by the correction factor and youāll have great accuracy and resolution.
The micros() function can sometimes give inconsistent results. There is an improved and more robust version for the ARM processor boards in this thread:
Systick - Timing on the Arduino Zero????? - Classic / Zero - Arduino Forum
using an ESP32 this measures pulse width at different frequencies
// ESP32 - measure pulse width and rising edge-to-edge time using timer1 pins 16 and 17
// updated for Arduino ESP32 core 3.0 see
// https://docs.espressif.com/projects/arduino-esp32/en/latest/api/timer.html
// note using hw_timer_t or micros() give similar values
hw_timer_t *Timer1_Cfg = NULL; // timer object
// pulse timing data
volatile uint64_t riseTime, period, width;
// rising edge interrupt calculate period uSec
void IRAM_ATTR rising() {
uint64_t rise = timerReadMicros(Timer1_Cfg);
period = rise - riseTime;
riseTime = rise;
}
// falling edge interrupt calculate pulse width uSec
void IRAM_ATTR falling() {
width = timerReadMicros(Timer1_Cfg) - riseTime;
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.printf("\n\nESP32 measure pins 16 and 17 pulse information \n");
//Timer1_Cfg = timerBegin(0, 80, true); // API 2.x setup timer for 1uSec
if ((Timer1_Cfg = timerBegin(10000000)) == NULL) // API 3.0 setup timer for 1uSec
Serial.println("timerBegin Failed!!");
Serial.print("timerBegin() OK frequenmcy ");
Serial.println(timerGetFrequency(Timer1_Cfg));
// setup interrput routines - connect signal to pins 16 and 17
attachInterrupt(digitalPinToGPIONumber(16), rising, RISING); // detect rising edge on pin 16
attachInterrupt(digitalPinToGPIONumber(17), falling, FALLING); // detect falling edge on pin 17
Serial.println("displaying results");
}
void loop() {
static unsigned long int timer = millis();
// if 2 seconds have elapsed since last redaing print results
if (millis() - timer > 2000) {
timer += 2000;
Serial.printf("period %llduSec width = %llduSec frequency %.2fHz\n",
period, width, 1000000.0/period);
}
}
result at various frequencies different pulse widths
period 10uSec width = 6uSec frequency 100000.00Hz
period 10uSec width = 4uSec frequency 100000.00Hz
period 10uSec width = 6uSec frequency 100000.00Hz
period 100uSec width = 51uSec frequency 10000.00Hz
period 100uSec width = 52uSec frequency 10000.00Hz
period 100uSec width = 51uSec frequency 10000.00Hz
period 10000uSec width = 5000uSec frequency 100.00Hz
period 10000uSec width = 5000uSec frequency 100.00Hz
period 100000uSec width = 50000uSec frequency 10.00Hz
period 100001uSec width = 50001uSec frequency 10.00Hz
period 100000uSec width = 50000uSec frequency 10.00Hz
period 999993uSec width = 499995uSec frequency 1.00Hz
period 999994uSec width = 499997uSec frequency 1.00Hz
period 999994uSec width = 499994uSec frequency 1.00Hz
another test frequency 1Hz .01 duty cycle (100uSec width)
period 999992uSec width = 101uSec frequency 1.00Hz
period 999992uSec width = 99uSec frequency 1.00Hz
period 999993uSec width = 99uSec frequency 1.00Hz
period 999990uSec width = 100uSec frequency 1.00Hz
period 999992uSec width = 98uSec frequency 1.00Hz
period 999993uSec width = 100uSec frequency 1.00Hz
period 999993uSec width = 97uSec frequency 1.00Hz
period 999992uSec width = 99uSec frequency 1.00Hz
This graph is an example of how the accuracy of a crystal-controlled processor clock speed varies with temperature. If you wanted to measure the pendulum clock swings using the micros() function, say, you would need to correct for this temperature effect (unless the loss of accuracy didnāt matter to you).
You could simply run some tests and see how your particular board responds to temperature, then correct your pendulum measurements based on the temperature at the time.
Or you could run a (say) 15 minute calibration sequence using the PPS signal from a GPS module to see how fast or slow your board is running immediately before measuring the pendulum ticks. Thatās how this graph was made, using a rolling previous 15 minutes sample, updated every minute.
Oh, neat! Note that the error of 20s/day is about 0.02%, or 200ppm, which is pretty much in-line with the specs of many low-priced SMT 32768Hz crystals. (although the way I read the specs, the actual temperature dependence is supposed to be less. Perhaps other circuit elements come into play (those load caps, for instance.)
Yes, I think there must be other effects at play, because the piezo crystal should oscillate slower, not faster as temperature increases, and thatās not what the testing shows. (Iāve triple-checked that the testing sketch maths is correct).
Regardless, the OP would need to correct in some way for temperature effects, unless the loss of accuracy is small enough to ignore for whatever use heās going to put the measurements to.
