Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

#include "uSMC.h"

#ifdef uSMC_MAIN
//#  include "uSMC_ui.h"
#endif /* uSMC_MAIN */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef _WINDOWS
#  include "libusmc.h"
#  include <getopt.h>
#  define Delay(x) usleep((int)(x*1000000))
#else
#  include "USMCDLL.H"
#  include <utility.h>
#  include <ansi_c.h>
/*
#  define ERR(s, c) if(opterr) fprintf(stderr,"%s %c\n",s,c);  
int opterr = 1;
int optind = 1;
int optopt;
char  *optarg;

int getopt(int argc, char **argv, char *opts){
  static int sp = 1;
  int c;
  char *cp;

  if(sp == 1)
    if(optind >= argc ||
       argv[optind][0] != '-' || argv[optind][1] == '\0')
      return(EOF);
    else if(strcmp(argv[optind], "--") == NULL) {
      optind++;
      return(EOF);
    }
  optopt = c = argv[optind][sp];
  if(c == ':' || (cp=strchr(opts, c)) == NULL) {
    ERR(": illegal option -- ", c);
    if(argv[optind][++sp] == '\0') {
      optind++;
      sp = 1;
    }
    return('?');
  }
  if(*++cp == ':') {
    if(argv[optind][sp+1] != '\0')
      optarg = &argv[optind++][sp+1];
    else if(++optind >= argc) {
      ERR(": option requires an argument -- ", c);
      sp = 1;
      return('?');
    } else
      optarg = argv[optind++];
    sp = 1;
  } else {
    if(argv[optind][++sp] == '\0') {
      sp = 1;
      optind++;
    }
    optarg = NULL;
  }
  return(c);
}
*/

#endif /* _WINDOWS */

// Function that prints information about device state to console
void PrintDState(USMC_State *State) {
  printf( "The state is:\n" );
  printf( "- Current Position in microsteps - %d\n", State->CurPos );
  printf( "- Temperature - %.2f\xf8\x43\n", State->Temp );
  printf( "- Step Divisor - %d\n", State->SDivisor);
  printf( "- Loft State - %s\n", State->Loft?"Indefinite":"Fixed" );
  printf( "- Power - %s\n", State->Power?(State->FullPower?"Full":"Half"):"Off" );
  if(State->RUN)
    printf( "- Step Motor is Running in %s Direction %s\n",
            State->CW_CCW?"CCW":"CW", ((State->SDivisor==1) && State->FullSpeed)?"at Full Speed":"" );
  else
    printf( "- Step Motor is Not Running\n" );
  printf( "- Device %s\n", State->AReset?"is After Reset":"Position Already Set" );
  printf( "- Input Synchronization Logical Pin State - %s\n", State->SyncIN?"TRUE":"FALSE" );
  printf( "- Output Synchronization Logical Pin State - %s\n", State->SyncOUT?"TRUE":"FALSE" );
  printf( "- Rotary Transducer Logical Pin State - %s\n", State->RotTr?"TRUE":"FALSE" );
  printf( "- Rotary Transducer Error Flag - %s\n", State->RotTrErr?"Error":"Clear" );
  printf( "- Emergency Disable Button - %s\n", State->EmReset?"Pushed":"Unpushed" );
  printf( "- Trailer 1 Press State - %s\n", State->Trailer1?"Pushed":"Unpushed" );
  printf( "- Trailer 2 Press State - %s\n", State->Trailer2?"Pushed":"Unpushed" );
  if( State->Voltage == 0.0f )
    printf( "- Input Voltage - Low\n");
  else
    printf( "- Input Voltage - %.1fV\n", State->Voltage);
}

// Function that prints information about device start parameters to console
void PrintDStartParameters(int DPos, float Speed, const USMC_StartParameters *SP ) {
  printf( "Destination position - %d\n", DPos);
  printf( "Speed - %.2ftacts/s\n", Speed );
  printf( "Steps Divisor - %d\n", SP->SDivisor );
  if(SP->SDivisor == 1) {
    printf( "Slow start/stop mode - %s\n", SP->SlStart?"Enabled":"Disabled" );
  } else if(SP->LoftEn) {
    printf( "Automatic backlash operation - Enabled\n" );
    printf( "Automatic backlash operation direction - %s\n", SP->DefDir?"CCW":"CW" );
    printf( "Force automatic backlash operation - %s\n", SP->ForceLoft?"TRUE":"FALSE" );
  } else {
    printf( "Automatic backlash operation - Disabled\n" );
  }
  if(SP->WSyncIN)
    printf( "Controller will wait for input synchronization signal to start\n" );
  else
    printf( "Input synchronization signal ignored \n" );
  printf( "Output synchronization counter will %sbe reset\n", SP->SyncOUTR?"":"not " );
}

// Function that prints information about device parameters to console
void PrintDParameters(USMC_Parameters *Parameters) {
  printf( "The parameters are:\n" );
  printf( "Full acceleration time - %.0f ms\n", (double) Parameters->AccelT );
  printf( "Full deceleration time - %.0f ms\n", (double) Parameters->DecelT );
  printf( "Power reduction timeout - %.0f ms\n", (double) Parameters->PTimeout );
  printf( "Button speedup timeout 1 - %.0f ms\n", (double) Parameters->BTimeout1 );
  printf( "Button speed after timeout 1 - %.2f steps/s\n", (double) Parameters->BTO1P );
  printf( "Button speedup timeout 2 - %.0f ms\n", (double) Parameters->BTimeout2 );
  printf( "Button speed after timeout 2 - %.2f steps/s\n", (double) Parameters->BTO2P );
  printf( "Button speedup timeout 3 - %.0f ms\n", (double) Parameters->BTimeout3 );
  printf( "Button speed after timeout 3 - %.2f steps/s\n", (double) Parameters->BTO3P );
  printf( "Button speedup timeout 4 - %.0f ms\n", (double) Parameters->BTimeout4 );
  printf( "Button speed after timeout 4 - %.2f steps/s\n", (double) Parameters->BTO4P );
  printf( "Button reset timeout - %.0f ms\n", (double) Parameters->BTimeoutR );
  printf( "Button reset operation speed - %.2f steps/s\n", (double) Parameters->MinP );
  printf( "Backlash operation distance - %d steps\n", (int)Parameters->MaxLoft );
  printf( "Revolution distance - %d steps\n", (int)Parameters->RTDelta );
  printf( "Minimal revolution distance error - %d steps\n", (int)Parameters->RTMinError );
  printf( "Power off temperature - %.2f\xf8\x43\n", (double)Parameters->MaxTemp );
  printf( "Duration of the output synchronization pulse - ");
  if(Parameters->SynOUTP == 0)
    printf( "minimal\n");
  else
    printf( "%.1f * [Tact Period]\n", Parameters->SynOUTP - 0.5);
  printf( "Speed of the last phase of the backlash operation - ");
  if(Parameters->LoftPeriod == 0.0f)
    printf( "normal\n" );
  else
    printf( "%.2f steps/s\n", (double)Parameters->LoftPeriod );
  printf( "<Angular Encoder Step> Equals <Angular Step Motor Step>/<%.2f>\n", Parameters->EncMult);
}

// Function that prints information about device "mode" parameters to console
void PrintDMode(USMC_Mode *Mode) {
  printf( "Mode parameters:\n" );
  printf( "Buttons - ");
  if(Mode->PMode) {
    printf( "Disabled\n" );
  } else {
    printf( "Enabled\nButton 1 TRUE state - %s\n", Mode->Butt1T?"+3/+5 V":"0 V(GND)" );
    printf( "Button 2 TRUE state - %s\n", Mode->Butt2T?"+3/+5 V":"0 V(GND)" );
  }
  printf( "Current reduction regime - %s\n", Mode->PReg?"Used":"Not Used" );

  if(Mode->ResetD)
    printf( "Power - %s\n", Mode->EMReset?"Emerjency Off":"Off" );
  else
    printf( "Power - On\n" );
  if(Mode->Tr1En || Mode->Tr2En)
    printf( "Trailers are - %s\n", Mode->TrSwap?"Swapped":"Direct" );

  printf( "Trailer 1 - ");
  if(Mode->Tr1En)
    printf( "Enabled\nTrailer 1 TRUE state - %s\n", Mode->Tr1T?"+3/+5 V":"0 V(GND)" );
  else
    printf( "Disabled\n");
  printf( "Trailer 2 - ");
  if(Mode->Tr2En)
    printf( "Enabled\nTrailer 2 TRUE state - %s\n", Mode->Tr2T?"+3/+5 V":"0 V(GND)" );
  else
    printf( "Disabled\n");

  if(Mode->EncoderEn) {
    printf( "Encoder - Enabled\n");
    printf( "Encoder Position Counter is %s\n", Mode->EncoderInv?"Inverted":"Direct");
    printf( "Rotary Transducer and Input Syncronisation are\n"
            " Disabled Because of Encoder\n");
  } else {
    printf( "Encoder - Disabled\n");
    printf( "Rotary Transducer - ");
    if(Mode->RotTeEn) {
      printf( "Enabled\nRotary Transducer TRUE state - %s\n", Mode->RotTrT?"+3/+5 V":"0 V(GND)" );
      printf( "Rotary Transducer Operation - %s\n", Mode->RotTrOp?"Stop on error":"Check and ignore error" );
      printf( "Reset Rotary Transducer Check Positions - %s\n", Mode->ResetRT?"Initiated":"No, why?");
    } else {
      printf("Disabled\n");
    }
    printf("Synchronization input mode:\n");
    if(Mode->SyncINOp)
      printf("Step motor will move one time to the destination position\n");
    else
      printf("Step motor will move multiple times by [destination position]\n");
  }
  printf( "Output Syncronization - ");
  if(Mode->SyncOUTEn) {
    printf( "Enabled\nReset Output Synchronization Counter - %s\n", Mode->SyncOUTR?"Initiated":"No, why?" );
    printf( "Number of steps after which synchronization output sygnal occures - %u\n", Mode->SyncCount );
  } else {
    printf("Disabled\n");
  }
  printf("Synchronization Output is ");
  if(Mode->SyncInvert)
    printf("INVERTED\n");
  else
    printf("NORMAL\n");
}

