SDK PMSOptical предоставляет 44 экспортируемые C-функции из одной Windows DLL, охватывающие последовательное и Ethernet-соединение, абсолютное позиционирование, обратное чтение состояния, возможности шифрованной контроллерной карты и полное параллельное семейство API для двухмоторных объективов. Базовый рабочий процесс — четыре вызова: open → home → move → wait. Дескриптор получают через PMSOptical_OpenComm("COM1", 9600) для последовательного порта или PMSOptical_OpenSocket("192.168.1.200", 4196) для TCP.
В этом руководстве описаны семейства функций, рекомендуемая последовательность вызовов и четыре ограничения интеграции, вызывающие большинство проблем у новичков, — включая одно, важное для безопасности оборудования: в SDK нет пригодной для использования программной аварийной остановки.
| Пункт | Значение |
|---|---|
| Экспортируемые функции | 44 (24 одномоторные, 20 двухмоторных) |
| Платформа | Windows x64 / x86 (DLL) |
| Соединение | Последовательный порт 9600 бод или TCP на порту 4196 |
| Тип дескриптора | PMSHANDLE (void*) — всегда проверяйте на null |
| Базовая последовательность | Open → GoHome → MoveTo(pulse) → WaitForOpticalFinished → GetPos → Close |
| Тайм-аут ожидания по умолчанию | 100000 ms (100 s) |
| Нереализованные функции | 8, включая Stop и Stop2 |
| Привязки языков | Нативный C++; C# через P/Invoke; другие языки через ctypes/cffi (официальной привязки нет) |
PMSOptical-SDK/
├── Doc/
│ ├── POMEAS electric lens development documents V4.4.7.pdf (English)
│ ├── encrypted / non-encrypted development documents V4.4.7 (control-card comparison)
│ └── dual-motor control card operation manual V1.5
├── SDK/
│ ├── include/PMSOpticalDll.h 44 exported functions
│ ├── x64/{Release,Debug}/PMSOpticalDll.dll + .lib
│ │ └── OP/*.txt per-model pulse tables
│ └── x86/{Release,Debug}/ same, 32-bit
└── demo/
└── x64/PMSOpticalDemo.exe + .ini MFC demo application
DLL должна лежать рядом с исполняемым файлом или находиться в системном PATH.
| Способ | Функция | Параметры |
|---|---|---|
| Последовательный | PMSOptical_OpenComm(char* comname, int nBaud) | comname, напр. "COM1"; nBaud = 9600 |
| Ethernet | PMSOptical_OpenSocket(char* ip, int nPort) | ip, напр. "192.168.1.200"; nPort = 4196 |
| Запрос состояния | PMSOptical_IsOpened(PMSHANDLE, bool&) | — |
| Закрытие | PMSOptical_Close(PMSHANDLE&) | Дескриптор передаётся по ссылке |
Для сетевого подключения хост-ПК и контроллерная карта объектива должны находиться в одной подсети — первые три октета должны совпадать, например 192.168.1.xxx. Маска подсети получается автоматически.
#include "PMSOpticalDll.h"
PMSHANDLE h = PMSOptical_OpenComm("COM2", 9600); // serial
// PMSHANDLE h = PMSOptical_OpenSocket("192.168.1.200", 4196); // Ethernet
if (!h) { /* connection failed */ }
| № | Функция | Назначение |
|---|---|---|
| 1 | PMSOptical_OpenSocket(char* ip, int nPort) | Открыть через Ethernet, вернуть дескриптор устройства |
| 2 | PMSOptical_OpenComm(char* comname, int nBaud) | Открыть через последовательный порт, вернуть дескриптор устройства |
| 3 | PMSOptical_IsOpened(PMSHANDLE, bool& bIsOpened) | Сообщить, открыт ли дескриптор |
| 4 | PMSOptical_Close(PMSHANDLE&) | Закрыть дескриптор |
Функции 3 и 4 передают результат и дескриптор по ссылке. Это сделано намеренно: в заголовочном файле отмечено, что сигнатуры сформированы так ради совместимости с C# P/Invoke.
| № | Функция | Назначение | Реализовано |
|---|---|---|---|
| 5 | GoHome(PMSHANDLE) | Возврат в исходное положение | Да |
| 6 | IsHomed(PMSHANDLE, bool&) | Сообщить, завершён ли возврат в исходное положение | Нет — помечено как нереализованное |
| 7 | MoveTo(PMSHANDLE, int nPulse) | Переход в абсолютную позицию по импульсам | Да |
| 8 | Stop(PMSHANDLE) | Остановка немедленно | Нет — помечено как нереализованное |
| 9 | JogStart(PMSHANDLE, int nJogSpeed) | Джог (положительная или отрицательная скорость) | Нет — помечено как нереализованное |
| 10 | JogStop(PMSHANDLE) | Остановка джога | Нет — помечено как нереализованное |
| 11 | GetPos(PMSHANDLE, int& nCurPulse) | Чтение текущей позиции | Да |
| 12 | GetMaxPos(PMSHANDLE, int& nMaxPulse) | Чтение максимального импульса (общего хода) | Да |
| 13 | GetStatus(PMSHANDLE, int& nStatus) | Чтение состояния движения: 0 движение, 1 остановка, 2 сбой инициализации | Да |
| 14 | WaitForOpticalFinished(PMSHANDLE, int nTimeOut = 100000) | Блокировка до завершения движения зума | Да |
| 15 | GetVer(PMSHANDLE, char* Ver) | Чтение версии прошивки | Да |
WaitForOpticalFinished внутренне оборачивает логику опроса состояния — опрашивает запрос статуса и проверяет признак останова — с тайм-аутом по умолчанию 100000 ms. В большинстве приложений следует вызывать её, а не писать собственный цикл опроса.
Доступно только когда объектив укомплектован шифрованной контроллерной картой (обозначается словом encrypt в имени файла таблицы импульсов).
| № | Функция | Назначение |
|---|---|---|
| 16 | EncryptCommStatus(PMSHANDLE, bool& IsConnected) | Подключена ли шифрованная плата |
| 17 | EncryptReadTimes(PMSHANDLE, int& nTimes) | Чтение счётчика циклов зума |
| 18 | EncryptWriteTimes(PMSHANDLE, int nTimes) | Запись счётчика циклов зума |
| 19 | EncryptAddTimes(PMSHANDLE) | Увеличение счётчика циклов зума |
| 20 | EncryptReadFlashMaxPos(PMSHANDLE, int&) | Чтение максимального импульса, хранящегося в Flash |
| 21 | EncryptWriteFlashMaxPos(PMSHANDLE, int) | Запись максимального импульса в Flash |
| 22 | EncryptCheckHomeStatus(PMSHANDLE, bool& bHasStatus, bool& bNowStatus) | Состояние возврата в исходное положение и концевого выключателя |
| 23 | EncryptReadFlashLensInfo(PMSHANDLE, unsigned char buf[64]) | Чтение информации об объективе (фиксированный блок 64 байта) |
| 24 | EncryptWriteFlashLensInfo(PMSHANDLE, unsigned char buf[64]) | Запись информации об объективе (только печатный ASCII) |
Для чего на самом деле нужна шифрованная карта: она хранит счётчик циклов зума и 64-байтовый блок идентификации объектива в Flash контроллера. Это поддерживает учёт активов оборудования, статистику использования и распознавание подлинного объектива — непосредственно полезно для системных интеграторов, прокатных парков и сервисных служб.
У каждой функции выше есть параллельная версия с суффиксом 2 и конечным параметром unsigned char u8lensnum = 0, выбирающим мотор 1 или мотор 2.
| Одномоторная | Двухмоторная | Назначение |
|---|---|---|
GoHome | GoHome2(h, u8lensnum) | Возврат выбранного мотора в исходное положение |
IsHomed | IsHomed2(h, bool&, u8lensnum) | Нереализовано |
MoveTo | MoveTo2(h, nPulse, u8lensnum) | Переход выбранного мотора в абсолютную позицию |
Stop | Stop2(h, u8lensnum) | Нереализовано |
JogStart / JogStop | JogStart2 / JogStop2 | Нереализовано |
GetPos | GetPos2(h, int&, u8lensnum) | Чтение позиции |
GetMaxPos | GetMaxPos2(h, int&, u8lensnum) | Чтение общего хода |
GetStatus | GetStatus2(h, int&, u8lensnum) | Чтение состояния |
WaitForOpticalFinished | WaitForOpticalFinished2(h, nTimeOut, u8lensnum) | Ожидание завершения |
GetVer | GetVer2(h, char*, u8lensnum) | Чтение версии прошивки |
Encrypt* (9 functions) | Encrypt*2(h, …, u8lensnum) | Полный набор для шифрованной карты |
Двухмоторные объективы сочетают мотор зума с независимым мотором доводки фокуса — например, зум-объектив 12.5X с 12 mm моторизованной доводкой фокуса или двухмоторный 12.5X с осью доводки 3 mm.
// Dual motor: motor 0 = zoom, motor 1 = focus trim
PMSOptical_GoHome2(h, 0);
PMSOptical_MoveTo2(h, 4600, 0); // zoom to 1X (see the model pulse table)
PMSOptical_WaitForOpticalFinished2(h, 100000, 0);
Open (serial or Ethernet)
|
GoHome() -> WaitForOpticalFinished(timeout)
|
GetMaxPos() -> validate total travel, and confirm the link is alive
|
+-- MoveTo(pulse)
| -> WaitForOpticalFinished(timeout) (or poll GetStatus until it returns 1)
| -> GetPos() -> compare with target (closed loop)
+-- repeat for the next magnification
|
Close()
Блок-схема производителя предписывает три правила для пути опроса:
Пока контроллерная карта приводит мотор, связь приостанавливается. Запрос статуса может вообще ничего не вернуть. Обрабатывайте это через тайм-аут и повтор или вызывая WaitForOpticalFinished. Не считайте это сбоем и не перезапускайте соединение.
Если запрошенный импульс равен текущему, объектив не двигается и сообщает об успехе. Никогда не используйте «команда отправлена» как проверку живости линии. Используйте вместо этого GetMaxPos или GetPos.
При включении питания объектив сам возвращается в исходное положение и не принимает команд в это время. Прикладная программа должна ждать не менее 35 секунд, прежде чем открывать соединение и отдавать команды. Игнорирование этого — частая причина сообщений «устройство не отвечает», которые на самом деле не являются сбоями.
Stop и Stop2 оба помечены как нереализованные в заголовочном файле, наряду с IsHomed, JogStart, JogStop и их двухмоторными аналогами — всего восемь функций. Не проектируйте вокруг них функцию безопасности. Определяйте завершение через GetStatus или WaitForOpticalFinished, а аварийную остановку реализуйте аппаратной схемой — отключением питания или внешним сигналом блокировки.
| Требование | Рекомендация |
|---|---|
| Только управление зумом | Стандартная карта |
| Подсчёт использования, проверка подлинности, прокатная тарификация | Шифрованная карта (EncryptReadTimes, EncryptReadFlashLensInfo) |
| Смешанный парк | Учтите, что две карты используют разные таблицы импульсов — смена карты означает смену таблицы |
Официальный SDK поставляется только с DLL для Windows (x64 и x86). На других платформах реализуйте последовательный протокол напрямую — это пять простых ASCII-команд без привязки к платформе, поэтому они работают на любом хосте с последовательным портом или TCP-сокетом.
Да, через ctypes или cffi, поскольку экспорты имеют C-связывание. Официальной привязки Python нет, поэтому обёртку пишете вы сами. Учтите, что PMSHANDLE — это void*, а параметры bool& нужно передавать через ctypes.byref.
Технически да, но не делайте этого на одной линии. Оба обращаются к одним и тем же аппаратным регистрам, и их смешивание — особенно вблизи исходной точки (home) — приводит к несогласованному состоянию. Выберите один подход на проект.
По умолчанию 100000 ms. Задайте его не менее чем в два раза больше времени, которое самый большой ход зума занимает на вашем оборудовании. Справочное значение в руководстве — 10 секунд или более.
Нет, и описывать его так не следует. SDK предоставляет программируемый интерфейс управления оптикой — позицию, состояние и обратное чтение. Его можно интегрировать в архитектуру ИИ-зрения, где управляющее ПО выдаёт новую команду увеличения на основе результата инспекции, но сам SDK не содержит возможностей ИИ или анализа изображений. Точная формулировка: моторизованную зум-оптику можно интегрировать в управляемый ИИ рабочий процесс машинного зрения.
Две стоит знать. GetVer2 объявляет свой параметр как u8lennum — опечатка, не влияющая на вызов, но её стоит нормализовать в собственной обёртке. И на восемь нереализованных функций, описанных выше, полагаться нельзя.
MoveTo
Введите свой адрес электронной почты, чтобы получать свежие новости и эксклюзивные обновления от Pomeas. Оставайтесь на связи с Pomeas и будьте в курсе новейших оптических решений.