Lab Setup & Safety
Keep the bench consistent and safe before any script
touches an instrument:
-
Keep AWG amplitude <= 1 Vpp and offset at 0 V
unless a mentor says otherwise.
-
Start with DC coupling on the scope. Enable the 20
MHz bandwidth limit when running noise sweeps.
-
Verify the BNC loopback from AWG CH1 to Scope CH1
before you call
read_channels.
-
PSU and DMM stay idle unless you are on Track B3.
Use them only for validation and cross-checks.
Track A — Warm-up (Beginner-friendly)
A1 — Hello, Oscilloscope (Sine @ 1 kHz)
Steps
-
Connect to the scope with PyTestLab
(simulation fallback is fine if needed).
-
Configure CH1 scale/offset, set an edge
trigger, and acquire one frame.
-
Compute frequency and Vpp in Python, then
plot the time-domain trace.
Acceptance: |f_meas − 1 kHz| <=
2%; |Vpp_meas − 1.0 V| <= 5%.
Starter snippet
from pytestlab import AutoInstrument
from pytestlab.plotting import PlotSpec
import numpy as np
scope = AutoInstrument.from_config("keysight/DSOX1204G", simulate=False)
scope.connect_backend()
scope.channel(1).setup(scale=0.2, coupling="DC").enable()
scope.trigger.setup_edge(source="CH1", level=0.1)
trace = scope.read_channels(1) # MeasurementResult with DataFrame
fig = trace.plot(PlotSpec(title="CH1")) # save/show as needed
scope.close()
A2 — Duty Cycle Explorer (Square @ 1 kHz)
Steps
-
Capture the waveform using the same
PyTestLab flow.
-
Compute duty cycle (%) and 10–90% rise/fall
times.
-
Record results and keep plots ready for
check-in.
Acceptance: Duty within ±2% of the
AWG setpoint. Record rise/fall times in your notes.
Track B — Core Measurement Automation (Intermediate)
B1 — Frequency Sweep (Flatness)
Plan
- Sweep 100 Hz to 100 kHz (log steps).
-
For each frequency, acquire the trace and
compute Vpp.
-
Plot |Vpp(f)| and report droop at 100 kHz
relative to 1 kHz in dB.
Session skeleton
from pytestlab.measurements import MeasurementSession
import numpy as np
with MeasurementSession("Flatness") as s:
s.parameter("freq", np.logspace(2, 5, 25), unit="Hz")
awg = s.instrument("awg", "keysight/33500B", simulate=False)
scop = s.instrument("scope","keysight/DSOX1204G", simulate=False)
@s.acquire
def step(freq, awg, scop):
awg.channel(1).setup_sine(frequency=float(freq), amplitude=0.8)
scop.trigger.setup_edge(source="CH1", level=0.2)
tr = scop.read_channels(1)
return {
"freq": float(freq),
"vpp": tr.dataframe()["Voltage (V)"].max()
- tr.dataframe()["Voltage (V)"].min(),
}
exp = s.run()
# TODO: convert to dB relative to 1 kHz and plot
B2 — Aliasing Demo (Sample Rate & Timebase)
Steps
- Keep the scope timebase fixed.
-
Increase the AWG frequency until aliasing
appears.
-
Log the true input frequency versus the
apparent alias frequency and capture a plot.
Acceptance: One slide or note
explaining the aliasing region, plus a plot
illustrating the effect.
B3 — PSU + DMM Cross-Check (DC Accuracy)
Steps
- Sweep 1.0 V to 5.0 V in 1 V steps.
-
Hold each point for ~2 s before reading the
DMM.
-
Record setpoint, measured value, and percent
error.
Acceptance: Table with setpoint,
measured voltage, and error (%).
Track C — Reproducibility & Tooling (Advanced,
optional)
C1 — Record & Replay
Steps
-
Use
pytestlab replay record during
a full sweep.
-
Run
pytestlab replay run to
validate the log.
-
Attach the replay YAML and confirm zero
sequence mismatches.
C2 — Noise & Bandwidth Limit
Steps
-
Measure RMS noise with bandwidth limit off.
- Enable the 20 MHz limit and repeat.
-
Report RMS_off versus RMS_20MHz and the
percentage reduction.
Logistics & Grouping
-
Pair newer students on Track A → B1 for confidence
before tackling advanced work.
-
Experienced attendees choose B1 + C1 or B2 + C2.
-
Total time budget is two hours: A1 (15 min), A2 (15
min), B1 (40 min), B3 (20 min) with 30 min slack.
-
Mentors circulate to approve PSU usage and to sanity
check automation scripts.
Bench & Config (template)
Update the model names and addresses to match your bench
before connecting:
bench.yaml
bench_name: "Workshop Bench"
simulate: false
instruments:
scope:
profile: "keysight/DSOX1204G" # change to your model
address: "auto" # or VISA/LAN address
awg:
profile: "keysight/33500B"
address: "auto"
psu:
profile: "keysight/EDU36311A"
address: "auto"
dmm:
profile: "keysight/34470A"
address: "auto"
Need discovery? Run
pytestlab instruments list from the CLI and
paste the addresses into your config.
Submission Checklist
-
One plot from A1 or B1 (PNG or PDF) with labeled
axes.
-
One table (CSV) from B3 or B1 with frequency, Vpp,
and droop (dB).
-
A short note (<= 150 words): what changed in your
code and one thing you learned.