// Function that prints Encoder state information
void PrintEncState(USMC_EncoderState *EnState, USMC_Parameters *up) {
/*
|Type    |Name       |Description
|--------|-----------|-------------------------------------------------------------------------
|Int     |EncoderPos |Current position measured by encoder
|Int     |ECurPos    |Current position (in Encoder Steps) - Synchronized with request call
|--------|-----------|-------------------------------------------------------------------------
*/

  printf( "The encoder state is:\n" );
  printf( "- Current Position in microsteps - %.2f\n", EnState->ECurPos/up->EncMult );
  printf( "- Encoder Position in microsteps - %.2f\n\n", EnState->EncoderPos/up->EncMult );
  printf( "- Current Position in \"Half of Encoder Step\"s - %d\n", EnState->ECurPos );
  printf( "- Encoder Position in \"Half of Encoder Step\"s - %d\n", EnState->EncoderPos );
}

// Function that prints last error information
void PrintError(void) {
  char er[101];
  USMC_GetLastErr(er,100);
  er[100] = '\0';
  printf("\n%s",er);
}

////////////////////////////////////////////////////////////////////////

static int ierr;
static float Speed=15000.0f;

#define MAXNODES 4
static USMC_Devices         Devices;
static USMC_StartParameters DStartPar[MAXNODES];
static USMC_Parameters      DPar[MAXNODES];
static USMC_State           DState[MAXNODES];
static USMC_EncoderState    DEncState[MAXNODES];
static USMC_Mode            DMode[MAXNODES];

#define ERRLEN 128
static char errstr[ERRLEN];

void uSMC_PrintDevices(void) {
  /*
  |Type    |Name       |Description
  |--------|-----------|-------------------------------------------------------------------------
  |DWORD   |NOD        |Number of devices connected to computer
  |char ** |Serial     |Array of pointers to 16–byte ASCII strings of length – NOD
  |char ** |Version    |Array of pointers to 4–byte ASCII strings of length – NOD
  |--------|-----------|-------------------------------------------------------------------------
  */

  int i;
  for (i=0; i<Devices.NOD; i++) {
    printf("Device - %d,\tSerial Number - %.16s,\tVersion - %.4s\n",i+1,Devices.Serial[i],Devices.Version[i]);
  }
}

