Multifunction Instrumentation System

A Raspberry Pi-based digital multimeter and function generator featuring custom analog front-ends, a software-driven SAR ADC, and a 4-layer mixed-signal PCB.

ECSE 2920 Jan – Apr 2026
The breadboarded test bench with its analog front-ends, Raspberry Pi GPIO breakout, and 20×4 LCD

Highlights

  • Built a Raspberry Pi digital multimeter and function generator in Python with a ±12 V split-rail supply and active virtual ground
  • Designed a SAR ADC from a digital potentiometer and comparator for a ±5 V voltmeter, 500-10 kΩ ohmmeter, and ±5 V reference
  • Implemented function generators (0-10 Vpk, 0-10 kHz) and a 0-10 kHz frequency counter with op-amp conditioning
  • Improved DC resolution ~6x and voltmeter precision ~2x by adding digipot calibration LUTs
  • Designed a 4-layer mixed-signal Pi HAT PCB in KiCad with dedicated power and ground planes

Overview

ECSE 2920 course project with a five-person team. I designed and built the measurement and generation path end to end — Pi software, analog front-ends, digipot SAR ADC, and calibration — while teammates handled the enclosure, wiring documentation, and demo slides. The M.I.S. folds a bench of lab instruments into one platform. The Raspberry Pi 4 is the only processor: Python firmware runs the measurement algorithms, waveform output, and a menu-driven interface on a 20×4 I²C LCD with a rotary encoder. Custom analog circuits handle signal conditioning, comparison, and generation.

Results

Instrument Range Accuracy
Ohmmeter 500 Ω – 10 kΩ ±10%
Voltmeter −5 V to +5 V ±0.2 V
DC reference −5 V to +5 V, 32 levels ±0.2 V
Square-wave generator 100 Hz – 10 kHz, up to ±10 V ±1 V amplitude
Sine-wave generator 1 – 10 kHz, 0 – 10 V peak ±0.2 V amplitude
Frequency meter 1 – 10 kHz ±2%

Those 6× / 2× gains come from characterizing the digipot’s real resistance steps and replacing naïve wiper-index math with calibrated lookup tables (plus interpolation on the voltmeter). Split-rail bring-up measured −12.04 V / +12.05 V under load.

Measuring with a comparator and a digipot

The Pi has no ADC, so the voltmeter and ohmmeter use a discrete successive-approximation converter. An MCP4131 digital potentiometer sets a reference over SPI, an LM339 comparator reports whether the input is above or below it, and the firmware binary-searches the wiper in 8 steps, which takes about 40 ms per reading including settling time.

  • Ohmmeter: the unknown resistor forms a divider against the digipot, and the converged wiper step gives R = R_known × step / (128 − step). A 1 kΩ series resistor keeps the wiper current under the MCP4131’s 2.5 mA limit even at 500 Ω.
  • Voltmeter: summing and inverting amplifiers map −5…+5 V into the 0–3.3 V comparator range, and a calibrated lookup table with linear interpolation brings readings to ±0.2 V.

Generating signals

Click bits on the interactive R-2R ladder below — the ladder stays at 0–3.3 V; the op-amps map that to −5…+5 V.

  • DC reference: five GPIO pins drive an R-2R ladder (0–3.3 V), a non-inverting stage scales to 0–10 V, and a difference amp subtracts 5 V for a bipolar −5…+5 V output. An earlier binary-weighted design suffered from cross-loading between bits; the R-2R ladder presents a constant impedance and stays monotonic across all 32 codes.
  • Square wave: the Pi’s hardware PWM is RC-filtered, then an MCP4231 dual digipot sets amplitude and offset ahead of a gain-of-10 difference amplifier, giving a 0 V-centered output up to ±10 V.
  • Sine wave: the Pi’s audio output is buffered, offset, and scaled, with an MCP4131 providing digital amplitude control up to 10 V peak.

Timing on a non-real-time OS

Linux scheduling jitter rules out bit-banged timing in Python. The frequency meter squares up the input with a comparator, and the pigpio daemon timestamps each rising edge with microsecond resolution in the background. The UI loop computes frequency from a rolling 100-period buffer and rejects outliers beyond 2σ, so measurements never block the interface. Leaving a menu automatically disables waveform and DC outputs as a safety interlock.

Power and PCB

A ±12 V split rail comes from a single 24 V input: a TL081 buffer drives an IRFZ34N / IRF5305 push-pull stage that holds a virtual ground at the midpoint, tied to the Pi’s ground at a single star point. With both rails loaded they measured −12.04 V and +12.05 V.

The whole system is captured as a hierarchical KiCad schematic and a 4-layer Pi HAT layout with dedicated power and ground planes, with DRC-checked Gerbers ready for fabrication.

Demo videos

Interactive DC reference

Five GPIO bits drive an R-2R ladder (0–3.3 V). A non-inverting stage scales that to 0–10 V, then a difference amp subtracts 5 V for a bipolar −5…+5 V output.

R-2R → gain / offset

Click a bit on the ladder, scrub the code, or sweep all 32 levels. The ladder stays in the Pi’s 0–3.3 V domain; the op-amps do the bipolar mapping.

Code
—
Binary
—
V_R2R
—
Vout
—
Ladder · 0 – 3.3 V
0 1.65 3.3
Output · −5 – +5 V
−5 0 +5