Scope
XYControlStanda.cpp
1 #include "StdAfx.h"
2 #include "XYControlStanda.h"
3 #include "ScopeDefines.h"
4 #include "parameters/Devices.h"
5 #include "helpers/Helpers.h"
6 #include "helpers/ScopeException.h"
7 #include "controllers/ScopeLogger.h"
8 
9 #ifdef SCOPE_USE_STANDA_XYFPUSTAGE
10 
11 namespace scope {
12 
13 XYControlStanda::XYControlStanda()
14  : speed(10.0)
15  , microsteps_per_micron(3.226) {
16 }
17 
18 XYControlStanda::~XYControlStanda(void) {
19  StopPolling();
20  try {
21  std::lock_guard<std::mutex> lock(mutex);
22  // Do not turn off the device -> with the motors switched off, push buttons do not work
23  /*for ( auto d : dev )
24  TurnOffAndSaveToFlash(d);
25  */
26  CheckError(USMC_Close());
27  }
28  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
29 }
30 
31 void XYControlStanda::Initialize(parameters::XYControlStanda& _params) {
32  try {
33  std::lock_guard<std::mutex> lock(mutex);
34  CheckError(USMC_Init(devices));
35  ScopeLogger scope_logger;
36  std::stringstream msg;
37  msg << "XYControlStanda connected\r\n";
38  for ( uint32_t i = 0 ; i < devices.NOD ; i++ )
39  msg << "Device " << i << " - " << devices.Serial[i] << " - " << devices.Version[i] << "\r\n";
40  CA2W tmp(msg.str().c_str());
41  scope_logger.Log(std::wstring(tmp), log_info);
42 
43  //assert(devices.NOD == SCOPE_NAREAS);
44 
45  // zero based device number
46  dev[0] = static_cast<DWORD>(_params.devicex());
47  dev[1] = static_cast<DWORD>(_params.devicey());
48  speed = static_cast<float>(_params.speed());
49  microsteps_per_micron = _params.microstepspermicron();
50  for ( uint32_t d = 0 ; d < 2 ; d++ )
51  InitAxis(dev[d]);
52 
53  // call base class Initialize, which connects ScopeValues, sets initialized to true, and starts the polling thread
54  XYControl::Initialize(_params);
55 
56  std::wstring msg2(L"Initialized XYControlStanda");
57  scope_logger.Log(msg2, log_info);
58  }
59  catch (...) {
60  initialized = false;
61  ScopeExceptionHandler(__FUNCTION__);
62  }
63 
64  //std::this_thread::sleep_for(std::chrono::milliseconds(500));
65  _params.stageinfo = L"XYControlStanda\r\n\r\nStart Parameters\r\n" + GetStartParameters() + L"\r\n\r\nParameters\r\n"+ GetParameters() + L"\r\n\r\nMode\r\n" + GetMode();
66 }
67 
68 void XYControlStanda::InitAxis(const DWORD& _device) {
69  CheckError(USMC_GetMode(_device, mode));
70  // Do not wait for external sync signal
71  mode.SyncINOp = false;
72  // Power on ?
73  mode.ResetD = false;
74  CheckError(USMC_SetMode(_device, mode));
75  CheckError(USMC_GetStartParameters(_device, stprms));
76  // set slow start
77  stprms.SlStart = true;
78  stprms.LoftEn = false;
79  stprms.WSyncIN = false;
80  stprms.ForceLoft = false;
81 }
82 
83 void XYControlStanda::TurnOffAndSaveToFlash(const DWORD& _device) {
84  // Initialize structures
85  CheckError(USMC_GetParameters(_device, prms));
86  CheckError(USMC_GetMode(_device, mode));
87  // Go to Full Step (automaticaly), then Turn Off
88  mode.ResetD = TRUE;
89  CheckError(USMC_SetMode(_device, mode));
90  // Wait until Previous Comand is Done
91  do {
92  std::this_thread::sleep_for(std::chrono::milliseconds(50));;
93  CheckError(USMC_GetState(_device, state));
94  } while(state.Power == TRUE);
95  // Remember CurPos in Parameters Only While State.Power - FALSE
96  prms.StartPos = state.CurPos;
97  CheckError(USMC_SetParameters( _device, prms));
98  // Then of Course You Need to SaveToFlash
99  CheckError(USMC_SaveParametersToFlash( _device ));
100  // Now You Can Unplug ME
101 }
102 
103 void XYControlStanda::StartPolling() {
104  // If something went wrong during initialization we do not want to poll (and probably cause more errors)
105  if ( initialized ) {
106  fut = std::async([this]() {
107  while (!stop.IsSet()) {
108  try {
109  std::lock_guard<std::mutex> lock(mutex);
110  UpdatePositionValues();
111  }
112  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
113  std::this_thread::sleep_for(std::chrono::milliseconds(pollinterval));
114  }
115  return true;
116  } );
117  }
118 }
119 
120 void XYControlStanda::UpdatePositionValues() {
121  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
122  CheckError(USMC_GetState(dev[d], state));
123  // Convert from current position (in microsteps, 1/8 step) to micrometers and truncate to one digit
124  double micron = round(static_cast<double>(state.CurPos)/microsteps_per_micron * 10.0) / 10.0;
125  // Use Set with "call other signal" false, thus MoveAbsolute is not called as consequence (that would lead to circular calls...)
126  pos[d]->Set(micron, true, false);
127  }
128 }
129 
130 void XYControlStanda::SetZero() {
131  try {
132  std::lock_guard<std::mutex> lock(mutex);
133  for ( uint32_t d = 0 ; d < 2 ; d++ )
134  CheckError(USMC_SetCurrentPosition(dev[d], 0));
135  std::this_thread::sleep_for(std::chrono::milliseconds(500));
136  }
137  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
138 }
139 
140 void XYControlStanda::MoveRelative(const double& _xrel, const double& _yrel) {
141  try {
142  std::lock_guard<std::mutex> lock(mutex);
143  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
144  CheckError(USMC_GetState(dev[d], state));
145  DBOUT(L"XYControlStanda::MoveRelative from " << state.CurPos << L" by " << _xrel << L" " << _yrel);
146  CheckError(USMC_Start(dev[d], state.CurPos+round2i32(microsteps_per_micron*((d==0)?_xrel:_yrel)), speed, stprms));
147  }
148  std::this_thread::sleep_for(std::chrono::milliseconds(500));
149  //UpdatePositionValues();
150  }
151  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
152 }
153 
154 void XYControlStanda::MoveAbsolute(const double& _xabs, const double& _yabs) {
155  try {
156  std::lock_guard<std::mutex> lock(mutex);
157  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
158  CheckError(USMC_GetState(dev[d], state));
159  DBOUT(L"XYControlStanda::MoveAbsolute to " << _xabs << L" " << _yabs);
160  CheckError(USMC_Start(dev[d], round2i32(microsteps_per_micron*((d==0)?_xabs:_yabs)), speed, stprms));
161  }
162  std::this_thread::sleep_for(std::chrono::milliseconds(500));
163  }
164  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
165 }
166 
167 void XYControlStanda::CheckError(const DWORD& errorcode) {
168  if ( errorcode != 0 ) {
169  char perrorstring[256];
170  USMC_GetLastErr(perrorstring, 256);
171  throw( ScopeException(perrorstring) );
172  }
173 }
174 
175 std::wstring XYControlStanda::GetParameters() {
176  std::lock_guard<std::mutex> lock(mutex);
177  std::wstringstream stream;
178  try {
179  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
180  CheckError(USMC_GetParameters(dev[d], prms));
181  stream << L"Axis: " << d << L" Device: " << dev[d] << L"\r\nAccel time (ms): " << prms.AccelT << L"\r\nDecel time (ms): " << prms.DecelT << L"\r\nCurrent reduction time (ms): ";
182  stream << prms.PTimeout << L"\r\nTime to speed B time (ms): " << prms.BTimeout1 << L"\r\nReset time (ms): " << prms.BTimeoutR;
183  stream << L"\r\nSpeed at reset (steps/s): " << prms.MinP << L"\r\nSpeed B (steps/s): " << prms.BTO1P << L"\r\nSteps for backlash: " << prms.MaxLoft;
184  stream << L"\r\nPosition in flash: " << prms.StartPos << L"\r\nSteps per revolution: " << prms.RTDelta << L"\r\nSteps missed for error flag: ";
185  stream << prms.RTMinError << L"\r\nMax temperature (C): " << prms.MaxTemp << L"\r\nSync out pulse duration: " << prms.SynOUTP;
186  stream << L"\r\nLast phase backlash speed: " << prms.LoftPeriod << L"\r\nEncoder steps per rev/SM steps per rev: " << prms.EncMult << L"\r\n";
187  }
188  }
189  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
190  return stream.str();
191 }
192 
193 std::wstring XYControlStanda::GetMode() {
194  std::lock_guard<std::mutex> lock(mutex);
195  std::wstringstream stream;
196  try {
197  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
198  CheckError(USMC_GetMode(dev[d], mode));
199  stream << L"Axis: " << d << L" Device: " << dev[d] << L"\r\nButtons disabled: " << mode.PMode << L"\r\nCurrent reduction: " << mode.PReg << L"\r\nReset: " << mode.ResetD;
200  stream << L"\r\nQuick power off: " << mode.EMReset << L"\r\nTrailer 1: " << mode.Tr1T << L"\r\nTrailer 2: " << mode.Tr2T << L"\r\nRotary transducer: ";
201  stream << mode.RotTrT << L"\r\nTrailers swapped: " << mode.TrSwap << L"\r\nTrailer 1 operation: " << mode.Tr1En << L"\r\nTrailer 2 operation: ";
202  stream << mode.Tr2En << L"\r\nRotary transducer operation: " << mode.RotTeEn << L"\r\nRotary transducer operation select: " << mode.RotTrOp;
203  stream << L"\r\nButton 1: " << mode.Butt1T << L"\r\nButton 2: " << mode.Butt2T << L"\r\nReset rotary transducer: " << mode.ResetRT;
204  stream << L"\r\nSync Out enabled: " << mode.SyncOUTEn << L"\r\nSync Out counter reset: " << mode.SyncOUTR << L"\r\nSync In mode: " << mode.SyncINOp;
205  stream << L"\r\nSync count: " << mode.SyncCount << L"\r\nSync invert: " << mode.SyncInvert << L"\r\nEnable Encoder: " << mode.EncoderEn;
206  stream << L"\r\nInvert Encoder: " << mode.EncoderInv << L"\r\nReset Encoder position: " << mode.ResBEnc << L"\r\nReset SM position to encoder position: ";
207  stream << mode.ResEnc << L"\r\n";
208  }
209  }
210  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
211  return stream.str();
212 }
213 
214 std::wstring XYControlStanda::GetState() {
215  std::lock_guard<std::mutex> lock(mutex);
216  std::wstringstream stream;
217  try {
218  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
219  CheckError(USMC_GetState(dev[d], state));
220  stream << L"Axis: " << d << L" Device: " << dev[d] << L"\r\nCurrent position: " << state.CurPos << L"\r\nTemperature: " << state.Temp << L"\r\nStep divisor: " << state.SDivisor;
221  stream << L"\r\nBacklash status: " << state.Loft << L"\r\nFull power: " << state.FullPower << L"\r\nCurrent direction: " << state.CW_CCW;
222  stream << L"\r\nPower: " << state.Power << L"\r\nFull speed: " << state.FullSpeed << L"\r\nAfter reset: " << state.AReset << L"\r\nRotating: ";
223  stream << state.RUN << L"\r\nInput sync state: " << state.SyncIN << L"\r\nOutput sync state: " << state.SyncOUT << L"\r\nRotary transducer state: ";
224  stream << state.RotTr << L"\r\nRotary transducer error: " << state.RotTrErr << L"\r\nEmergeny disable state: " << state.EmReset << L"\r\nTrailer 1 state: ";
225  stream << state.Trailer1 << L"\r\nTrailer 2 state: " << state.Trailer2 << L"\r\nVoltage: " << state.Voltage << L"\r\n";
226  }
227  }
228  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
229  return stream.str();
230 }
231 
232 std::wstring XYControlStanda::GetStartParameters() {
233  std::lock_guard<std::mutex> lock(mutex);
234  std::wstringstream stream;
235  try {
236  for ( uint32_t d = 0 ; d < 2 ; d++ ) {
237  CheckError(USMC_GetStartParameters(dev[d], stprms));
238  stream << L"Axis: " << d << L" Device: " << dev[d] << L"\r\nStep divisor: " << stprms.SDivisor << L"\r\nBacklash direction: " << stprms.DefDir << L"\r\nAutomatic backlash: ";
239  stream << stprms.LoftEn << L"\r\nSlow start/stop enabled: " << stprms.SlStart << L"\r\nWait for input sync signal: " << stprms.WSyncIN;
240  stream << L"\r\nReset sync out counter: " << stprms.SyncOUTR << L"\r\nForce backlash: " << stprms.ForceLoft << L"\r\n";
241  }
242  }
243  catch (...) { ScopeExceptionHandler(__FUNCTION__); }
244  return stream.str();
245 }
246 
247 }
248 
249 #endif
virtual void Initialize(parameters::XYControl &_params)
Initialize hardware.
Definition: XYControl.cpp:17
This is the include file for standard system include files, or project specific include files that ar...
bool CheckError(const int32 &error)
Checks return value of NI DAQmx function for error, prints out error information and throws an except...
Definition: DAQmxTask.cpp:9
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
void ScopeExceptionHandler(const std::string &_origin, const bool &_log, const bool &_showmessagebox, const bool &_trace, const bool &_rethrow)
Handles all exceptions and does nice logging.
Various helper functions and classes for Scope.