int uSMC_SetParameters(int node, int stageType) {
  /*
  |Type    |Name       |Description
  |--------|-----------|-------------------------------------------------------------------------
  |float   |AccelT     |Acceleration time (in ms)
  |float   |DecelT     |Deceleration time (in ms)
  |float   |PTimeout   |Time (in ms) after which current will be reduced to 60% of normal
  |float   |BTimeout1  |Time (in ms) after which speed of step motor rotation will be equal to the one specified at
  |        |           |BTO1P field in this structure
  |float   |BTimeout2  |Time (in ms) after which speed of step motor rotation will be equal to the one specified at
  |        |           |BTO2P field in this structure
  |float   |BTimeout3  |Time (in ms) after which speed of step motor rotation will be equal to the one specified at
  |        |           |BTO3P field in this structure
  |float   |BTimeout4  |Time (in ms) after which speed of step motor rotation will be equal to the one specified at
  |        |           |BTO4P field in this structure
  |float   |BTimeoutR  |Time (in ms) after which reset command will be performed (see 5.4.7 at page 53)
  |float   |BTimeoutD  |This field is reserved for future use
  |float   |MinP       |Speed (steps/sec) while performing reset operation
  |float   |BTO1P      |Speed (steps/sec) after BTIMEOUT1 time has passed (see 5.4.8 at page 54)
  |float   |BTO2P      |Speed (steps/sec) after BTIMEOUT2 time has passed (see 5.4.8 at page 54)
  |float   |BTO3P      |Speed (steps/sec) after BTIMEOUT3 time has passed (see 5.4.8 at page 54)
  |float   |BTO4P      |Speed (steps/sec) after BTIMEOUT4 time has passed (see 5.4.8 at page 54)
  |WORD    |MaxLoft    |Value in full steps that will be used performing backlash operation
  |DWORD   |StartPos   |Current Position saved to FLASH. Refer to test.cpp for implementing this functionality.
  |        |           |Should be set to 0 for correct reloading of current position in SMCVieW program
  |WORD    |RTDelta    |Revolution distance – number of full steps per one full revolution
  |WORD    |RTMinError |Number of full steps missed to raise the error flag
  |float   |MaxTemp    |Maximum allowed temperature (centigrade degrees)
  |BYTE    |SynOUTP    |Duration of the output synchronization pulse ( see 5.4.13 at page 58)
  |float   |LoftPeriod |Speed (steps/sec) of the last phase of the backlash operation
  |float   |EncMult    |Encoder step multiplier. Should be <Encoder Steps per Revolution> / <SM Steps per Revolution>
  |        |           |and should be integer multiplied by 0.25
  |--------|-----------|-------------------------------------------------------------------------
  */

  int saveToFlash;
  int Dev;

  saveToFlash=0;
  Dev=node-1;
  if (ierr=USMC_GetParameters(Dev,&DPar[Dev])) return ierr;
  switch (stageType) {
    case -1:
      saveToFlash=1;
//      DPar[Dev].StartPos = 0;
    case 1:
      // Linear stage
      DPar[Dev].AccelT = 200.0f;
      DPar[Dev].DecelT = 200.0f;
      DPar[Dev].PTimeout = 1.0f;
      DPar[Dev].BTimeout1 = 500.0f;
      DPar[Dev].BTimeout2 = 500.0f;
      DPar[Dev].BTimeout3 = 500.0f;
      DPar[Dev].BTimeout4 = 500.0f;
      DPar[Dev].BTimeoutR = 500.0f;
      DPar[Dev].MinP = 60.0f;
      DPar[Dev].BTO1P = 10.0f;
      DPar[Dev].BTO2P = 20.0f;
      DPar[Dev].BTO3P = 30.0f;
      DPar[Dev].BTO4P = 60.0f;
      DPar[Dev].MaxLoft = 32;
      DPar[Dev].RTDelta = 200;
      DPar[Dev].RTMinError = 15;
      DPar[Dev].MaxTemp = 70.0f;
      DPar[Dev].SynOUTP = 1;
      DPar[Dev].LoftPeriod = 50.0f;
      DPar[Dev].EncMult = 1.0f;
      break;
    case -2:
      saveToFlash=1;
    case 2:
// Rotation stage
      DPar[Dev].MaxTemp = 70.0f;
      DPar[Dev].AccelT = 200.0f;
      DPar[Dev].DecelT = 200.0f;
      DPar[Dev].BTimeout1 = 500.0f;
      DPar[Dev].BTimeout2 = 500.0f;
      DPar[Dev].BTimeout3 = 500.0f;
      DPar[Dev].BTimeout4 = 500.0f;
      DPar[Dev].BTO1P = 100.0f;
      DPar[Dev].BTO2P = 200.0f;
      DPar[Dev].BTO3P = 300.0f;
      DPar[Dev].BTO4P = 600.0f;
      DPar[Dev].MinP = 500.0f;
      DPar[Dev].BTimeoutR = 500.0f;
      DPar[Dev].LoftPeriod = 500.0f;
      DPar[Dev].RTDelta = 200;
      DPar[Dev].RTMinError = 15;
      DPar[Dev].EncMult = 2.5f;
      DPar[Dev].MaxLoft = 32;
      DPar[Dev].PTimeout = 100.0f;
      DPar[Dev].SynOUTP = 1;
      break;
  }
  if (ierr=USMC_SetParameters(Dev,&DPar[Dev])) return ierr;
  if (saveToFlash) {
    if(ierr=USMC_SaveParametersToFlash(Dev)) return ierr;
    PrintDParameters(&DPar[Dev]);
    printf("\nThese Parameters were Saved to Flash");
  }
  return FALSE;
}

int uSMC_RevertStartPosition(int node) {
  int Dev;

  Dev=node-1;
  if (ierr=USMC_GetParameters(Dev,&DPar[Dev])) return ierr;
  DPar[Dev].StartPos = 0;
  if (ierr=USMC_SetParameters(Dev,&DPar[Dev])) return ierr;
  if(ierr=USMC_SaveParametersToFlash(Dev)) return ierr;
  printf("\nStart Position is Reset to 0\n");
  return FALSE;
}

int _VI_FUNC uSMC_PowerOn (int node) {
  int Dev;

  Dev=node-1;
  if (ierr=USMC_GetMode(Dev,&DMode[Dev])) return ierr;
  DMode[Dev].ResetD = FALSE;
  if (ierr=USMC_SetMode(Dev,&DMode[Dev])) return ierr;
  return FALSE;
}

int uSMC_PowerOffSave(int node,int saveToFlash) {
  int Dev=node-1;
  if (saveToFlash) {
    if (ierr=USMC_GetParameters(Dev,&DPar[Dev])) return ierr;
  }
  if (ierr=USMC_GetMode(Dev,&DMode[Dev])) return ierr;
  DMode[Dev].ResetD = TRUE;
  if (ierr=USMC_SetMode(Dev,&DMode[Dev])) return ierr;
  do {
    Sleep(50);
    if (ierr=USMC_GetState(Dev,&DState[Dev])) return ierr;
  } while(DState[Dev].Power == TRUE);
  if (saveToFlash) {
    DPar[Dev].StartPos = DState[Dev].CurPos;
    if (ierr=USMC_SetParameters(Dev,&DPar[Dev])) return ierr;
    if (ierr=USMC_SaveParametersToFlash(Dev)) return ierr;
  }
  return FALSE;
}

int _VI_FUNC uSMC_PowerOff (int node) {
  if (ierr=uSMC_PowerOffSave(node,0)) return ierr;
  return FALSE;
}

int _VI_FUNC uSMC_Open (void) {
  int i;
  if (ierr=USMC_Init(&Devices)) return ierr;
  uSMC_PrintDevices();
  return FALSE;
}

int _VI_FUNC uSMC_FindSerial (char serial[])
{
  int i;
  for (i=0; i<Devices.NOD; i++)
    if (!strncmp (Devices.Serial[i], serial, 16)) return i;
  return -1;
}

int _VI_FUNC uSMC_Reset (int node) {
  return FALSE;
}

