This repository has been archived by the owner on Mar 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsfun_maxon.c
331 lines (277 loc) · 9.24 KB
/
sfun_maxon.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#define S_FUNCTION_NAME sfun_maxon
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include "mex.h"
#include "Definitions.h"
#ifdef _LINUX_
#include "Win2Linux.h"
#endif
/* Global data for all instance of this S-function */
static volatile int mylock = 0;
static volatile int NumberOfInstances = 0;
static HANDLE mHandle = NULL;
static BYTE OpModes[5];
_inline void EnterLock(void) {
while (mylock);
mylock++;
}
_inline void LeaveLock(void) { mylock--; }
/* Check Size and Parameters */
static void mdlInitializeSizes(SimStruct *S) {
double ThisSampleTime;
int NodeID, OperationMode;
/* Set OpModes */
if (NumberOfInstances == 0) {
EnterLock();
OpModes[0] = OMD_CURRENT_MODE;
OpModes[1] = OMD_VELOCITY_MODE;
OpModes[2] = OMD_POSITION_MODE;
LeaveLock();
};
/* Number of expected parameters */
ssSetNumSFcnParams(S, 3);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
/* Return if number of expected != number of actual parameters */
ssSetErrorStatus(S, "Expected three parameters: SampleTime, NodeID and OperationMode");
return;
}
/* Obtain Sample Time */
ThisSampleTime = (double) mxGetScalar(ssGetSFcnParam(S, 0));
if (ThisSampleTime < 0.0) {
ssSetErrorStatus(S, "Parameter 1 must be > 0.0 and < 1.0");
return;
}
if (ThisSampleTime > 1.0) {
ssSetErrorStatus(S, "Parameter 1 must be > 0.0 and < 1.0");
return;
}
/* Obtain Node ID */
NodeID = (int) mxGetScalar(ssGetSFcnParam(S, 1));
if (NodeID < 0) {
ssSetErrorStatus(S, "Parameter 2 must be a possitive number");
return;
}
if (NodeID > 16) {
ssSetErrorStatus(S, "Parameter 2 must be lower than 16");
return;
}
/* Obtain Operation Mode */
OperationMode = (int) mxGetScalar(ssGetSFcnParam(S, 2));
if (OperationMode < 1) {
ssSetErrorStatus(S, "Parameter 3 must be > 1 and < = 3");
return;
}
if (OperationMode > 3) {
ssSetErrorStatus(S, "Parameter 3 must be > 1 and < = 3");
return;
}
/* continous and discretes states */
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
/* one input port with size one */
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
/* one output port with size one */
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, 1);
/* direct input signal access */
ssSetInputPortRequiredContiguous(S, 0, true);
/* Port based sample time */
ssSetNumSampleTimes(S, PORT_BASED_SAMPLE_TIMES);
ssSetInputPortSampleTime(S, 0, ThisSampleTime);
ssSetInputPortOffsetTime(S, 0, 0);
ssSetOutputPortSampleTime(S, 0, ThisSampleTime / 2.0);
ssSetOutputPortOffsetTime(S, 0, 0);
/* two Integers data to store Node ID and OperationMode */
ssSetNumIWork(S, 2);
/* No pointers, real works variables */
ssSetNumPWork(S, 0);
ssSetNumRWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
/* Specify the sim state compliance to be same as a built-in block */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
static void mdlInitializeSampleTimes(SimStruct *S) {
/*
ssSetSampleTime(S, 0, 0.1);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInherance(S);
*/
}
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
/* Function: mdlStart =======================================================
* Abstract:
* This function is called once at start of model execution. If you
* have states that should be initialized once, this is the place
* to do it.
*/
static void mdlStart(SimStruct *S) {
WORD NodeID;
DWORD ErrCode = 0;
BOOL Fault = FALSE;
LONG actualpos;
int opmode;
/* Get Node ID from first parameters */
NodeID = (WORD) mxGetScalar(ssGetSFcnParam(S, 1));
/* Get operation mode */
opmode = (int) mxGetScalar(ssGetSFcnParam(S, 2));
opmode--;
/* Store NodeID */
ssSetIWorkValue(S, 0, (int) NodeID);
ssSetIWorkValue(S, 1, opmode);
/* Lock */
EnterLock();
/* Store handle */
if (mHandle == NULL) {
mHandle = VCS_OpenDevice("EPOS4", "MAXON SERIAL V2", "USB", "USB0", &ErrCode);
if (ErrCode) {
mexPrintf("Error opening USB, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error opening Device");
/* release lock */
LeaveLock();
return;
};
};
/* Reseting Error if in error state */
if (!VCS_GetFaultState(mHandle, NodeID, &Fault, &ErrCode)) {
mexPrintf("Error Checking Fault, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error Checking Fault State");
/* release lock */
LeaveLock();
return;
}
if (Fault) {
if (!VCS_ClearFault(mHandle, NodeID, &ErrCode)) {
mexPrintf("Error clearing fault state, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error Clearing Fault State");
/* release lock */
LeaveLock();
return;
}
}
/* Enabling device */
if (!VCS_SetEnableState(mHandle, NodeID, &ErrCode)) {
mexPrintf("Error Enabling Node, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error Enabling Device");
/* release lock */
LeaveLock();
return;
}
/* Set Encoder to Zero for Actual Position */
if (!VCS_ActivateHomingMode(mHandle, NodeID, &ErrCode)) {
mexPrintf("Error activating homming, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error activating homming");
/* release lock */
LeaveLock();
return;
};
if (!VCS_DefinePosition(mHandle, NodeID, 0, &ErrCode)) {
mexPrintf("Error setting position to zero for node %i, ErrCode is %i\n", (int) NodeID, (int) ErrCode);
ssSetErrorStatus(S, "Error setting zero");
/* release lock */
LeaveLock();
return;
};
/* Changing to Op Mode */
if (!VCS_SetOperationMode(mHandle, NodeID, OpModes[opmode], &ErrCode)) {
mexPrintf("Error Setting Operation Mode, ErrCode is %i\n", (int) ErrCode);
ssSetErrorStatus(S, "Error Setting Operation Mode");
/* release lock */
LeaveLock();
return;
}
/* Update Instance */
NumberOfInstances++;
/* release lock */
LeaveLock();
}
#endif /* MDL_START */
#define MDL_UPDATE
#if defined(MDL_UPDATE)
static void mdlUpdate(SimStruct *S, int_T tid) {
/* Read Encoder Position */
WORD NodeID;
DWORD ErrCode;
short current;
LONG posvel;
/* Accesing inputs and outputs */
const real_T *u = (const real_T *) ssGetInputPortSignal(S, 0);
/* Get Node ID */
NodeID = (WORD) ssGetIWorkValue(S, 0);
EnterLock();
switch (ssGetIWorkValue(S, 1)) {
case 0:
current = (short) u[0];
if (current > 2000) current = 2000;
if (current < -2000) current = -2000;
VCS_SetCurrentMust(mHandle, NodeID, current, &ErrCode);
break;
case 1:
posvel = (long) u[0];
VCS_SetVelocityMust(mHandle, NodeID, posvel, &ErrCode);
break;
case 2:
posvel = (long) u[0];
VCS_SetPositionMust(mHandle, NodeID, posvel, &ErrCode);
break;
}
LeaveLock();
}
#endif /* MDL_UPDATE */
/* Function: mdlOutputs =======================================================
* Abstract:
* In this function, you compute the outputs of your S-function
* block.
*/
static void mdlOutputs(SimStruct *S, int_T tid) {
/* Read Encoder Position */
WORD NodeID;
DWORD ErrCode;
LONG Position;
/* Accesing inputs and outputs */
real_T *y = ssGetOutputPortSignal(S, 0);
/* Get Node ID */
NodeID = (WORD) ssGetIWorkValue(S, 0);
/* Obtaining actual position */
EnterLock();
VCS_GetPositionIs(mHandle, NodeID, &Position, &ErrCode);
LeaveLock();
/* output */
y[0] = (real_T) Position;
}
/* Function: mdlTerminate =====================================================
* Abstract:
* In this function, you should perform any actions that are necessary
* at the termination of a simulation. For example, if memory was
* allocated in mdlStart, this is the place to free it.
*/
static void mdlTerminate(SimStruct *S) {
WORD NodeID;
DWORD ErrCode;
/* Get Data */
NodeID = (WORD) ssGetIWorkValue(S, 0);
EnterLock();
/* Disable device */
VCS_SetDisableState(mHandle, NodeID, &ErrCode);
/* update instances */
if (--NumberOfInstances <= 0) {
/* Close Device */
VCS_CloseDevice(mHandle, &ErrCode);
mHandle = NULL;
}
LeaveLock();
}
/*======================================================*
* See sfuntmpl_doc.c for the optional S-function methods *
*======================================================*/
/*=============================*
* Required S-function trailer *
*=============================*/
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif