Subversion Repositories f9daq

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
365 f9daq 1
 
2
// This example uses the Kinesis C++ API to move and control Thorlabs integrated stepper motor, LTS, K10CR1, and MLJ stages.
3
/* Default parameters
4
HS LTS300C 300mm Stage
5
 
6
General
7
 
8
Name = HS LTS300C 300mm Stage
9
Stage ID = Unknown
10
Axis ID = SingleAxis
11
 
12
Home Settings
13
 
14
HomeDir = MOT_Reverse
15
HomeLimitSwitch = MOT_ReverseLimitSwitch
16
HomeVel = 2
17
HomeZeroOffset = 0,5
18
 
19
Jog Settings
20
 
21
JogMode = MOT_ExtSingleStep
22
JogStopMode = MOT_Profiled
23
JogStepSize = 5,0
24
JogMinVel = 0,0
25
JogAccn = 10,0
26
JogMaxVel = 10,0
27
 
28
Control Settings
29
 
30
DefMinVel = 0,0
31
DefAccn = 20,0
32
DefMaxVel = 20,0
33
 
34
Limit Settings
35
 
36
CWHardLimit = MOT_LimitSwitchMakeOnContact
37
CCWHardLimit = MOT_LimitSwitchMakeOnContact
38
CWSoftLimit = 3,0
39
CCWSoftLimit = 1,0
40
SoftLimitMode = MOT_LimitSwitchIgnored
41
LimitsSoftwareApproachPolicy = DisallowIllegalMoves
42
 
43
Physical Settings
44
 
45
Pitch = 1,0
46
StepsPerRev = 200
47
GearboxRatio = 1
48
TST101 Stage ID = 0
49
UseDeviceUnits = False
50
Units = MOT_Linear
51
DirSense = MOT_Backwards
52
MinPos = 0,00
53
MaxPos = 300,00
54
MaxAccn = 50,0
55
MaxVel = 50,0
56
MaxContinuousVel = 40,0
57
Factor = 1,0
58
UnitsTxt = mm
59
DisplayDP = -1
60
 
61
Misc. Settings
62
 
63
BacklashDist = 0,05
64
MoveFactor = 30
65
RestFactor = 5
66
 
67
Stepper Motor Settings
68
 
69
Pitch = 1,0
70
StepsPerRev = 200
71
GearboxRatio = 1
72
TST101 Stage ID = 0
73
UseDeviceUnits = False
74
Units = MOT_Linear
75
DirSense = MOT_Backwards
76
MinPos = 0,00
77
MaxPos = 300,00
78
MaxAccn = 50,0
79
MaxVel = 50,0
80
MaxContinuousVel = 40,0
81
Factor = 1,0
82
UnitsTxt = mm
83
DisplayDP = -1
84
 
85
Velocity Profile Settings
86
 
87
BowIndex = 0
88
 
89
Button Settings
90
 
91
ButtonMode = MOT_JogMode
92
ButtonPos1 = 10,0
93
ButtonPos2 = 20,0
94
 
95
Potentiometer Settings
96
 
97
FPControls = True
98
PotZeroWnd = 1
99
PotVel1 = 5,0
100
PotWnd1 = 50
101
PotVel2 = 10,0
102
PotWnd2 = 80
103
PotVel3 = 15,0
104
PotWnd3 = 100
105
PotVel4 = 20,0
106
 
107
 
108
*/
109
 
110
//CVI Add dll path to: Options>Environment>Include Path> C:\Program Files\Thorlabs\Kinesis
111
#include <stdio.h>
112
#include <stdlib.h>
113
#include <stdbool.h>
114
#include <windows.h> 
115
#include <userint.h>
116
#include <utility.h>
117
#include "ThorlabsLTS_ui.h" 
118
 
119
 
120
#include "ThorlabsMotionControlIntegratedStepperMotors.h"
121
 
122
 
123
void LTS_waitMove(int i, int timeout);
124
void LTS_waitHome(int i, int timeout);
125
char serialNumbers[][9] = {"45388004", "45387934","45388034"};  
126
 
127
// Set number of microsteps, found in APT communications protocol. Should be changed to 136533 if using K10CR1
128
int StepsPerMm = 409600;
129
double SingleMove=1; // in mm
130
 
131
int LTSTimerOut=0;
132
int p1_h;
133
 
134
 
