/*
8mru
sudo ./usmc_ctrl -n 0 -p 1 -s 1000 -h 0 -p 0
sudo ./usmc_ctrl -n 0 -p 1 -s 1000 -m +1210 -p 0
sudo ./usmc_ctrl -n 0 -p 1 -s 1000 -m -1210 -p 0
usmc_ctrl -a
usmc_ctrl -n 0 -i
usmc_ctrl -n 0 -p 1 -s 5000 -m 10000 - p 0
usmc_ctrl -n 0 -p 1 -h -p 0
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef _WINDOWS
#include "libusmc.h"
#include <getopt.h>
#include <time.h>
void sleep_us(unsigned long microseconds)
{
struct timespec ts;
ts.tv_sec = microseconds / 1000000; // whole seconds
ts.tv_nsec = (microseconds % 1000000) * 1000; // remainder, in nanoseconds
nanosleep(&ts, NULL);
}
#define Delay(x) sleep_us((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
#define MAXNODES 4
USMC_Devices devices;
USMC_StartParameters parstart[MAXNODES];
USMC_Parameters parameters[MAXNODES];
USMC_State parstate[MAXNODES];
USMC_EncoderState parencstate[MAXNODES];
#define ERRLEN 128
char errstr[ERRLEN];
// Function that prints information about device parameters to console
void print_parameters(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)
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)
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 start parameters to console
void print_start_params ( const USMC_StartParameters sp ){
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 state to console
void print_state(USMC_State *State)
{
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
);
}
void print_enc_state ( USMC_EncoderState enc_state )
{
printf ( "# The encoder state is:\n" );
printf ( "# Current Position in \"Half of Encoder Step\"s - %d\n", enc_state.
ECurPos );
printf ( "# Encoder Position in \"Half of Encoder Step\"s - %d\n", enc_state.
EncoderPos );
}
// Function that prints information about connected devices to console
void printdevices(USMC_Devices DVS)
{
DWORD i;
for( i = 0; i < DVS.NOD; i++)
{
printf("Device - %d,\tSerial Number - %.16s,\tVersion - %.4s\n",i
,DVS.
Serial[i
],DVS.
Version[i
]);
}
}
void usmc_SwapSwitches ( int cur_dev, int swap ){
USMC_Mode mode;
if ( USMC_GetMode ( cur_dev, &mode ) ) return;
mode.TrSwap = swap;
if ( USMC_SetMode ( cur_dev, &mode ) ) return;
printf ( "Now, Switches of %d are %s swapped.\n", cur_dev
, mode.
TrSwap ? "" : "not" );
}
void usmc_EnableSwitches ( int cur_dev, int enable ){
USMC_Mode mode;
if ( USMC_GetMode ( cur_dev, &mode ) ) return;
mode.Tr1En = enable;
mode.Tr2En = enable;
if ( USMC_SetMode ( cur_dev, &mode ) ) return;
printf ( "Now, Switches of %d are %s.\n", cur_dev
, mode.
Tr1En ? "enabled" : "disabled" );
}
int usmc_Set_Parameters(int Dev, int mode)
{
if( USMC_GetParameters(Dev, ¶meters[Dev]) )
return TRUE;
switch (mode) {
case 0:
// Rotation stage
usmc_SwapSwitches(Dev,1);
parameters[Dev].MaxTemp = 70.0f;
parameters[Dev].AccelT = 200.0f;
parameters[Dev].DecelT = 200.0f;
parameters[Dev].BTimeout1 = 500.0f;
parameters[Dev].BTimeout2 = 500.0f;
parameters[Dev].BTimeout3 = 500.0f;
parameters[Dev].BTimeout4 = 500.0f;
parameters[Dev].BTO1P = 10.0f;
parameters[Dev].BTO2P = 20.0f;
parameters[Dev].BTO3P = 30.0f;
parameters[Dev].BTO4P = 60.0f;
parameters[Dev].MinP = 60.0f;
parameters[Dev].BTimeoutR = 500.0f;
parameters[Dev].LoftPeriod = 50.0f;
parameters[Dev].RTDelta = 20;
parameters[Dev].RTMinError = 15;
parameters[Dev].EncMult = 2.5f;
parameters[Dev].MaxLoft = 32;
parameters[Dev].PTimeout = 100.0f;
parameters[Dev].SynOUTP = 1;
break;
case 1:
// Linear stage
usmc_SwapSwitches(Dev,0);
parameters[Dev].MaxTemp = 70.0f;
parameters[Dev].AccelT = 200.0f;
parameters[Dev].DecelT = 200.0f;
parameters[Dev].BTimeout1 = 500.0f;
parameters[Dev].BTimeout2 = 500.0f;
parameters[Dev].BTimeout3 = 500.0f;
parameters[Dev].BTimeout4 = 500.0f;
parameters[Dev].BTO1P = 100.0f;
parameters[Dev].BTO2P = 200.0f;
parameters[Dev].BTO3P = 300.0f;
parameters[Dev].BTO4P = 600.0f;
parameters[Dev].MinP = 500.0f;
parameters[Dev].BTimeoutR = 500.0f;
parameters[Dev].LoftPeriod = 500.0f;
parameters[Dev].RTDelta = 200;
parameters[Dev].RTMinError = 15;
parameters[Dev].EncMult = 2.5f;
parameters[Dev].MaxLoft = 32;
parameters[Dev].PTimeout = 100.0f;
parameters[Dev].SynOUTP = 1;
break;
}
//
if( USMC_SetParameters( Dev, ¶meters[Dev] ) )
return TRUE;
if( USMC_SaveParametersToFlash( Dev ) )
return TRUE;
//system("cls");
print_parameters( ¶meters[Dev] );
printf("\nThese Parameters are Saved to Flash");
return FALSE;
}
int usmc_Init(int node, int mode){
USMC_GetStartParameters(node,&parstart[node]);
USMC_GetLastErr
(errstr
,ERRLEN
); if (strlen(errstr
)) printf("i1 %s\n",errstr
);
USMC_GetState(node,&parstate[node]);
USMC_GetLastErr
(errstr
,ERRLEN
); if (strlen(errstr
)) printf("i2 %s\n",errstr
);
USMC_GetEncoderState(node,&parencstate[node]);
USMC_GetLastErr
(errstr
,ERRLEN
); if (strlen(errstr
)) printf("i3 %s\n",errstr
);
print_state(&parstate[node]);
print_enc_state ( parencstate[node]);
print_start_params (parstart[node] );
usmc_Set_Parameters(node, mode);
return 0;
}
float usmc_speed=10000;
int usmc_Move(int node, int pos, BOOL absrel){
time_t tcur=0, tprev=-1;
USMC_GetStartParameters(node,&parstart[node]);
USMC_GetLastErr
(errstr
,ERRLEN
); if (strlen(errstr
)) printf("x1 %s\n",errstr
);
parstart[node].WSyncIN=absrel;
parstart[node].SlStart=1;
parstart[node].LoftEn=0;
print_start_params ( parstart[node] );
if (absrel
) printf("usmc_Move relative for %d\n",pos
);
else printf("usmc_Move absolute %d\n",pos
);
USMC_Start(node,pos,&usmc_speed, &parstart[node]);
Delay(0.1);
USMC_GetLastErr
(errstr
,ERRLEN
); if (strlen(errstr
)) printf("x2 %s speed %f\n",errstr
,usmc_speed
);
do {
USMC_GetState(node,&parstate[node]);
USMC_GetLastErr(errstr,ERRLEN); // if (strlen(errstr)) printf("x3 %s\n",errstr);
if (tcur != tprev){
printf("%d CurPos %d L%d R%d Rot%d %s %s\n",node
,
parstate[node].CurPos,parstate[node].Trailer1,parstate[node].Trailer2, parstate[node].RotTr,
parstate[node].RUN?"Run":"Stopped",parstate[node].Power?"On":"Off" );
tprev= tcur;
}
} while ( parstate[node].RUN == 1 );
USMC_GetState(node,&parstate[node]);
printf("***** %d CurPos %d L%d R%d %s %s\n",node
,
parstate[node].CurPos,parstate[node].Trailer1,parstate[node].Trailer2,
parstate[node].RUN?"Run":"Stopped",parstate[node].Power?"On":"Off" );
USMC_GetParameters(node,¶meters[node]);
USMC_GetEncoderState(node,&parencstate[node]);
printf("node %d ECurPos 0x%0x %f EncoderPos =0x%04x %f\n",node
,
parencstate[node].ECurPos, (((parencstate[node].ECurPos)>>5)&0x8FFFFF)/parameters[node].EncMult,
parencstate[node].EncoderPos,((parencstate[node].EncoderPos >> 5)&0x8FFFFF)/parameters[node].EncMult);
return 0;
}
void usmc_PowerOnOff ( int cur_dev, int smpower ){
USMC_Mode mode;
if ( USMC_GetMode ( cur_dev, &mode ) ) return;
mode.ResetD = !smpower;
if ( USMC_SetMode ( cur_dev, &mode ) ) return;
printf ( "Now, Power of the node %d is %s\n", cur_dev
, mode.
ResetD ? "Off" : "On" );
}
int usmc_MoveTo(int node, int pos){
return usmc_Move(node,pos, FALSE);
}
int usmc_RelMove(int node, int pos){
//return usmc_Move(node,pos, TRUE);// does not work - don't know why
USMC_GetState(node,&parstate[node]);
return usmc_MoveTo( node, pos + parstate[node].CurPos );
}
int Revert_Start_Position_to_0(int node)
{
USMC_Parameters Prms;
// Initialize structures (in case this function runs first)
if( USMC_GetParameters(node, &Prms) )
return TRUE;
Prms.StartPos = 0;
if( USMC_SetParameters( node, &Prms ) )
return TRUE;
// Then of Course You Need to SaveToFlash
if( USMC_SaveParametersToFlash( node ) )
return TRUE;
//system("cls");
printf("\nStart Position is Reset to 0\n");
printf("\nPress any key to exit");
return FALSE;
}
int usmc_Reset(int node, int mode){
usmc_Init(node,mode);
USMC_SetCurrentPosition(node, 0);
Revert_Start_Position_to_0(node);
return 0;
}
int usmc_ReferenceMove(int node, int mode){
int pos = 1000000;
int dir=1;
if (!mode) usmc_SwapSwitches(node,1);
else usmc_SwapSwitches(node,0);
usmc_EnableSwitches(node,1);
USMC_GetState(node,&parstate[node]);
usmc_MoveTo(node, parstate[node].CurPos -2 *pos * dir);
USMC_GetState(node,&parstate[node]);
pos = 5000;
if (!mode) pos=500;
usmc_MoveTo(node, parstate[node].CurPos + pos * dir);
USMC_GetState(node,&parstate[node]);
usmc_speed /=5;
usmc_MoveTo(node, parstate[node].CurPos -2 *pos * dir);
USMC_GetState(node,&parstate[node]);
pos = 2000;
if (!mode) pos=200;
usmc_MoveTo(node, parstate[node].CurPos + pos *dir);
USMC_GetState(node,&parstate[node]);
usmc_speed /= 10;
usmc_MoveTo(node, parstate[node].CurPos -2 *pos * dir);
USMC_GetState(node,&parstate[node]);
USMC_SetCurrentPosition(node, 0);
Revert_Start_Position_to_0(node);
usmc_EnableSwitches(node,0);
return 0;
}
int help(){
fprintf(stderr
, "Usage: mikro [-i node][-n node] [-u up] [-d down] [-r node] [-h node] [-a] [-g] [-m pos]\n");
fprintf(stderr
," -n node -i mode .. initialize node\n");
fprintf(stderr
," -n node -h <endswitch_direction> .. homing procedure for node\n");
fprintf(stderr
," -n node -p 1 .. power on\n");
fprintf(stderr
," -n node -p 0 .. power off\n");
fprintf(stderr
," -n node -r mode .. reset node\n");
fprintf(stderr
," -n node -u <steps> .. move node for <steps>\n");
fprintf(stderr
," -a .. current status of the nodes\n");
fprintf(stderr
," -n node -v value -f cmd .. set value of the cmd on the node\n");
fprintf(stderr
," -n node -g cmd .. get value of the cmd on the node\n");
fprintf(stderr
," -n node -m position -s speed .. move node to position at speed (default 10000)\n");
fprintf(stderr
," -l delaysec .. loop test with the delay delaysec\n");
return 0;
}
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:u:n:m:s:v:gh: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,&parstate[i]);
printf("%d CurPos %d L%d R%d %s %s\t",i
,
parstate[i].CurPos,parstate[i].Trailer1,parstate[i].Trailer2,
parstate[i].RUN?"Run":"Stopped",parstate[i].Power?"On":"Off" );
USMC_GetParameters(i,¶meters[i]);
USMC_GetEncoderState(i,&parencstate[i]);
printf("node %d ECurPos 0x%0x %f EncoderPos =0x%04x %f\n",i
,
parencstate[i].ECurPos, (((parencstate[i].ECurPos)>>5)&0x8FFFFF)/parameters[i].EncMult,
parencstate[i].EncoderPos,((parencstate[i].EncoderPos >> 5)&0x8FFFFF)/parameters[i].EncMult);
}
break;
case 'l':
for (i=0;i<5;i++){
int xpos=i*1000+10000;
usmc_MoveTo (0, xpos);
for (j=0;j<5;j++){
int ypos=j*1000+10000;
usmc_MoveTo (1, ypos);
for (k=0;k<50;k++){
int zpos=k*1000+10000;
usmc_MoveTo (2, zpos);
printf("x=%d y=%d z=%d\n",xpos
,ypos
,zpos
);
}
}
}
break;
case 'n':
break;
case 's':
usmc_speed
= atoi(optarg
);
break;
case 'p':
usmc_PowerOnOff
(node
,atoi(optarg
));
break;
case 'm':
usmc_EnableSwitches(node,1);
usmc_MoveTo
(node
, atoi(optarg
));
usmc_EnableSwitches(node,0);
printf("usmc_MoveTo node=%d pos=%d \n",node
,atoi(optarg
));
break;
case 'v':
break;
/*
case 'f':
MIKRO_Set (node,optarg,value);
printf("MIKRO_Set node %d cmd=%s val=%d\n",node,optarg, value);
break;
*/
case 'g':
USMC_GetState(node,&parstate[node]);
printf("node %d CurPos %d L%d R%d %s %s\n",node
,
parstate[node].CurPos,parstate[node].Trailer1,parstate[node].Trailer2,
parstate[node].RUN?"Run":"Stopped",parstate[node].Power?"On":"Off" );
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 endswitch=%d\n",node
, atoi(optarg
));
usmc_ReferenceMove
(node
, atoi(optarg
));
break;
case 'u':
usmc_EnableSwitches(node,1);
usmc_RelMove
(node
, atoi(optarg
));
usmc_EnableSwitches(node,0);
break;
default: /* '?' */
help();
break;
}
}
if (argc==1) help();
USMC_Close ();
#ifdef _WINDOWS
#endif
return 0;
}