When I first joined the DVT department at TDK-Lambda, products were tested entirely by hand. Each measurement started the same way: key a voltage into the AC source's front panel, wait for the display to settle, then work through each electronic load, punching in the current for every output channel. Instrument interfaces were slow, buried behind nested menus and laggy keypads. If the test needed a scope capture, that meant more setup: configuring the trigger, adjusting the timebase, waiting for a stable trace, saving to USB.
Then you'd change one variable and do it all again. A different input voltage, a different load level, a different temperature. Every combination had to be tested, and each one meant the same sequence of keystrokes across the same instruments. For a test covering 4 temperatures, 5 input voltages, and 5 load levels, that's 100 repetitions for a single output. Add more outputs and each one multiplies the count. A single-output product took weeks of this.
And that was just the testing. Every measurement then had to go into a report: tables of data, scope screenshots pasted in, pass/fail verdicts against the specification. Every repetition was another chance to mis-key a voltage, misread a display, mislabel a screenshot, or drop a value into the wrong cell. Hundreds of data points per product, all recorded by hand. A custom Siemens unit with more than twelve outputs took over nine months to complete a full set of functional tests.
The explorer below shows how these conditions combine. Adjust the axes and add outputs to see how quickly it adds up.
See how test conditions scale combinatorially for a single functional test. A full DVT campaign runs over 20 tests, each with its own condition matrix.
For a single test. A full DVT campaign runs 20+ tests of varying complexity, each with its own condition matrix.
I'd started a Computing degree through the Open University before joining the DVT team, studying in my own time. I paused it to focus on the electronics qualifications that came with the technician role: a BTEC, then an HNC. My principal engineer knew about the programming background and brought me onto the ATE project he'd started: a basic VB.NET application with some instrument interfaces and a simple test loop. I gradually took over development, building out test procedures, then the configuration layer, then the framework itself, over the next six years.
By the end: wire up a power supply, configure the project, set it running. Come back to finished reports for every functional test.
TDK-Lambda's range spans single-output units, multi-output converters, and modular products. The same test procedures run across all of them because nothing in a test is coupled to a specific product. Product details, acceptance limits, wiring, test conditions — all configured independently in XSD-validated XML.
The spec defines acceptance limits for each test, but it also feeds conditions back into the test matrix. If the spec says efficiency must meet 89% at 115V, the system picks up 115V as a test point for the efficiency test. Change a limit, and both the pass/fail thresholds and the test conditions update to match.
The loading calculation was the hardest part of the system. A single-output unit is straightforward, but many products are multi-output converters sharing a power budget, and modular products add another layer: multiple modules under a shared converter, each with their own power limit. Take a four-output converter at -30°C: the total power budget has derated, one load channel is maxed at 15A, and the algorithm still has to distribute valid currents across every output.
The algorithm works top-down through the hierarchy. Start with the converter’s rated power, account for fixed outputs, distribute the remainder proportionally. But the converter’s power limit isn’t constant: it derates with temperature and input voltage, following curves the system interpolates between defined points. As conditions change, every output’s allocation recalculates. On top of that, each electronic load channel has a physical current limit that the calculation has to honour.
Some tests break the rules on purpose. Over-current protection testing deliberately pushes past the rated limits. The same algorithm that carefully distributes power within budgets has to know when to exceed them.
The calculator below runs the same algorithm as the ATE. Configure a product, adjust temperature and voltage, and see how the power budget redistributes.
Configure a product topology, adjust environment conditions, and see how the algorithm distributes power through the hierarchy.
The load regulation test below is typical. Attributes at the top declare what conditions to vary and what to measure. The framework discovers the class via reflection, injects the correct instrument drivers, generates the condition matrix from the product specification, and runs every combination.
<TestClass(Name:="(C-1-2) Load Regulation", IsOutputTest:=True),MeasurementName(Name:="LoadRegulationInmV", Units:="mV"),TestCondition(Name:="InputVoltage", Units:="V"),TestCondition(Name:="LoadPercentage", Units:="%")>Public Class LoadRegulationTestInherits DVTTestPublic Function MeasureLoadRegulation(condition As TestCondition) As ResultDim loadCurrent As Double = DUT.GetMaximumOutputCurrent(condition.OutputName, condition.InputVoltage, condition.Temperature)loadCurrent *= condition.LoadPercentage * 0.01ACSource.SetOutputVoltage(condition.InputVoltage)ACSource.TurnOn()WaitMilliseconds(SettleTimeAfterPowerOnInms)result.InitialOutputVoltage = LoadArray.MeasureVoltage(condition.OutputName)LoadArray.SetLoadCurrents(loadCurrent)WaitMilliseconds(SettleTimeAfterConditionChange)result.MeasuredOutputVoltage = LoadArray.MeasureVoltage(condition.OutputName)result.DeltaInMv = (result.MeasuredOutputVoltage - result.InitialOutputVoltage) * 1000TurnOff()Return resultEnd FunctionEnd Class
The method body reads like pseudocode because the instruments are abstractions. ACSource, LoadArray, and DUT are interfaces injected at runtime based on the bench configuration. Behind each interface sits a driver translating high-level calls into SCPI command strings sent over GPIB, USB serial, or Ethernet through VISA.
I wrote those drivers for over thirteen instrument types across manufacturers like Chroma, Kikusui, Rohde & Schwarz, and LeCroy: AC sources, electronic loads, oscilloscopes, power analysers, multimeters, and more. Every manufacturer implements SCPI differently, and some instruments only support specific protocols. Each one needed its own workarounds, discovered through testing and direct correspondence with the manufacturers. I also built a custom instrument for switching capacitive loads, with a driver that plugged into the same abstraction layer.
I was learning reflection and attribute-based patterns while the framework was already running production campaigns. My principal engineer set the direction and reviewed my code; I did the design and implementation. Over twenty test procedures in the system all follow this pattern.
The system has tested hundreds of products across TDK-Lambda's range. Five ATEs ran in the department: three bench systems, one rack-mounted, and one shipped to the sister factory in Switzerland. It's still in production today. Along the way, the same electronics and programming skills fed into other projects at TDK, including a Simon Says game I built for the Big Bang Science Fair.
A technician works nine hours, then everything stops until tomorrow. The ATE runs unattended overnight, nearly tripling the available testing hours. A campaign that took weeks of manual bench time could finish over a weekend. Running unattended meant every failure mode needed a safe recovery path; the system had to handle instrument communication drops, unexpected readings, and aborted runs without leaving equipment in an unsafe state.
Technicians monitor progress through a WPF interface that mirrors the execution hierarchy. The test runner fires events at every level (temperature group, test, condition, measurement) and the UI subscribes without coupling to the execution logic. Status and colour propagate up through the tree as results come in.
Each test builds its own report as it runs: measurement tables, charts, scope captures, and pass/fail verdicts against the specification. The framework assembles these into Word, HTML, or PDF. A full campaign generates thousands of data points with embedded waveform captures, so report elements are serialised to a database during execution rather than held in memory.