135
int CVICALLBACK LTS_Timeout (int panel, int control, int event,
136
                             void *callbackData, int eventData1, int eventData2) {
137
  switch (event) {
138
    case EVENT_TIMER_TICK:
139
      LTSTimerOut = 1;
140
      printf("LTS timeout\n");
141
      break;
142
  }
143
  return 0;
144
}
145
 
146
/*
147
void LTS_Timerast (int signumber) {
148
  LTSTimerOut = 1;
149
  printf("TIMEOUT !!!\n");
150
  SetCtrlAttribute (p1_h, P1_TIMEOUT, ATTR_ENABLED, 0);
151
}
152
*/
153
 
154
void LTS_Tmlnk (int tout) {
155
  LTSTimerOut = 0;
156
  SetCtrlAttribute (p1_h, P1_TIMEOUT, ATTR_INTERVAL, (float)tout/1000.);
157
  SetCtrlAttribute (p1_h, P1_TIMEOUT, ATTR_ENABLED, 1);
158
}
159
 
160
void LTS_Tmulk ( void ) {
161
  SetCtrlAttribute (p1_h, P1_TIMEOUT, ATTR_ENABLED, 0);
162
  LTSTimerOut = 0;
163
}
164
 
165
void LTS_Home(int i,int wait){
166
 
167
//Set up homing parameters. 
168
                MOT_HomingParameters homingParams;
169
                ISC_GetHomingParamsBlock(serialNumbers[i], &homingParams);
170
                homingParams.direction = MOT_Reverse;
171
                ISC_SetHomingParamsBlock(serialNumbers[i], &homingParams);
172
 
173
                //Clear existing messages in the hardware buffer.
174
                ISC_ClearMessageQueue(serialNumbers[i]);
175
 
176
                //Home the stage and wait for the return message before continuing.
177
                ISC_Home(serialNumbers[i]);
178
                printf( "Start Homing...\n");
179
                if (wait) LTS_waitHome(i, wait);
180
                // printf( "Homed...\n");
181
}
182
 
183
int LTS_Init(int i){
184
 
185
  int errorReturn = ISC_Open(serialNumbers[i]);
186
  /*
187
  double stepsPerRev = 200;
188
  double gearBoxRatio = 1;
189
  double pitch = 1;
190
  int err = ISC_SetMotorParamsExt(serialNumbers[i], stepsPerRev, gearBoxRatio, pitch);
191
  err = ISC_GetMotorParamsExt(serialNumbers[i], &stepsPerRev, &gearBoxRatio, &pitch);
192
  // No effect
193
  */
194
  Sleep(1000);
195
  if (errorReturn == 0){
196
          printf( "Device %d (serial %s) Connected... \n",i, serialNumbers[i]);
197
          //Settings are loaded based on Stage Name. The integrated stepper class holds LTS and K10CR1 Information.
198
          ISC_SetLEDswitches(serialNumbers[i], 0); // disable LED 
199
          ISC_StartPolling(serialNumbers[i], 50);
200
          Sleep(1000);
201
  } else {
202
          printf( "Error connecting device %d (%s)\n",i, serialNumbers[i] );  
203
  }
204
  return errorReturn;
205
}
206
 
207
void LTS_Close(int i){
208
//Close the stage
209
        ISC_StopPolling(serialNumbers[i]);
210
        ISC_Close(serialNumbers[i]);
211
        printf( "Device Disconnected...\n");
212
}
213
 
214
void LTS_StopProfiled(int i){
215
  ISC_StopProfiled(serialNumbers[i]);
216
}  
217
 
218
void LTS_MoveAbsolute(int i, double position, int wait){
219
        ISC_SetMoveAbsolutePosition(serialNumbers[i], (position*StepsPerMm));
220
    ISC_MoveAbsolute(serialNumbers[i]);
221
        if (wait) LTS_waitMove(i, wait);
222
 
223
}
224
 
225
void LTS_MoveRelative(int i, double distance, int wait){
226
        ISC_SetMoveRelativeDistance(serialNumbers[i], (distance*StepsPerMm));
227
    ISC_MoveRelativeDistance(serialNumbers[i]);
228
        if (wait) LTS_waitMove(i, wait);
229
}
230
 
231
 