int _VI_FUNC uSMC_Init (int node, int type) {
  /*
  |Type    |Name       |Masked|Saved|Description
  |--------|-----------|------|-----|------------------------------------------------------------
  |BOOL    |PMode      |–     |YES  |Turn off buttons (TRUE - buttons disabled)
  |BOOL    |PReg       |–     |YES  |Current reduction regime (TRUE - regime is on)
  |BOOL    |ResetD     |–     |YES  |Turn power off and make a whole step (TRUE - apply)
  |BOOL    |EMReset    |–     |–    |Quick power off (see 5.4.6 at page 53)
  |BOOL    |Tr1T       |–     |YES  |Limit switch 1 TRUE state (TRUE : +3/+5?; FALSE : 0?)
  |BOOL    |Tr2T       |–     |YES  |Limit switch 2 TRUE state (TRUE : +3/+5?; FALSE : 0?)
  |BOOL    |RotTrT     |–     |YES  |Rotary Transducer TRUE state (TRUE : +3/+5?; FALSE : 0?)
  |BOOL    |TrSwap     |–     |YES  |If TRUE, Limit switches are treated to be swapped
  |BOOL    |Tr1En      |–     |YES  |If TRUE Limit switch 1 Operation Enabled
  |BOOL    |Tr2En      |–     |YES  |If TRUE Limit switch 2 Operation Enabled
  |BOOL    |RotTeEn    |–     |YES  |If TRUE Rotary Transducer Operation Enabled
  |BOOL    |RotTrOp    |–     |YES  |Rotary Transducer Operation Select (stop on error if TRUE)
  |BOOL    |Butt1T     |–     |YES  |Button 1 TRUE state (TRUE : +3/+5?; FALSE : 0?)
  |BOOL    |Butt2T     |–     |YES  |Button 2 TRUE state (TRUE : +3/+5?; FALSE : 0?)
  |BOOL    |ResetRT    |YES   |–    |Reset Rotary Transducer Check Positions (need one full revolution
  |        |           |      |     |before it can detect error)
  |BOOL    |SyncOUTEn  |–     |YES  |If TRUE output synchronization enabled
  |BOOL    |SyncOUTR   |YES   |–    |If TRUE output synchronization counter will be reset
  |BOOL    |SyncINOp   |–     |YES  |Synchronization input mode:
  |        |           |      |     |- TRUE - Step motor will move one time to the DestPos
  |        |           |      |     |- FALSE - Step motor will move multiple times by DestPos microsteps as distance
  |DWORD   |SyncCount  |–     |YES  |Number of steps after which synchronization output signal occurs
  |BOOL    |SyncInvert |–     |YES  |Set this bit to TRUE to invert output synchronization polarity
  |BOOL    |EncoderEn  |–     |YES  |Enable Encoder on pins {SYNCIN,ROTTR} - disables Synchronization input and Rotary Transducer
  |BOOL    |EncoderInv |–     |YES  |Invert Encoder Counter Direction BOOL ResBEnc YES – Reset <EncoderPos> and <ECurPos> to 0
  |BOOL    |ResEnc     |YES   |–    |Reset <ECurPos> to <EncoderPos>
  |--------|-----------|-------------------------------------------------------------------------
  Masked –> These Boolean values will be automatically cleared by USMC_GetMode (to FALSE)
  */

  int Dev;

  Dev=node-1;
//  if (ierr=uSMC_PowerOff(node)) return ierr;
  if (ierr=uSMC_SetParameters(node,type)) return ierr;
  switch (type) {
    case -1:
    case 1:
      if (ierr=USMC_GetMode(Dev,&DMode[Dev])) return ierr;
      DMode[Dev].Tr1T = FALSE;
      DMode[Dev].Tr2T = FALSE;
      DMode[Dev].Tr1En = TRUE;
      DMode[Dev].Tr2En = TRUE;
      DMode[Dev].TrSwap = FALSE;
      DMode[Dev].EncoderEn = FALSE;
      if (ierr=USMC_SetMode(Dev,&DMode[Dev])) return ierr;
      break;
  }
  if (ierr=uSMC_PowerOn(node)) return ierr;
  return FALSE;
}

int _VI_FUNC uSMC_ReferenceMove (int node) {
  int Dev;
  float tmpSpeed;

  Dev=node-1;
  tmpSpeed=Speed;
  if (ierr=USMC_GetMode(Dev,&DMode[Dev])) return ierr;
  DMode[Dev].Tr1T = FALSE;
  DMode[Dev].Tr2T = FALSE;
  DMode[Dev].Tr1En = TRUE;
  DMode[Dev].Tr2En = TRUE;
  DMode[Dev].TrSwap = FALSE;
  DMode[Dev].EncoderEn = FALSE;
  if (ierr=USMC_SetMode(Dev,&DMode[Dev])) return ierr;
  Speed=10000.0f;
  if (ierr=USMC_SetCurrentPosition(Dev,0)) return ierr;
  if (ierr=uSMC_MoveTo(node,-500000)) return ierr;
  if (ierr=uSMC_MoveFor(node,5000)) return ierr;
  Speed=500.0f;
  if (ierr=uSMC_MoveTo(node,-500000)) return ierr;
  Speed=tmpSpeed;
  if (ierr=uSMC_MoveFor(node,5000)) return ierr;
  if (ierr=USMC_SetCurrentPosition(Dev,0)) return ierr;
  return FALSE;
}

int _VI_FUNC uSMC_MoveFor (int node, int dist) {
  int CurPos;
  if (ierr=uSMC_GetPosition(node,&CurPos)) return ierr;
  if (ierr=uSMC_MoveTo(node,CurPos+dist)) return ierr;
  return FALSE;
}

