PhysicsLab turns the phone in your pocket into a lab bench. Five experiments — all of them lifted straight out of the first-year undergraduate lab — run entirely off the sensors already sitting inside the handset. No probes, no DAQ box, no bench kit. You choose how many data points to record, the app builds the table as you go, and it plots the graph you'd actually reach for during analysis.

The pitch is simple: you shouldn't need a lab to check whether the universe is behaving.

The five experiments

Each one is a standard lab exercise reduced to a phone and a bit of geometry. The job is the same every time — record clean data, then watch a known law fall out of it.

  1. Vibration & resonance Rest the phone firmly on a vibrating body. The accelerometer reads the oscillation, and a frequency sweep finds the resonant peak.
  2. Inverse-square law Point the front of the phone at a bulb in a dark room and step back through measured distances. The light sensor should fall off as 1/r².
  3. Elevator kinematics Hold the phone steady and ride a lift. Integrate the accelerometer trace to recover velocity, acceleration, and how far you've travelled.
  4. Speed of sound Stand a measured distance from a big flat wall and give one sharp clap. Time the gap to the echo and you've got the speed of sound in air.
  5. Coupled oscillators Hang the phone and a similar mass as two pendulums from one taut string. Set the other bob swinging while the phone is still, and watch the energy slosh back and forth between them.

Why a phone is a half-decent lab

The accelerometer, light sensor and microphone in a modern handset are good enough to recover real numbers — not lab-grade, but real. That's the whole point. The reading on the screen isn't borrowed from a textbook; it came out of your data, on hardware you already own, which is a far more convincing way to believe a law than being told it.

Where the physics bites

The honest answer to "how hard was it?" is that the code was rarely the problem — the physics of cheap sensors was. Three places fought back, and the interesting work was in how I handled (or deliberately didn't hide) each one.

Elevator drift. The lift experiment integrates acceleration once to get velocity and twice to get height. The trouble is that any tiny constant bias in the accelerometer integrates into a velocity that quietly drifts, then integrates again into a height that runs away entirely — by the time the lift stops, the app still thinks you're moving. The fix is a zero-velocity correction: the ride begins and ends at rest, so I pin velocity to zero at both endpoints and drag the accumulated drift back out of the height estimate. It's a cheap trick borrowed from inertial navigation, and it's the only reason the elevator numbers are usable at all.

The inverse-square intercept will never be perfect — and I left it that way. The 1/r² plot comes out clean, but the intercept never lands exactly where theory says it should. That's not a bug to chase. A real bulb isn't a point source, the light sensor has an angular response (it doesn't weight every incoming angle equally), and there's a non-zero ambient offset baked into every reading. So the line is honest about the trend while the constant term quietly carries all the sins of real hardware. Forcing it onto the theoretical intercept would mean fudging the data, which defeats the point of measuring anything.

The FFT is hand-rolled. The resonance and speed-of-sound experiments both need frequency and timing analysis, and rather than pull in a DSP library I wrote the transform by hand against the platform sensor APIs.

// radix-2 Cooley–Tukey, in-place
for (stage in 1..log2n) {
    val span = 1 shl stage
    val half = span shr 1
    // butterflies across each block...
}

Which sounds hardcore but is really just a textbook radix-2 — the win wasn't cleverness, it was that doing it myself meant I understood exactly what the windowing and the bin resolution were doing to my peaks. When the peak is the answer, that's not a detail you want hidden behind someone else's library.

The stack

Kotlin, native Android, built in Android Studio, talking to the platform sensor APIs directly with the hand-rolled FFT and no DSP dependency. A few constraints are worth knowing, because they shaped everything:

What I'd do differently

Add raw CSV export. Right now the app keeps the underlying arrays to itself and only hands you the table and the on-device plot. I want to pull the raw samples straight into NumPy and do the analysis properly — fits, residuals, real uncertainties — instead of trusting a phone-screen line of best fit. That's the first thing going into the next version.


The whole thing is a bet that the best lab equipment most students own is already in their pocket. Source is on GitHub if you want to poke around.