232
double LTS_GetPosition(int i){
233
  int device_unit = ISC_GetPosition(serialNumbers[i]); ;
234
  double real_unit = 1.0*device_unit / StepsPerMm;
235
  //const int unitType = 0 ;// 0 .. distance , 1 .. velocity, 2 .. acceleration
236
  // does not work int err = ISC_GetRealValueFromDeviceUnit(serialNumbers[i], device_unit,&real_unit, unitType);
237
  // printf("err = 0x%x pos %d %f\n", err ,device_unit, real_unit);
238
  return real_unit;
239
}
240
 
241
unsigned int LTS_GetStatus(int i){
242
  return ISC_GetStatusBits(serialNumbers[i]);
243
}  
244
 
245
 
246
int LTS_Enable(int i){
247
  return ISC_EnableChannel(serialNumbers[i]);
248
}
249
 
250
 
251
int LTS_Disable(int i){
252
  return ISC_DisableChannel(serialNumbers[i]);
253
}
254
 
255
 
256
int LTS_GetNumberPositions(int i){
257
  return ISC_GetNumberPositions(serialNumbers[i]);
258
}
259
 
260
int LTS_Open(){
261
 
262
  TLI_BuildDeviceList();
263
  TLI_DeviceInfo info;
264
  int err=0;
265
  for (int i=0;i<3;i++){
266
        TLI_GetDeviceInfo(serialNumbers[i], &info);
267
        Sleep(100);
268
        err = LTS_Init(i);
269
        printf("%s err=%x\n", info.description, err);
270
        if (err) return err;
271
  }
272
  return 0;
273
}
274
 
275
 
276
void LTS_RegisterMessageCallback(int i, void (* functionPointer)()){
277
  ISC_RegisterMessageCallback(serialNumbers[i], functionPointer );
278
}
279
 
280
void LTS_GetRealValueFromDeviceUnit(int i, int device_unit, double *real_unit, int unitType){
281
  ISC_GetRealValueFromDeviceUnit(serialNumbers[i], device_unit, real_unit, unitType);
282
}
283
 
284
void LTS_GetDeviceUnitFromRealValue(int i, double real_unit, int *device_unit, int unitType){
285
  ISC_GetDeviceUnitFromRealValue(serialNumbers[i], real_unit, device_unit, unitType);
286
}
287
//Waits should only be used for Home commands. The home command has a different status return.
288
void LTS_waitHome(int i, int tout)// Waits until a single axis is homed.
289
{
290
        WORD messageType=0;
291
        WORD messageId=0;
292
        DWORD messageData=0;
293
        int condition=0;
294
        LTS_Tmlnk (tout);
295
        do {
296
                while (!ISC_MessageQueueSize(serialNumbers[i])){
297
                  Sleep(250);
298
                  if (LTSTimerOut) break;
299
                }
300
                if (LTSTimerOut){
301
                        printf( "Timeout in axis [%d] pos: %f messageType %d, messageId %d\n",i,LTS_GetPosition(i), messageType, messageId);
302
                        break;
303
                }
304
                ISC_GetNextMessage(serialNumbers[i], &messageType, &messageId, &messageData);
305
                condition = (messageType == 2) && (messageId == 0);
306
 
307
        } while (!condition || !LTSTimerOut);
308
 
309
        LTS_Tmulk();
310
}
311
 
312
void LTS_waitMove(int i, int tout)// Waits until axis is stopped.
313
{
314
        WORD  messageType=0;
315
        WORD  messageId=0;
316
        DWORD messageData=0;
317
        int condition=0;  
318
        LTS_Tmlnk (tout);
319
        do {
320
                while (!ISC_MessageQueueSize(serialNumbers[i])){
321
                  Sleep(250);
322
                  if (LTSTimerOut) break;
323
                }
324
                if (LTSTimerOut){
325
                        printf( "Timeout in axis [%d] pos: %f messageType %d, messageId %d\n",i,LTS_GetPosition(i), messageType, messageId);
326
                        break;
327
                }
328
                ISC_GetNextMessage(serialNumbers[i], &messageType, &messageId, &messageData);
329
                condition = (messageType == 2) && (messageId == 1);
330
 
331
        } while (!condition);      
332
 
333
 
334
        LTS_Tmulk();
335
}
336
//*******************************************************************
337
 
338
#ifdef LTS_MAIN
339
 
340
 
341
int rID, tfID;
342
 