int _VI_FUNC uSMC_MoveTo (int node, int dest) {
  /*
  |Type    |Name       |Description
  |--------|-----------|-------------------------------------------------------------------------
  |BYTE    |SDivisor   |Step is divided by this factor (1,2,4,8)
  |BOOL    |DefDir     |Direction for backlash operation (relative) (see 5.4.15 at page 60)
  |BOOL    |LoftEn     |Enable automatic backlash operation (works if slow start/stop mode is off)
  |BOOL    |SlStart    |If TRUE slow start/stop mode enabled
  |BOOL    |WSyncIN    |If TRUE controller will wait for input synchronization signal to start
  |BOOL    |SyncOUTR   |If TRUE output synchronization counter will be reset
  |BOOL    |ForceLoft  |If TRUE and destination position is equal to the current position
  |        |           |backlash operation will be performed
  |--------|-----------|-------------------------------------------------------------------------
  */

  int Dev;
  time_t tcur,tprev;

  Dev=node-1;
  if (ierr=USMC_GetStartParameters(Dev,&DStartPar[Dev])) return ierr;
  DStartPar[Dev].SDivisor=8;
  DStartPar[Dev].SlStart=TRUE;
  DStartPar[Dev].LoftEn=FALSE;
  DStartPar[Dev].WSyncIN=FALSE;
  if (ierr=USMC_Start(Dev,dest,&Speed,&DStartPar[Dev])) return ierr;
  tprev=time(NULL)+1;
  do {
    Delay(0.01);
    if (ierr=USMC_GetState(Dev,&DState[Dev])) return ierr;
    tcur=time(NULL);
    if (tcur > tprev) {
      printf("%d CurPos %d L%d R%d Rot%d %s %s\n",node,
             DState[Dev].CurPos,DState[Dev].Trailer1,DState[Dev].Trailer2, DState[Dev].RotTr,
             DState[Dev].RUN?"Run":"Stopped",DState[Dev].Power?"On":"Off" );
      tprev= tcur;
    }
  } while (DState[Dev].RUN);
  return FALSE;
}

int _VI_FUNC uSMC_GetPosition (int node, int *pos) {
  /*
  |Type    |Name       |Description
  |--------|-----------|-------------------------------------------------------------------------
  |int     |CurPos
  |float   |Temp       |Current temperature of the power driver
  |BYTE    |SDivisor   |Step is divided by this factor
  |BOOL    |Loft       |Indicates backlash status
  |BOOL    |FullPower  |Full power if TRUE
  |BOOL    |CW_CCW     |Current direction of rotation (relatively to some direction – dependent on
  |        |           |step motor circuits connection and on its construction)
  |BOOL    |Power      |If TRUE then Step Motor power is ON
  |BOOL    |FullSpeed  |If TRUE then full speed. Valid in "Slow Start" mode only
  |BOOL    |AReset     |TRUE After Device reset, FALSE after "Set Position"
  |BOOL    |RUN        |TRUE if step motor is rotating
  |BOOL    |SyncIN     |Logical state directly from input synchronization PIN (pulses treated as positive)
  |BOOL    |SyncOUT    |Logical state directly from output synchronization PIN (pulses are positive)
  |BOOL    |RotTr      |Indicates current rotary transducer logical press state
  |BOOL    |RotTrErr   |Indicates rotary transducer error flag (reset by USMC_SetMode function with ResetRT bit – TRUE)
  |BOOL    |EmReset    |Indicates state of emergency disable button (TRUE – Step motor power off)
  |BOOL    |Trailer1   |Indicates Limit switch 1 logical press state
  |BOOL    |Trailer2   |Indicates Limit switch 2 logical press state
  |float   |Voltage    |Power supply voltage (Volts)
  |--------|-----------|-------------------------------------------------------------------------
  */

  int Dev;

  Dev=node-1;
  if (ierr=USMC_GetState(Dev,&DState[Dev])) return ierr;
  *pos=DState[Dev].CurPos;
  return FALSE;
}

void _VI_FUNC uSMC_Close (void) {
  USMC_Close();
}

//******************************

