Python gets most of the attention in PicoSDK tutorials because it is the fastest way to get a measurement script running on a laboratory bench. But laboratory scripts are not production test rigs, and the moment an Indian contract manufacturer, a Tier-1 automotive supplier, or a medical device company moves a measurement from R&D to the production line, the runtime environment changes completely. This post walks through when C and C++ are the right PicoSDK bindings for Indian production test work, the native PicoSDK API lifecycle your test executive needs to implement, the RAII and error-handling conventions that production C++ teams settle on, and the deployment patterns that keep a fanless industrial PC on a contract manufacturing line running for five years without a reinstall.
GSAS Micro Systems is the authorized Indian engineering partner for Pico Technology, and a significant fraction of our Pico shipments end up inside in-house test executives on production lines in Bengaluru, Pune, Chennai, and Hyderabad. The questions from those teams are rarely about Python, they are about C API version stability, single-binary deployment, Windows vs Linux portability, and how to drive four PicoScope units from one test executive at full line rate. That is the story this post tells.
Why C/C++ is the right choice for a production test rig
PicoSDK ships native C headers and platform libraries for every supported PicoScope and PicoLog family. The Python wrappers and the MATLAB instrument drivers all sit on top of that C layer, they are thin shims that marshal data in and out of the same functions your C test executive would call directly. For bench work the convenience of Python outweighs the overhead. For a production line, the calculus flips for four specific reasons.
The runtime environment is locked. A fanless industrial PC running Windows IoT LTSC or a Yocto-built embedded Linux distribution typically has no package manager, no interpreter, and no developer tooling. Adding a Python runtime to an audited test environment means adding a dependency the IT and validation teams did not sign off on. A single statically-linked C++ binary plus the PicoSDK shared libraries is a much smaller change surface than CPython plus forty pip packages.
Cycle time matters. On a board-level test cell handling one unit every eight seconds, the Python interpreter startup, GIL contention during multi-threaded acquisition, and marshalling overhead between NumPy and ctypes buffers add up. A C++ test executive opens the PicoScope handle once at line start, reuses pre-allocated buffers for every unit, and hits the same cycle time with measurable headroom.
Single-binary deliverables simplify validation. In an audited environment, medical device assembly in Hyderabad, aerospace sub-assembly in Bengaluru, or a Tier-1 automotive customer quality specification, the production test software is a controlled artefact. A single signed .exe or .elf is easier to version, hash, and audit than a Python tree with a requirements.txt that shifts every pip install. And if the test rig is part of a larger C++ application already wrapping a programmer, a GPIB or Modbus instrument chain, and a PLC interface, PicoSDK C/C++ drops into that environment cleanly.
The native PicoSDK C API lifecycle
Every PicoScope and PicoLog family in PicoSDK follows the same shape of C API. The driver names differ, ps5000a, ps6000a, ps4000a, picoipp, plcm3, and so on, but the call pattern is consistent. For a production test executive targeting the PicoScope 5000D series as a worked example:
#include <libps5000a/ps5000aApi.h>
int16_t handle;
PICO_STATUS status;
// 1. Open the unit, selecting hardware resolution up front.
status = ps5000aOpenUnit(&handle, NULL, PS5000A_DR_14BIT);
if (status != PICO_OK) { /* error path */ }
// 2. Configure each channel's range, coupling, and bandwidth limit.
status = ps5000aSetChannel(handle, PS5000A_CHANNEL_A, 1,
PS5000A_DC, PS5000A_5V, 0.0f);
// 3. Set up the trigger.
status = ps5000aSetSimpleTrigger(handle, 1, PS5000A_CHANNEL_A,
16384, PS5000A_RISING, 0, 0);
// 4. Arm the block-mode acquisition.
int32_t timeIndisposedMs = 0;
status = ps5000aRunBlock(handle, 0, 10000, 1, &timeIndisposedMs,
0, NULL, NULL);
// 5. Poll or wait-on-callback until ready.
int16_t ready = 0;
while (!ready) {
ps5000aIsReady(handle, &ready);
}
// 6. Register a destination buffer and read the samples.
int16_t buffer[10000];
ps5000aSetDataBuffer(handle, PS5000A_CHANNEL_A, buffer, 10000, 0, PS5000A_RATIO_MODE_NONE);
uint32_t samples = 10000;
ps5000aGetValues(handle, 0, &samples, 1, PS5000A_RATIO_MODE_NONE, 0, NULL);
// 7. Post-test cleanup.
ps5000aCloseUnit(handle);
On Windows the linker consumes ps5000a.lib from the SDK install directory; on Linux the shared object is libps5000a.so and the linker flag is -lps5000a. macOS uses .dylib variants. Include paths and library names are the only portions of the code that normally need conditional compilation.
Block mode vs streaming in C. Block mode (the pattern above) is right for the vast majority of production test measurements, a fixed trigger, a fixed number of samples, a fixed analysis. Streaming mode, ps5000aRunStreaming, ps5000aGetStreamingLatestValues with a callback, is used when the test involves observing a signal continuously for seconds or minutes, typical for board-level burn-in, insulated-gate bipolar transistor life test, or motor soak measurements.
Async callbacks vs polled completion. PicoSDK supports both a pBlockReady callback that fires from the driver thread when acquisition is complete, and a polled ps5000aIsReady loop. Production C++ code usually prefers the callback, it frees the main test-executive thread to drive other instruments (programmer, PSU, PLC) in parallel with the PicoScope acquisition. The callback runs on a driver-owned thread, so the handler must be short, must not call back into ps5000aGetValues directly, and should post to a thread-safe queue that the main thread drains.
C++ wrapper conventions Indian production teams settle on
C is portable and tiny, but a production test codebase almost always wraps the raw PicoSDK calls in a small C++ layer to make the rest of the application safer and easier to reason about. Four conventions show up repeatedly.
RAII around the device handle. A PicoScope5000D class opens the unit in its constructor, stores the int16_t handle, and closes it in the destructor. Test-executive code that constructs the object at line start and holds it in a std::unique_ptr for the shift’s duration never leaks a handle, even if an exception propagates through the test logic.
Exception translation from PICO_STATUS. Raw PicoSDK functions return a PICO_STATUS enum. A wrapper method checks the status after each call and throws a typed PicoException carrying the status code and the name of the failing function. Tests that want the old C-style behaviour can still catch the exception and inspect the code; tests that prefer exception-driven control flow get it automatically.
std::vector<int16_t> and std::span<int16_t> for sample buffers. Sized containers replace raw pointers and explicit lengths. A captureBlock(std::span<int16_t> dst) method takes a caller-owned buffer and fills it, letting the caller decide whether to allocate once for the shift or per-unit.
enum class wrappers around the integer constants. PicoSDK headers use integer #define or legacy enum for channel identifiers, voltage ranges, trigger directions, and coupling modes. Wrapping those in enum class Channel : int16_t { A = 0, B = 1, C = 2, D = 3 }; and similar for Range, Coupling, TriggerDirection catches almost every “wrong argument to ps5000aSetChannel” bug at compile time instead of runtime.
Multi-unit test rigs: driving several PicoScopes from one test executive
Many Indian contract manufacturing lines want to test several boards in parallel through one PC. PicoSDK supports multiple simultaneous PicoScope units on the same host with two conventions that matter for production code.
Each OpenUnit call returns a distinct handle. A PicoScope 4000A plus three PicoScope 2205A MSO units plugged into a powered USB 3.0 hub give four independent handles. The C++ wrapper can hold four RAII objects inside a std::array<std::unique_ptr<PicoScope>, 4> and the main test thread can dispatch acquisition to each in sequence.
Where truly parallel acquisition is needed, four boards under test at the same cycle time, or cross-correlated channels across two PicoScope 5000D units, the driver’s block-ready callback is the right primitive. Arm all four units from the main thread, return, and let the four driver callbacks fire independently as each unit finishes. A std::mutex plus std::condition_variable coordinate the “all four done” rendezvous before the test executive moves to the analysis step.
USB bandwidth is the limit to watch. Four PicoScope 4000A units on a single hub running short block captures on two channels each at moderate sample rate share the USB 3.0 bus comfortably; four PicoScope 6000E units streaming at 5 GS/s most certainly do not. For high-throughput parallel test, one USB 3.0 root hub per PicoScope, a motherboard with multiple discrete USB 3.0 controllers, or a PCIe USB 3.0 card per unit, removes the bottleneck.
Cross-platform builds with CMake
Windows, Linux, and macOS share the bulk of a PicoSDK C++ codebase. CMake is the standard build driver, and the conditional-compilation points are small, the USB enumeration delay window after OpenUnit (Linux kernels typically need a shorter wait than Windows), callback calling conventions in older SDK revisions, and the header include layout. A small platform-specific header in your wrapper folder contains the differences; the rest of the test executive is portable.
Indian production use cases worth calling out
Bengaluru consumer electronics board test. A contract manufacturer runs board-level functional test on a fanless industrial Linux PC. The test executive is a single C++ binary linked against libps5000a.so, driving a PicoScope 5000D Series for analog rail measurements and signal-integrity spot checks. The RAII wrapper constructs at line start and the test thread cycles through boards at the conveyor rate.
Pune automotive Tier-1 validation rig. A Tier-1 supplier validation bench on a Windows industrial PC runs an in-house C++ test executive that drives a programmer, a CAN interface, and a PLC. A PicoScope 6000E provides high-bandwidth capture for electromagnetic interference pre-screens and power-rail transient measurements, integrated via a single wrapper class.
Chennai contract manufacturing parallel-test line. Four PicoScope 4000A units on a powered USB 3.0 hub test four boards in parallel. The test executive uses the driver’s block-ready callback to trigger all four acquisitions simultaneously and waits on a condition variable for completion.
Hyderabad medical device production. A regulated assembly line requires the test software to ship as a single signed binary. The C++ test executive links statically where possible, with the PicoSDK shared libraries as the only runtime dependency, under the configuration-management system the validation team already uses.
Further reading
- PicoSDK on picotech.com, canonical SDK documentation and downloads
- PicoSDK C function examples on GitHub, reference C code for every supported PicoScope family
- Pico Technology partner page, full PicoScope range available in India from GSAS
- PicoSDK product page, SDK support details for Indian teams
- pyPicoSDK for automated test, the Python-side complement when the test rig is happier in Python
- pyPicoSDK streaming mode, long-duration capture patterns that apply equally well in C++
- PicoScope 6000E deep dive, flagship scope for high-throughput validation benches
The takeaway for Indian production engineering teams
PicoSDK C and C++ are not the exciting way to write a PicoScope program, Python and MATLAB both demo better. But on a production test cell, the excitement is over long before the line starts. What matters then is a single binary that opens its PicoScope handles at shift start, runs the same cycle thousands of times without drift, and does not need a Python interpreter on the audited industrial PC. The PicoSDK C API is small, stable, and portable across Windows and Linux, and the C++ wrapper patterns above are what Indian production teams converge on by the time the second or third product ships on the same rig.
GSAS Micro Systems supports Indian production teams adopting PicoScope hardware into their in-house test executives, from initial selection through bring-up to on-site integration. Our engineering teams in Bengaluru, Chennai, Hyderabad, Pune, Mumbai, and Delhi NCR handle hardware supply, PicoSDK orientation, and test-rig commissioning across the contract manufacturing, automotive Tier-1, medical device, and aerospace sub-assembly markets we serve.
Also appears in:
Interested in Pico Technology tools?
Talk to our application engineers for personalized tool recommendations.
More from Pico Technology
View all →