Skip to content

Add support for the KPC101 K-Cube Piezo Strain Gauge controller - #157

Open
MahsaHabibi wants to merge 9 commits into
mainfrom
kpc101-support
Open

MahsaHabibi wants to merge 9 commits into
mainfrom
kpc101-support

Conversation

@MahsaHabibi

@MahsaHabibi MahsaHabibi commented Jul 9, 2026 •

Copy link
Copy Markdown

Summary

Adds MIC support for the Thorlabs KPC101, which integrates the piezo driver and strain gauge reader into a single K-Cube with a single serial number. MIC predates this device: the existing mex wrappers only cover the split-device architecture (KPZ101/TPZ001 driver + KSG101/TSG001 gauge, PCC_/SG_ C APIs), so classes like mic.linearstage.KCubePiezo and mic.stage3D.NanoMaxPiezos cannot drive it. This PR adds wrappers for the KPC_ C API (Thorlabs.MotionControl.KCube.PiezoStrainGauge) and a new linear stage class, following the existing MIC patterns throughout.

New files

Mex wrappers (mex_source/MIC/Kinesis_KPC_*/mexFunction.cpp + compiled mex64/*.mexw64)

Wrapper Functionality
Kinesis_KPC_Open Opens the device, loads settings, identifies, starts 200 ms polling
Kinesis_KPC_Close Stops polling and closes the device
Kinesis_KPC_SetPosition Commands closed-loop position (uint16, 0-32767 = 0-100% of travel)
Kinesis_KPC_GetPosition Reads position from the strain gauge feedback (same units)
Kinesis_KPC_SetPositionControlMode Sets loop mode (1 = open, 2 = closed)
Kinesis_KPC_SetZero Starts the strain gauge zeroing routine
Kinesis_KPC_GetStatusBits Reads the status word (used to wait for zeroing to finish)
Kinesis_KPC_GetMaximumTravel Best-effort read of actuator travel in 100 nm steps

Build script (mex_source/MIC/buildKPCMex.m)

Compiles all eight wrappers against the Kinesis import library into mex64/. Requires a configured C++ compiler (mex -setup C++) and Kinesis at C:\Program Files\Thorlabs\Kinesis.

Class (src/+mic/+linearstage/@KCubePiezoStrainGauge/KCubePiezoStrainGauge.m)

mic.linearstage.KCubePiezoStrainGauge extends mic.linearstage.abstract. On construction it opens the device, sets closed loop, runs the zeroing routine (~30 s, waits on status bits), and centers the stage. Positions are in microns; the class converts to/from the API's percentage-of-travel WORD internally. Because the device reports true position through its built-in strain gauge, no Slope/Offset calibration is needed (unlike KCubePiezo).

PZ = mic.linearstage.KCubePiezoStrainGauge('113251934','Z');   % 20 um default travel
PZ.setPosition(5);
PZ.getPosition()

MaxPosition is an optional third argument (default 20 um) and must match the Maximum Travel configured in Kinesis — KPC101 firmware was observed to return 0 from KPC_GetMaximumTravel even after zeroing, so the device query is best-effort only.

Runtime DLLs (mex64/)

Adds Thorlabs.MotionControl.KCube.PiezoStrainGauge.dll and updates all existing Thorlabs DLLs in mex64/ from 1.14.10/1.14.11 to 1.14.59. The device DLLs and DeviceManager.dll are mutually version-locked: mixing releases fails at load time with missing-module/missing-procedure errors, so they must all come from the same Kinesis release.

Testing

Verified on hardware (KPC101 S/N 113251934, NanoMax 300 Z axis, 20 um travel, MATLAB R2025b, MSVC 2022):

  • Construction, zeroing, and centering complete cleanly
  • Commanded 5 / 10 / 15 um; strain gauge read back 4.9995 / 10.0003 / 15.0011 um

Known limitation (shared with the other Kinesis mex classes): re-opening the device in the same MATLAB session can crash MATLAB; construct the object once per session.

Notes for reviewers

  • DLL updates affect existing workflows: everyone using this repo's TCube/stepper/laser-diode mex files gets the 1.14.59 DLLs after merging. The Thorlabs device DLLs and DeviceManager.dll only load as a matched set, so a partial update is not possible. Existing mex binaries were not recompiled and load fine against the new DLLs, but other lab setups should be sanity-checked after pulling.
  • Docs workflow fix included: the GenerateDocumentation workflow could never pass on pull requests (PR runs check out a detached HEAD, so its git push step always exits 128). This PR guards the commit-and-push step to run only on push events; on PRs the workflow now just validates that genDoc runs. Happy to split this into a separate PR if preferred.
  • Zeroing on every construction (~30 s): the constructor always runs the strain gauge zeroing routine to guarantee positional accuracy after power-up. If this proves annoying in daily use, an optional skip-zeroing flag would be an easy follow-up.

🤖 Generated with Claude Code

MahsaHabibi and others added 7 commits July 9, 2026 15:44
The KPC101 integrates the piezo controller and strain gauge reader in
a single KCube with one serial number, replacing device pairs like
KPZ101+KSG101. MIC predates this device, so no KPC_ mex wrappers
existed.

- Add 8 Kinesis_KPC_* mex sources in mex_source/MIC/ wrapping the
  Thorlabs.MotionControl.KCube.PiezoStrainGauge C API, following the
  existing Kinesis_KCube_* wrapper pattern
- Add buildKPCMex.m to compile them into mex64/
- Add mic.linearstage.KCubePiezoStrainGauge class: closed-loop
  positioning in microns via built-in strain gauge feedback, with
  device-reported max travel and automatic zeroing on construction

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Built with MATLAB R2025b and Microsoft Visual C++ 2022 against
Kinesis Thorlabs.MotionControl.KCube.PiezoStrainGauge.lib.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Kinesis_KPC_* mex files load
Thorlabs.MotionControl.KCube.PiezoStrainGauge.dll at runtime; MIC keeps
the Thorlabs runtime DLLs in mex64/ since Kinesis is not on the system
PATH. DeviceManager.dll is updated from 1.14.10 to 1.14.59 to match the
PiezoStrainGauge.dll version (both from the current Kinesis install).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The device DLLs and DeviceManager.dll must come from the same Kinesis
release: mixing the new PiezoStrainGauge.dll (1.14.59) with the old
DeviceManager (1.14.10) failed to load, and updating only DeviceManager
made the old device DLLs fail with a missing-procedure load error.
All DLLs are now copied from the same Kinesis install.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On hardware, KPC_GetMaximumTravel returned 0 when called right after
opening the device. Move the travel readout to after the strain gauge
zeroing routine and retry up to 5 times, since the underlying request
is asynchronous.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
KPC101 firmware returns 0 from KPC_GetMaximumTravel even after zeroing
and retries, so the device cannot be relied on to report its travel.
MaxPosition is now an optional constructor argument (default 20 um)
that must match the Maximum Travel configured in Kinesis; the device
query only overrides it (with a warning) if it returns a conflicting
nonzero value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The GenerateDocumentation workflow could never pass on pull requests:
PR runs check out a detached HEAD, so its git push step always exits
128. Guard the commit-and-push step to run only on push events; on PRs
the workflow now just validates that genDoc runs.

Also commit the genDoc-generated Readme.md for the new
KCubePiezoStrainGauge class, matching the other class folders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MahsaHabibi MahsaHabibi assigned MahsaHabibi and kalidke and unassigned MahsaHabibi Jul 9, 2026
MahsaHabibi and others added 2 commits August 19, 2026 07:05
Covers TPZ001+TSG001 (X), KPZ101+KSG101 (Y) and KPC101 (Z): position
sweeps with strain gauge readback, repeatability, small step response,
combined 3D moves and state export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants