C++ Motor Control Board Interface - Python bindings for Theia MCR IQ 400 motor control board
Project description
TheiaMCR_C — C++ Motor Control Board Interface
Theia Technologies offers the MCR IQ 400 motor control board for controlling motorized lenses. This board drives focus, zoom, iris, and IRC filter motors and connects to a host computer over USB, UART, or I2C.
This repository is the C++ port of the TheiaMCR Python module. It provides:
- A native C++ library (
TheiaMCR.h / TheiaMCR.cpp) with the full motor control API - A C-linkage shared library (
TheiaMCR_C.dll/libTheiaMCR_C.so) callable from C, C++, or any language that loads shared libraries (e.g. Pythonctypes, LabVIEW, MATLAB) - A pybind11 Python module (
TheiaMCR_py.pyd) with native-speed Python bindings to the same C++ class
Which version should I use?
| Use case | Recommended module |
|---|---|
| Writing a C++ application | TheiaMCR.h — native C++ class, full API |
| Calling from C, LabVIEW, MATLAB, or any non-Python language | TheiaMCR_C.dll — C-linkage shared library via TheiaMCR_C.h |
| Writing a Python script that needs maximum performance or access to the full C++ API | TheiaMCR_py — pybind11 module (built alongside the C library) |
| Writing a Python script using only pip, no compilation needed | TheiaMCR on PyPI — pure-Python package |
TheiaMCR_C.cpp implements the flat C-linkage wrapper (MCR_Create, MCR_Focus_MoveAbs, etc.). Use it when you need a stable ABI that any language can call without a C++ compiler or Python interpreter on the target.
TheiaMCR_pybind11.cpp exposes the native C++ class directly to Python. The resulting TheiaMCR_py module mirrors the Python TheiaMCR package API almost exactly, so existing Python code is easy to port, while running at native C++ speed. Choose this when Python is your target language and you want the full feature set with no pip dependency.
Getting theiaMCR_C
Unlike other languages, C++ does not have a standard built-in package manager like Python's pip. Because of this, the standard and most direct method to integrate the theiaMCR_C library into your project is to download the package structure directly without requiring external registries.
1. Download prebuilt packages
Prebuilt binaries compiled for common platforms are published with each release.
- Navigate to the Releases page on GitHub.
- Under Assets for the latest release, download the package matching your environment:
theiaMCR_C-v{version}-windows-x64.zip(for 64-bit Windows)theiaMCR_C-v{version}-linux-x64.zip(for 64-bit Linux)theiaMCR_C-v{version}-source.zip(if you wish to build it yourself from source)
- Extract the downloaded
.zipfile. The archive contains:include/— All header files needed to reference functions in your code.lib/— Compiled library binaries (.dlland.libfor Windows,.sofor Linux).
Integrating Prebuilt Binaries into Your Project
To use the prebuilt binaries in your own projects, you simply need to point your build tool or IDE to the unzipped folders:
Option A: Using CMake (Recommended)
If your project uses CMake, add the following pattern to your CMakeLists.txt (substituting the path to where you unzipped the package):
# Define the path to your extracted package
set(THEIA_SDK_DIR "/path/to/extracted/theiaMCR_C")
# Include the headers directory
target_include_directories(your_target PRIVATE "${THEIA_SDK_DIR}/include")
# Link the binary library
# On Windows, you link the .lib import library and ensure the .dll is placed alongside your executable.
# On Linux, link the shared object (.so) directly.
find_library(THEIA_MCR_LIB TheiaMCR_C HINTS "${THEIA_SDK_DIR}/lib")
target_link_libraries(your_target PRIVATE ${THEIA_MCR_LIB})
Option B: Using Visual Studio (Windows)
- Open your project Properties in Visual Studio.
- Go to C/C++ -> General -> Additional Include Directories and add the path to the unzipped
include/directory. - Go to Linker -> General -> Additional Library Directories and add the path to the unzipped
lib/directory. - Go to Linker -> Input -> Additional Dependencies and append
TheiaMCR_C.lib. - Ensure
TheiaMCR_C.dllis copied into your final output directory alongside your compiled.exebefore running.
Building from Source
If you want to build the SDK from source instead of using prebuilt binaries:
Prerequisites
- A C++ compiler: MSVC (Visual Studio) on Windows, or GCC/Clang on Linux.
- CMake ≥ 3.15.
Building
- Download and unzip the
theiaMCR_C-v{version}-source.zipor clone the repository. - From the root directory, configure and build using CMake:
# Configure the build system (produces Release configuration files)
cmake -B build -DCMAKE_BUILD_TYPE=Release
# Compile the library
cmake --build build --config Release
The resulting library binaries will be located under your build/ (or build/Release/) folder.
Features
The MCR IQ 400 board (and MCR IQ 600, MCR IQ 500, and others in the MCR series) uses a proprietary byte-string command protocol. This library formats and sends those commands automatically. For example, calling focus.moveAbs(6000) converts the request into the correct byte string and sends it over the USB virtual COM port, causing the lens motor to move to step 6000.
Motor initialization
After creating the control object, initialize each motor with its lens-specific step count and PI home position (from the lens specification sheet):
C++ (native API)
#include "TheiaMCR.h"
TheiaMCR::MCRControl MCR("COM4");
// TL1250 lens parameters:
MCR.focusInit(8390, 7959);
MCR.zoomInit(3227, 3119);
MCR.irisInit(75);
MCR.IRCInit();
Python (pybind11 module)
import sys; sys.path.append("build/Debug")
import TheiaMCR_py as mcr
MCR = mcr.MCRControl("COM4")
MCR.focusInit(8390, 7959)
MCR.zoomInit(3227, 3119)
MCR.irisInit(75)
MCR.IRCInit()
Python (ctypes, C-linkage library)
import ctypes
lib = ctypes.CDLL("./TheiaMCR_C.dll") # or libTheiaMCR_C.so on Linux
lib.MCR_Create.restype = ctypes.c_void_p
lib.MCR_Create.argtypes = [ctypes.c_char_p]
lib.MCR_Focus_MoveAbs.restype = ctypes.c_int
lib.MCR_Focus_MoveAbs.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
handle = lib.MCR_Create(b"COM4")
if lib.MCR_IsInitialized(handle):
lib.MCR_Focus_MoveAbs(handle, 6000, 1200)
lib.MCR_Destroy(handle)
Motor limits (lens parameters)
| Lens | focusInit |
zoomInit |
irisInit |
|---|---|---|---|
| TL1250 (-N) | focusInit(8390, 7959) |
zoomInit(3227, 3119) |
irisInit(75) |
| TL410 (-R) | focusInit(9353, 8652) |
zoomInit(4073, 154) |
irisInit(75) |
The PI position is the photo-interrupter home step. After homing, currentStep is set to PIStep. The motor can then travel from 0 (hard stop) through PIStep to maxSteps (hard stop). Hitting either hard stop causes a step-count mismatch; re-home the lens to recover.
Motor init parameters (all motors):
steps— total steps in the full range of movementpi— photo-interrupter home step positionmove(defaulttrue) — move to home position during initializationhomingSpeed(default: motor default) — speed in pps used when homingaccel(focus/zoom, default0) — acceleration steps (reserved for future hardware)
Motor functions
Each motor (focus, zoom, iris) supports:
| Function | Description |
|---|---|
motor.home() |
Move to the PI limit-switch home position |
motor.moveAbs(step) |
Move to an absolute step number |
motor.moveRel(steps, correctForBL=true) |
Move by a relative number of steps with optional backlash correction |
motor.setMotorSpeed(speed) |
Set speed in pps (focus/zoom: 100–1500; iris: 10–200) |
motor.setHomingSpeed(speed) |
Set homing speed in pps |
motor.setRespectLimits(state) |
Enable/disable enforcement of the PI limit position |
motor.readMotorSetup() |
Read motor configuration from board EEPROM |
motor.writeMotorSetup(...) |
Write motor configuration to board EEPROM |
IRC filter: MCR.IRC.state(1) (visible/IR-cut) or MCR.IRC.state(2) (clear filter).
Motor variables
| Variable | Description |
|---|---|
currentStep |
Current motor step number |
currentSpeed |
Current speed in pps |
homingSpeed |
Speed used when homing to PI position |
maxSteps |
Maximum steps for the full travel range |
PIStep |
PI limit-switch step position |
PISide |
1 if PI is on the high step side, -1 if on the low side |
respectLimits |
When true, moves are prevented from passing the PI limit |
Board functions
| Function | Description |
|---|---|
MCR.readFWRevision() |
Returns firmware version string (e.g. "5.3.1.0.0") |
MCR.readBoardSN() |
Returns board serial number string |
MCR.close() |
Close the serial port and release resources |
MCR.closeLogFiles() |
Stop logging to file; console logging continues |
MCRControl::setLogLevel(level) |
Library-wide log level: 0=off 1=error 2=warn 3=info 4=debug 5=trace |
Examples
See the Examples/ folder:
| File | Description |
|---|---|
Examples/cpp/Example_3.5.cpp |
Native C++ example — build with cmake -DBUILD_EXAMPLES=ON .. |
Examples/python/Example_3.5.py |
Python pybind11 example — run after building the TheiaMCR_py target |
Logging
The library uses spdlog for logging. Control the log level:
// C++
TheiaMCR::MCRControl::setLogLevel(3); // 3 = info
# Python (pybind11)
mcr.setLogLevel(3)
Log levels: 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace (shows raw byte communication).
See also
- TheiaMCR Python package (PyPI) — pure-Python version, install with
pip install TheiaMCR - MCR IQ 400 documentation
License
Theia Technologies BSD-3-Clause license
Copyright 2023–2026 Theia Technologies
Contact
Mark Peterson — Theia Technologies
mpeterson@theiatech.com
Revision
v.3.5
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file theiamcr_c-3.5.0.tar.gz.
File metadata
- Download URL: theiamcr_c-3.5.0.tar.gz
- Upload date:
- Size: 249.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c64c2d774db0ecbac4c8451f02de5c9868296c81f4357456c6e4e8cbed6eb6c9
|
|
| MD5 |
801f888fe2b55391456185818e1ee477
|
|
| BLAKE2b-256 |
08e7f501513ff90219140f9807acc06998ad122bcdb7d77526ce5f9692f48b78
|
File details
Details for the file theiamcr_c-3.5.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: theiamcr_c-3.5.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 382.2 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1882079d7f83c285ad2391b64634edd9686697beec0bdf63af05a217b7ca7ce
|
|
| MD5 |
6c6ff8cac20f3a3e3f3a7a3e0dd8392f
|
|
| BLAKE2b-256 |
44e2147d3b349a1ff98467af276e3ac5d4e4718500e8fba2ceb46b8d29171766
|