343
#define MAX_THREADS 10
344
static CmtThreadPoolHandle poolHandle = 0;
345
int lid[][14]= {
346
          {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},
347
          {P1_L1_2,P1_L2_2,P1_L3_2,P1_L4_2,P1_L5_2,P1_L6_2,P1_L7_2,P1_L8_2,P1_L9_2,P1_L10_2,P1_L11_2,P1_L12_2,P1_L13_2,P1_L14_2},
348
          {P1_L1_3,P1_L2_3,P1_L3_3,P1_L4_3,P1_L5_3,P1_L6_3,P1_L7_3,P1_L8_3,P1_L9_3,P1_L10_3,P1_L11_3,P1_L12_3,P1_L13_3,P1_L14_3}};
349
int dstat[3]={P1_N2,P1_N2_2,P1_N2_3};
350
int dpos[3]={P1_XP,P1_YP,P1_ZP};
351
int ctrl_c=0;
352
 
353
void LTS_SetStatus(int nid){
354
 
355
        int status=LTS_GetStatus(nid);
356
        SetCtrlVal (p1_h, dstat[nid], status);
357
        SetCtrlVal (p1_h, lid[nid][12], (status & 0x20000000)>0);
358
        SetCtrlVal (p1_h, lid[nid][13], (status & 0x80000000)>0);
359
 
360
        for (int i=0; i<12; i++) {
361
          SetCtrlVal (p1_h, lid[nid][i], status & 1);
362
          status>>=1;
363
        }
364
 
365
}
366
 
367
 
368
 
369
void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle,
370
                               CmtThreadFunctionID functionID, unsigned int event,
371
                               int value, void *callbackData  ) {
372
  SetCtrlVal (p1_h, P1_SCANLED, 0);
373
  ctrl_c=0;
374
  return ;
375
 
376
}
377
 
378
int CVICALLBACK daq(void *functionData) {
379
        ctrl_c =0;
380
        SetCtrlVal (p1_h, P1_SCANLED, 1);
381
        int nx,ny,nz;
382
        GetCtrlVal(p1_h,P1_NX, &nx);
383
        GetCtrlVal(p1_h,P1_NY, &ny);
384
        GetCtrlVal(p1_h,P1_NZ, &nz);
385
 
386
        double dx,dy,dz;
387
        GetCtrlVal(p1_h,P1_DX, &dx);
388
        GetCtrlVal(p1_h,P1_DY, &dy);
389
        GetCtrlVal(p1_h,P1_DZ, &dz);
390
 
391
        double x0,y0,z0;
392
        GetCtrlVal(p1_h,P1_X0, &x0);
393
        GetCtrlVal(p1_h,P1_Y0, &y0);
394
        GetCtrlVal(p1_h,P1_Z0, &z0);
395
 
396
        int cbx,cby,cbz;
397
        int timeout=10000; // timeout in ms 
398
        GetCtrlVal(p1_h,P1_CBX, &cbx);
399
        GetCtrlVal(p1_h,P1_CBY, &cby);
400
        GetCtrlVal(p1_h,P1_CBZ, &cbz);
401
 
402
    if (!cbx) nx=1;
403
        if (!cby) ny=1;
404
        if (!cbz) nz=1;
405
        int  nstep=0;
406
        double totalSteps=nx*ny*nz;
407
        for (int iz=0;iz<nz;iz++){
408
          double zposition= z0+ iz*dz;
409
 
410
          SetCtrlVal(p1_h,P1_IZ, iz);
411
          SetCtrlVal(p1_h,P1_DAQLED, 1);
412
          LTS_MoveAbsolute(2,zposition,timeout);
413
          SetCtrlVal(p1_h,P1_DAQLED, 0);
414
          for (int iy=0;iy<ny;iy++){
415
                double yposition= y0+ iy*dy;
416
 
417
                SetCtrlVal(p1_h,P1_IY, iy);
418
                SetCtrlVal(p1_h,P1_DAQLED, 1);
419
                LTS_MoveAbsolute(1,yposition,timeout);
420
                SetCtrlVal(p1_h,P1_DAQLED, 0);
421
            for (int ix=0;ix<nx;ix++){
422
                   double xposition= x0+ ix*dx;
423
 
424
                   SetCtrlVal(p1_h,P1_IX, ix);
425
                   SetCtrlVal(p1_h,P1_DAQLED, 1);
426
                   LTS_MoveAbsolute(0,xposition,timeout);
427
                   SetCtrlVal(p1_h,P1_DAQLED, 0);
428
 
429
                   for (int k=0;k<3;k++){  
430
             double n2 = LTS_GetPosition(k);
431
             SetCtrlVal (p1_h, dpos[k], n2);
432
                     LTS_SetStatus(k);
433
                   }
434
 
435
                   //printf("[%d]\n",nstep++);
436
                   nstep++;
437
                   double ratio = nstep/totalSteps;
438
                   SetCtrlVal(p1_h,P1_PROGRESS, 100.*ratio);
439
                   Delay(0.1);
440
 
441
                   if (ctrl_c) break;
442
            }
443
                if (ctrl_c) break;
444
          }
445
          if (ctrl_c) break;
446
        }
447
 
448
        return 0;
449
}
450
 
