Determination of 'g' via Optical Photogate Timing
Measure the time period $T$ of a simple pendulum with microsecond precision using digital hardware interrupts.
Principle & Theory
For small amplitude oscillations ($\theta < 10^\circ$), the time period $T$ of a simple pendulum of length $L$ is:
The photogate detector is connected to Arduino Pin 2 (Hardware Interrupt INT0). A full period corresponds to 2 successive interruptions of the optical beam.
// ============================================================
// Photogate Simple Pendulum Period Timer (Microsecond Accuracy)
// Connect IR Photogate sensor to Digital Pin 2 (INT0)
// ============================================================
const byte photogatePin = 2;
volatile unsigned long t1 = 0;
volatile unsigned long t2 = 0;
volatile byte count = 0;
volatile bool newPeriodReady = false;
void IRAM_ATTR onBeamBreak() {
unsigned long now = micros();
count++;
if (count == 1) {
t1 = now;
} else if (count == 3) {
t2 = now;
newPeriodReady = true;
count = 1;
t1 = now;
}
}
void setup() {
Serial.begin(115200);
pinMode(photogatePin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(photogatePin), onBeamBreak, FALLING);
Serial.println("P4P_PENDULUM_READY");
}
void loop() {
if (newPeriodReady) {
unsigned long durationMicros = t2 - t1;
float periodSec = durationMicros / 1000000.0;
Serial.print("PERIOD_S:");
Serial.println(periodSec, 5);
newPeriodReady = false;
}
}
import serial
import numpy as np
PORT = 'COM3' # Adjust to your Arduino serial port (e.g., /dev/ttyUSB0 on Linux)
BAUD = 115200
L = 0.85 # Measured pendulum length in meters
ser = serial.Serial(PORT, BAUD, timeout=2)
periods = []
print(f"Logging 20 periods for pendulum L = {L:.3f} m...")
while len(periods) < 20:
line = ser.readline().decode('utf-8', errors='ignore').strip()
if line.startswith("PERIOD_S:"):
T = float(line.split(":")[1])
periods.append(T)
g_inst = 4 * (np.pi**2) * L / (T**2)
print(f"Sample {len(periods):02d}: T = {T:.4f} s --> g = {g_inst:.3f} m/s^2")
ser.close()
T_mean = np.mean(periods)
T_std = np.std(periods)
g_final = 4 * (np.pi**2) * L / (T_mean**2)
print("\n--- RESULTS ---")
print(f"Mean Time Period: {T_mean:.4f} +/- {T_std:.4f} s")
print(f"Experimental 'g': {g_final:.3f} m/s^2")