#ifdef uSMC_MAIN
#define uSMC_SERIAL_X "0000000000004925"
#define uSMC_SERIAL_Y "0000000000006030"
#define uSMC_SERIAL_Z "0000000000002894"
#  ifdef _WINDOWS
int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpszCmdLine, int nCmdShow) {
 
  const char serials[3][16]={uSMC_SERIAL_X,uSMC_SERIAL_Y,uSMC_SERIAL_Z};

  int i;
  int DestPos[3],CurPos[3];
  int nodes[3];
//  float Speed=2000.0f;

  if (InitCVIRTE (hInstance, 0, 0) == 0) return -1; /* out of memory */

  uSMC_Open();
  for (i=0;i<3;i++) {
    nodes[i]=uSMC_FindSerial(serials[i])+1;
    uSMC_Init(nodes[i],1);
    uSMC_GetPosition(nodes[i],&CurPos[i]);
  }
  printf("nodes x,y,z: %2d, %2d, %2d\n",nodes[0],nodes[1],nodes[2]);
  printf("Current position: %2d, %2d, %2d\n",CurPos[0],CurPos[1],CurPos[2]);
//  uSMC_ReferenceMove(node);

  getchar();
  DestPos[0]=32000;
  DestPos[1]=125000;
  DestPos[2]=300000;
  for (i=0;i<3;i++) {
    uSMC_MoveTo(nodes[i],DestPos[i]);
    uSMC_GetPosition(nodes[i],&CurPos[i]);
  }
  printf("Current position: %2d, %2d, %2d\n",CurPos[0],CurPos[1],CurPos[2]);
   
  for (i=0;i<3;i++) uSMC_PowerOff(nodes[i]);
  getchar();
  uSMC_Close();
  return 0;
}

#  else

int main (int argc, char **argv) {
  int i,j,k;
  int node=0,opt,value=0;
  int EOldPos=-1;
  if ( USMC_Init ( &devices ) ) abort();


  while ((opt = getopt(argc, argv, "i:av:f:l:udn:m:s:v:g:h:r:p:")) != -1) {
    switch (opt) {
      case 'i':
        usmc_Init (node, atoi(optarg));

        break;
      case 'a':
        printdevices(devices);
        for (i=0; i<devices.NOD; i++) {

          USMC_GetState(i,&DState[i]);
          printf("%d CurPos %d L%d R%d %s %s\t",i,
                 DState[i].CurPos,DState[i].Trailer1,DState[i].Trailer2,
                 DState[i].RUN?"Run":"Stopped",DState[i].Power?"On":"Off" );
          USMC_GetParameters(i,&DPar[i]);
          USMC_GetEncoderState(i,&DEncState[i]);
          printf("node %d ECurPos 0x%0x %f EncoderPos =0x%04x %f\n",i,
                 DEncState[i].ECurPos, (((DEncState[i].ECurPos)>>5)&0x8FFFFF)/DPar[i].EncMult,
                 DEncState[i].EncoderPos,((DEncState[i].EncoderPos >> 5)&0x8FFFFF)/DPar[i].EncMult);

        }
        break;

      case 'l':
        printf("usmc_MoveTo Loop\n");
        for (i=0; i<5; i++) {
          int xpos=i*1000+10000;
          usmc_MoveTo (1, xpos);
          for (j=0; j<5; j++) {
            int ypos=j*1000+10000;
            usmc_MoveTo (2, ypos);
            for (k=0; k<50; k++) {
              int zpos=k*1000+10000;
              usmc_MoveTo (3, zpos);
              printf("x=%d y=%d z=%d\n",xpos,ypos,zpos);
              Delay(atof(optarg));

            }
          }
        }
        break;
      case 'n':
        node = atoi(optarg);
        break;
      case 's':
        usmc_speed = atoi(optarg);
        break;
      case 'p':
        usmc_PowerOnOff(node,atoi(optarg));
        break;
      case 'm':
        usmc_MoveTo (node, atoi(optarg));
        printf("usmc_MoveTo node=%d pos=%d \n",node,atoi(optarg));

        break;
      case 'v':
        value=atoi(optarg);
        break;
        /*
        case 'f':
        MIKRO_Set (node,optarg,value);
        printf("MIKRO_Set node %d  cmd=%s val=%d\n",node,optarg, value);
        break;
        case 'g':
        MIKRO_Get (node,optarg,&i);
        printf("MIKRO_Get node %d  cmd=%s val=%d\n",node,optarg, i);

        break;


        */


      case 'r':
        printf("usmc_Reset node=%d mode=%d\n",node, atoi(optarg));
        usmc_Reset (node, atoi(optarg));
        break;

      case 'h':
        printf("usmc_ReferenceMove node=%d mode=%d\n",node, atoi(optarg));
        usmc_ReferenceMove (node, atoi(optarg));
        break;

      case 'u':
        usmc_RelMove(node, 1000);
        break;
      case 'd':
        usmc_RelMove(node, -1000);
        break;


      default: /* '?' */
        help();

        break;
    }
  }
  if (argc==1) help();


  USMC_Close ();
  return 0;
}

#  endif /* _WINDOWS */
#endif /* _uSMC_MAIN */