451
 
452
void MessageCB(){
453
        //printf("Message %d\n",d[0]);
454
        return;
455
}
456
 
457
int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
458
                       LPSTR lpszCmdLine, int nCmdShow) {
459
 
460
 
461
  int evcontrl,evpanel,ierr;
462
  double n2;
463
  int comled;
464
  int enabled=0;
465
 
466
 
467
  SetSleepPolicy(VAL_SLEEP_MORE);
468
  CmtNewThreadPool (MAX_THREADS,  &poolHandle);
469
  SetStdioPort (CVI_STDIO_WINDOW);
470
  if (InitCVIRTE (hInstance, 0, 0) == 0) return -1; /* out of memory */
471
 
472
  p1_h = LoadPanel (0,"ThorlabsLTS_ui.uir", P1);
473
  //p1_h = BuildP1 (0);
474
  ierr = DisplayPanel (p1_h);
475
  ierr = SetActiveCtrl (p1_h,P1_B1);
476
  ierr = SetActiveCtrl (p1_h,P1_B3);
477
 
478
  GetCtrlVal (p1_h, P1_COMLED, &comled);
479
  if (!comled) {
480
      //GetCtrlVal (p1_h, P1_PORT, &port);
481
      //if (MIKRO_Open (port)) continue;
482
      LTS_Open();
483
 
484
      SetCtrlVal (p1_h, P1_COMLED, 1);
485
          for (int i=0;i<3;i++) LTS_RegisterMessageCallback(i, &MessageCB );
486
  }
487
 
488
  int scanled=0;
489
  while (1) {
490
    ierr = GetUserEvent (1, &evpanel, &evcontrl);
491
        //printf("GetUserEvent %d %d\n", evpanel, evcontrl);
492
 
493
 
494
        if (evcontrl == P1_STOPSCAN) ctrl_c=1;
495
        GetCtrlVal (p1_h, P1_SCANLED, &scanled);
496
        if (scanled) continue;
497
        if (evcontrl == P1_B1) break;
498
    switch (evcontrl) {
499
      case P1_BL:
500
        LTS_MoveRelative(0,-SingleMove, 0);
501
        break;
502
      case P1_BR:
503
        LTS_MoveRelative(0,+SingleMove, 0);
504
        break;
505
      case P1_BU:
506
        LTS_MoveRelative(1,+SingleMove, 0);
507
        break;
508
      case P1_BD:
509
        LTS_MoveRelative(1,-SingleMove, 0);
510
        break;
511
      case P1_BF:
512
        LTS_MoveRelative(2,+SingleMove, 0);
513
        break;
514
      case P1_BB:
515
        LTS_MoveRelative(2,-SingleMove, 0);
516
        break;
517
      case P1_HO:
518
        LTS_Home(0,0);
519
        break;
520
          case P1_HO_2:
521
        LTS_Home(1,0);
522
        break;
523
          case P1_HO_3:
524
        LTS_Home(2,0);
525
        break;
526
      case P1_GX:
527
        GetCtrlVal (p1_h, P1_XG, &n2);
528
                LTS_MoveAbsolute(0,n2,0);
529
        break;
530
      case P1_GY:
531
        GetCtrlVal (p1_h, P1_YG, &n2);
532
        LTS_MoveAbsolute(1,n2,0);
533
        break;
534
      case P1_GZ:
535
        GetCtrlVal (p1_h, P1_ZG, &n2);
536
        LTS_MoveAbsolute(2,n2,0);
537
        break;
538
      case P1_G:
539
        GetCtrlVal (p1_h, P1_XG, &n2);
540
        LTS_MoveAbsolute(0,n2,0);
541
        GetCtrlVal (p1_h, P1_YG, &n2);
542
        LTS_MoveAbsolute(1,n2,0);
543
        GetCtrlVal (p1_h, P1_ZG, &n2);
544
        LTS_MoveAbsolute(2,n2,0);
545
                break;
546
      case P1_B3: // reset
547
      case P1_B3_2: // reset
548
          case P1_B3_3: // reset
549
                printf("RST Not yet implemented\n");
550
        break;
551
          case P1_STOP:
552
        LTS_StopProfiled(0);
553
        break;
554
          case P1_STOP_2:
555
        LTS_StopProfiled(1);
556
        break;
557
          case P1_STOP_3:
558
        LTS_StopProfiled(2);
559
        break; 
560
      case P1_EN:
561
        LTS_Enable(0);
562
        break;
563
          case P1_EN_2:
564
        LTS_Enable(1);
565
        break;
566
          case P1_EN_3:
567
        LTS_Enable(2);
568
        break;
569
          case P1_DIS:
570
        LTS_Disable(0);
571
        break;
572
          case P1_DIS_2:
573
        LTS_Disable(1);
574
        break;
575
          case P1_DIS_3:
576
        LTS_Disable(2);
577
        break;
578
          case P1_TIMER:
579
                for (int k=0;k<3;k++){  
580
          double position = LTS_GetPosition(k);
581
          SetCtrlVal (p1_h, dpos[k], position);
582
                  LTS_SetStatus(k);
583
                }
584
        break;
585
          case P1_SCAN:
586
 
587
                enabled=1;
588
                const int LTS_Enabled = 0x80000000;
589
                for (int i=0;i<3;i++) if (!(LTS_GetStatus(i)& LTS_Enabled)) enabled =0;
590
                if (enabled){  
591
                  SetCtrlVal(p1_h,P1_DAQLED, 0);
592
                  CmtScheduleThreadPoolFunctionAdv (poolHandle, daq, &rID,
593
                                        DEFAULT_THREAD_PRIORITY,
594
                                        EndOfThread,
595
                                        EVENT_TP_THREAD_FUNCTION_END,
596
                                        NULL, RUN_IN_SCHEDULED_THREAD,
597
                                        &tfID);
598
                } else {
599
                  MessagePopup ("Error", "Enable LTS Stages First");
600
                }        
601
                break;
602
      default:
603
        break;
604
    }
605
    Delay(0.001);
606
 
607
  }
608
 
609
  GetCtrlVal (p1_h, P1_COMLED, &comled);
610
  if (comled) for (int i=0;i<3;i++) LTS_Close (i);
611
 
612
  return 0;
613
}
614
 
