Skip to main content

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. Python ctypes, 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.

  1. Navigate to the Releases page on GitHub.
  2. 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)
  3. Extract the downloaded .zip file. The archive contains:
    • include/ — All header files needed to reference functions in your code.
    • lib/ — Compiled library binaries (.dll and .lib for Windows, .so for 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)

  1. Open your project Properties in Visual Studio.
  2. Go to C/C++ -> General -> Additional Include Directories and add the path to the unzipped include/ directory.
  3. Go to Linker -> General -> Additional Library Directories and add the path to the unzipped lib/ directory.
  4. Go to Linker -> Input -> Additional Dependencies and append TheiaMCR_C.lib.
  5. Ensure TheiaMCR_C.dll is copied into your final output directory alongside your compiled .exe before 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

  1. Download and unzip the theiaMCR_C-v{version}-source.zip or clone the repository.
  2. 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 movement
  • pi — photo-interrupter home step position
  • move (default true) — move to home position during initialization
  • homingSpeed (default: motor default) — speed in pps used when homing
  • accel (focus/zoom, default 0) — 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


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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

theiamcr_c-3.5.0.tar.gz (249.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

theiamcr_c-3.5.0-cp313-cp313-win_amd64.whl (382.2 kB view details)

Uploaded CPython 3.13Windows x86-64

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

Hashes for theiamcr_c-3.5.0.tar.gz
Algorithm Hash digest
SHA256 c64c2d774db0ecbac4c8451f02de5c9868296c81f4357456c6e4e8cbed6eb6c9
MD5 801f888fe2b55391456185818e1ee477
BLAKE2b-256 08e7f501513ff90219140f9807acc06998ad122bcdb7d77526ce5f9692f48b78

See more details on using hashes here.

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

Hashes for theiamcr_c-3.5.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 b1882079d7f83c285ad2391b64634edd9686697beec0bdf63af05a217b7ca7ce
MD5 6c6ff8cac20f3a3e3f3a7a3e0dd8392f
BLAKE2b-256 44e2147d3b349a1ff98467af276e3ac5d4e4718500e8fba2ceb46b8d29171766

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page