// C++ Example for Thorlabs LTS stages;
// 2023-09-06;
// 2023-09-06;
// C++20;
// Kinesis 1.14.37;
// ==================
// This example uses the Kinesis C++ API to move and control Thorlabs integrated stepper motor, LTS, K10CR1, and MLJ stages.
//CVI Add dll path to: Options>Environment>Include Path> C:\Program Files\Thorlabs\Kinesis
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <windows.h>
#include <utility.h>
#include "ThorlabsMotionControlIntegratedStepperMotors.h"
void waitMove(char serialNo[]);
void waitHome(char serialNo[]);
char serialNumbers[][9] = {"45388004", "45387934","45388034"};
// Set number of microsteps, found in APT communications protocol. Should be changed to 136533 if using K10CR1
int conversionRate = 409600;
void LTS_Home(int i){
//Set up homing parameters.
MOT_HomingParameters homingParams;
ISC_GetHomingParamsBlock(serialNumbers[i], &homingParams);
homingParams.direction = MOT_Reverse;
ISC_SetHomingParamsBlock(serialNumbers[i], &homingParams);
//Clear existing messages in the hardware buffer.
ISC_ClearMessageQueue(serialNumbers[i]);
//Home the stage and wait for the return message before continuing.
ISC_Home(serialNumbers[i]);
waitHome(serialNumbers[i]);
}
int LTS_Init(int i){
int errorReturn = ISC_Open(serialNumbers[i]);
Sleep(1000);
if (errorReturn == 0){
printf( "Device %d (%s) Connected...\n",i
, serialNumbers
[i
] );
//Settings are loaded based on Stage Name. The integrated stepper class holds LTS and K10CR1 Information.
ISC_StartPolling(serialNumbers[i], 50);
Sleep(1000);
} else {
printf( "Error connecting device %d (%s)\n",i
, serialNumbers
[i
] );
}
return errorReturn;
}
void LTS_Close(int i){
//Close the stage
ISC_StopPolling(serialNumbers[i]);
ISC_Close(serialNumbers[i]);
printf( "Device Disconnected...\n");
}
void LTS_MoveAbsolute(int i, int position){
ISC_SetMoveAbsolutePosition(serialNumbers[i], conversionRate * position);
ISC_MoveAbsolute(serialNumbers[i]);
}
void LTS_MoveRelative(int i, int distance){
ISC_SetMoveRelativeDistance(serialNumbers[i], distance);
ISC_MoveRelativeDistance(serialNumbers[i]);
}
int LTS_GetPosition(int i){
return ISC_GetPosition(serialNumbers[i]);
}
//Waits should only be used for Home commands. The home command has a different status return.
void waitHome(char serialNo[])// Waits until a single axis is homed.
{
WORD messageType;
WORD messageId;
DWORD messageData;
ISC_WaitForMessage(serialNo, &messageType, &messageId, &messageData);
while (messageType != 2 || messageId != 0)
{
ISC_WaitForMessage(serialNo, &messageType, &messageId, &messageData);
printf( "pos: %d\n" , ISC_GetPosition
(serialNo
) );
}
}
void waitMove(char serialNo[])// Waits until axis is stopped.
{
WORD messageType;
WORD messageId;
DWORD messageData;
ISC_WaitForMessage(serialNo, &messageType, &messageId, &messageData);
while (messageType != 2 || messageId != 1)
{
ISC_WaitForMessage(serialNo, &messageType, &messageId, &messageData);
printf( "pos: %d\n", ISC_GetPosition
(serialNo
) );
}
}
#ifdef THORLABS_MAIN
int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow) {
int i,j;
int nlines,atline;
int evcontrl,evpanel,p1_h,ierr,type;
int rstat,n1,n2, n3, nid;
int comled;
int lid[16]= {P1_L1,P1_L2,P1_L3,P1_L4,P1_L5,P1_L6,P1_L7,P1_L8,
P1_L9,P1_L10,P1_L11,P1_L12,P1_L13,P1_L14,P1_L15,P1_L16
};
short int ns2, port;
char tline[80];
if (InitCVIRTE (hInstance, 0, 0) == 0) return -1; /* out of memory */
// p1_h = LoadPanel (0,"ThorlabsLTS_ui.uir", P1);
p1_h = BuildP1 (0);
ierr = DisplayPanel (p1_h);
ierr = SetActiveCtrl (p1_h,P1_B1);
ierr = SetActiveCtrl (p1_h,P1_B2);
ierr = SetActiveCtrl (p1_h,P1_B3);
while (1) {
ierr = GetUserEvent (1, &evpanel, &evcontrl);
if (evcontrl == P1_B1) break;
GetCtrlVal (p1_h, P1_COMLED, &comled);
if (!comled) {
GetCtrlVal (p1_h, P1_PORT, &port);
if (MIKRO_Open (port)) continue;
MIKRO_Init(1,0);
MIKRO_Init(2,0);
MIKRO_Init(3,0);
SetCtrlVal (p1_h, P1_COMLED, 1);
}
switch (evcontrl) {
case P1_BL:
MoveRelative(0,1000);
break;
case P1_BR:
MoveRelative(1,1000);
break;
case P1_BU:
MoveRelative(2,1000);
break;
case P1_BD:
MoveRelative(0,-1000);
break;
case P1_BF:
MoveRelative(1,-1000);
break;
case P1_BB:
MoveRelative(2,-1000);
break;
case P1_HO:
ierr = GetCtrlVal (p1_h, P1_N3, &nid);
LTS_Home(nid);
break;
case P1_GX:
GetCtrlVal (p1_h, P1_XG, &n2);
LTS_MoveAbsolute(0,n2);
break;
case P1_GY:
GetCtrlVal (p1_h, P1_YG, &n2);
LTS_MoveAbsolute(1,n2);
break;
case P1_GZ:
GetCtrlVal (p1_h, P1_ZG, &n3);
LTS_MoveAbsolute(2,n2);
break;
case P1_G:
GetCtrlVal (p1_h, P1_XG, &n2);
LTS_MoveAbsolute(0,n2);
GetCtrlVal (p1_h, P1_YG, &n2);
LTS_MoveAbsolute(1,n2);
GetCtrlVal (p1_h, P1_ZG, &n3);
LTS_MoveAbsolute(2,n3);
case P1_B2:
case P1_S1:
/*
ierr = GetCtrlVal (p1_h, P1_S1, MIKRO_Send);
nout = strlen (MIKRO_Send);
MIKRO_Send[nout++]=13;
rstat = FlushInQ (MIKRO_Port);
rstat = ComWrt (MIKRO_Port, MIKRO_Send, nout);
if ((nin = ComRdTerm (MIKRO_Port, MIKRO_Receive, 30, 0xa))!=0)
nin = ComRdTerm (MIKRO_Port, MIKRO_Receive, 30, 0xa);
if (nin!=0) nin--;
MIKRO_Receive[nin]=0;
switch (nin) {
case 0:
ierr = SetCtrlVal (p1_h, P1_N2, 0);
break;
case 9:
nout = sscanf (MIKRO_Receive, "%x %hx", &n1,&ns2);
ierr = SetCtrlVal (p1_h, P1_N2, ns2);
break;
case 13:
nout = sscanf (MIKRO_Receive, "%x %x", &n1,&n2);
ierr = SetCtrlVal (p1_h, P1_N2, n2);
break;
default:
break;
}
ierr = SetCtrlVal (p1_h, P1_N1, nin);
ierr = SetCtrlVal (p1_h, P1_S2, MIKRO_Receive);
*/
break;
case P1_B3: // reset
/*
ierr = GetCtrlVal (p1_h, P1_N3, &nid);
ierr = GetCtrlVal (p1_h, P1_STAGETYPE, &type);
MIKRO_Reset(nid);
rstat = GetNumTextBoxLines (p1_h, P1_T1, &atline);
rstat = InsertTextBoxLine (p1_h, P1_T1, atline, MIKRO_Receive);
MIKRO_Init(nid, type);
*/
break;
case P1_B4: // status
/*
ierr = GetCtrlVal (p1_h, P1_N3, &nid);
n2=MIKRO_GetStat(nid);
ierr = SetCtrlVal (p1_h, P1_N2, n2);
ierr = SetCtrlVal (p1_h, P1_N1, nin);
ierr = SetCtrlVal (p1_h, P1_S2, MIKRO_Receive);
for (i=0; i<16; i++) {
ierr = SetCtrlVal (p1_h, lid[i], n2 & 1);
n2>>=1;
}
*/
break;
case P1_EN:
/*
ierr = GetCtrlVal (p1_h, P1_N3, &nid);
MIKRO_Cmd(nid,"en");
*/
break;
default:
break;
}
Delay(0.1);
n2 = LTS_GetPosition(0);
SetCtrlVal (p1_h, P1_XP, n2);
n2 = LTS_GetPosition(1);
SetCtrlVal (p1_h, P1_YP, n2);
n2 = LTS_GetPosition(2);
SetCtrlVal (p1_h, P1_ZP, n2);
}
GetCtrlVal (p1_h, P1_COMLED, &comled);
if (comled) for (int i=0;i<3;i++) LTS_Close (i);
return 0;
}
#else
// *************************************
int main(int argc, char ** argv)
{
//Sets up simulations. Comment in if running on physical hardware.
//TLI_InitializeSimulations();
//Input serial number. Change for your specific device.
//serials = ["45388004", "45387934","45388034"]
//Build Device List and open device.
TLI_BuildDeviceList();
TLI_DeviceInfo info;
int err=0;
for (int i=0;i<3;i++){
TLI_GetDeviceInfo(serialNumbers[i], &info);
printf("%s\n", info.
description);
Sleep(1000);
err |= LTS_Init(i);
}
for (int i=0;i<3;i++){
//Move the stage and wait for the return message before continuing.
for (int k=0;k<10;k++){
LTS_MoveAbsolute(i,k);
waitMove(serialNumbers[i]);
printf( "Move Complete...\n");
}
}
for (int i=0;i<3;i++){
LTS_Close(i);
}
//Closes simulations. Comment if running on physical hardware.
//TLI_UninitializeSimulations();
Delay(10);
return 0;
}
#endif