615
 
616
 
617
 
618
int CVICALLBACK TimerCB (int panel, int control, int event,
619
                                                 void *callbackData, int eventData1, int eventData2)
620
{
621
        int isrunning;
622
        switch (event)
623
        {
624
                case EVENT_TIMER_TICK:
625
                        GetCtrlVal (p1_h, P1_SCANLED, &isrunning);
626
                        if (!isrunning) QueueUserEvent (1, p1_h, P1_TIMER);
627
                        break;
628
        }
629
        return 0;
630
}
631
 
632
 
633
#else
634
// *************************************
635
 
636
int main(int argc, char ** argv)
637
{
638
        //Sets up simulations. Comment in if running on physical hardware. 
639
        //TLI_InitializeSimulations();
640
 
641
        //Input serial number. Change for your specific device. 
642
        //serials = ["45388004", "45387934","45388034"] 
643
 
644
 
645
        //Build Device List and open device.
646
        TLI_BuildDeviceList();
647
        TLI_DeviceInfo info;
648
        int err=0;
649
        for (int i=0;i<3;i++){
650
          TLI_GetDeviceInfo(serialNumbers[i], &info);
651
          printf("%s\n", info.description);
652
          Sleep(1000);
653
          err |= LTS_Init(i);
654
        }  
655
 
656
 
657
        for (int i=0;i<3;i++){
658
 
659
                //Move the stage and wait for the return message before continuing.
660
                for (int k=0;k<10;k++){
661
                  LTS_MoveAbsolute(i,k);
662
                  printf( "Moving ...\n");
663
                  waitMove(i);
664
                  printf( "Move Complete...\n");
665
                }
666
 
667
 
668
        }
669
 
670
        for (int i=0;i<3;i++){
671
           LTS_Close(i);
672
        }
673
 
674
        //Closes simulations. Comment if running on physical hardware. 
675
        //TLI_UninitializeSimulations();
676
        Delay(10);
677
        return 0;
678
}
679
#endif