Simulink s-functions

Legacy support with Phidget21
mrDevGuy
Fresh meat
Posts: 2
Joined: Wed Aug 03, 2011 2:49 am
Contact:

Simulink s-functions

Postby mrDevGuy » Wed Aug 03, 2011 3:07 am

Hello,
I'm trying to write a s-funtion in simulink to acquire the analog and digital inputs from the interfacekit 888.
I'd like to do that using the C language so i read the c and matlab phidgets docs and i wrote a simple skeleton .c .
I compiled correctly using the mex comand in matlab and linking to the phidgets21.lib. It seems to work fine when i include only one s-function block into my simulink model (i can run the simulation, stop it and restart it). The problem is that when i include 2 or more s-function blocks (using the same sfcn_interfacekit8_8_8.c) the simulation starts but crashes when i close it (and it also doesn't work correctly).
The reason I'm writing this is because i want to use 3 interfacekits hooked to a usb-hub and then to a pc.
I think I'm making some mistakes in the init part of the code.
Could anyone help me?
Thanks to anyone who will try to help!!!

The code is:
#define S_FUNCTION_NAME sfcn_interfaceKit8_8_8
#define S_FUNCTION_LEVEL 2

#define NUMBER_OF_ANALOG_IN_SENSORS_INTERFACEKIT 8
#define NUMBER_OF_DIGITAL_IN_SENSORS_INTERFACEKIT 8

#include "simstruc.h"
#include "../libs/phidget21.h"

int __stdcall AttachHandler(CPhidgetHandle IFK, void *userptr)
{
int serialNo;
const char *name;
CPhidget_getDeviceName(IFK, &name);
CPhidget_getSerialNumber(IFK, &serialNo);
printf("%s %10d attached!\n", name, serialNo);
return 0;
}

int __stdcall DetachHandler(CPhidgetHandle IFK, void *userptr)
{
int serialNo;
const char *name;
CPhidget_getDeviceName (IFK, &name);
CPhidget_getSerialNumber(IFK, &serialNo);
printf("%s %10d detached!\n", name, serialNo);
return 0;
}

int __stdcall ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
{
printf("Error handled. %d - %s", ErrorCode, unknown);
return 0;
}

//callback that will run if an input changes.
//Index - Index of the input that generated the event, State - boolean (0 or 1) representing the input state (on or off)
int __stdcall InputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int State)
{
printf("Digital Input: %d > State: %d\n", Index, State);
return 0;
}

//callback that will run if an output changes.
//Index - Index of the output that generated the event, State - boolean (0 or 1) representing the output state (on or off)
int __stdcall OutputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int State)
{
printf("Digital Output: %d > State: %d\n", Index, State);
return 0;
}

//callback that will run if the sensor value changes by more than the OnSensorChange trigger.
//Index - Index of the sensor that generated the event, Value - the sensor read value
int __stdcall SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int Value)
{
printf("Sensor: %d > Value: %d\n", Index, Value);
return 0;
}


CPhidgetInterfaceKitHandle ifKit_1 = 0;


int_T AnalogSensorValue[NUMBER_OF_ANALOG_IN_SENSORS_INTERFACEKIT];
int_T DigitalSensorValue[NUMBER_OF_DIGITAL_IN_SENSORS_INTERFACEKIT];

static void mdlInitializeSizes(SimStruct *S)
{

ssSetNumSFcnParams(S, 1); /* Phidget Number */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))
{
return;
}

ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);

if (!ssSetNumInputPorts(S, 0)) return;
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, NUMBER_OF_ANALOG_IN_SENSORS_INTERFACEKIT);
ssSetOutputPortWidth(S, 1, NUMBER_OF_DIGITAL_IN_SENSORS_INTERFACEKIT);

ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions(S, 0);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);

}
#define MDL_INITIALIZE_CONDITIONS
#if defined(MDL_INITIALIZE_CONDITIONS)

static void mdlInitializeConditions(SimStruct *S)
{
}
#endif
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)

static void mdlStart(SimStruct *S)
{
int_T result;
const char *err;
const real_T *ifKitSN_1 = mxGetPr(ssGetSFcnParam(S,0));

//Declare an InterfaceKit handle

CPhidget_enableLogging(PHIDGET_LOG_VERBOSE, NULL);

//create the InterfaceKit object


CPhidgetInterfaceKit_create(&ifKit_1);


//Set the handlers to be run when the device is plugged in or opened from software, unplugged or closed from software, or generates an error.
CPhidget_set_OnAttach_Handler((CPhidgetHandle)ifKit_1, AttachHandler, NULL);
CPhidget_set_OnDetach_Handler((CPhidgetHandle)ifKit_1, DetachHandler, NULL);
CPhidget_set_OnError_Handler((CPhidgetHandle)ifKit_1, ErrorHandler, NULL);

//Registers a callback that will run if an input changes.
//Requires the handle for the Phidget, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
CPhidgetInterfaceKit_set_OnInputChange_Handler (ifKit_1, InputChangeHandler, NULL);


//Registers a callback that will run if the sensor value changes by more than the OnSensorChange trigger.
//Requires the handle for the IntefaceKit, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
CPhidgetInterfaceKit_set_OnSensorChange_Handler (ifKit_1, SensorChangeHandler, NULL);


//Registers a callback that will run if an output changes.
//Requires the handle for the Phidget, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
CPhidgetInterfaceKit_set_OnOutputChange_Handler (ifKit_1, OutputChangeHandler, NULL);


//open the interfacekit for device connections

CPhidget_open((CPhidgetHandle)ifKit_1,*ifKitSN_1);

//get the program to wait for an interface kit device to be attached
if((result = CPhidget_waitForAttachment((CPhidgetHandle)ifKit_1, 10000)))
{
CPhidget_getErrorDescription(result, &err);
}
}
#endif /* MDL_START */
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i ;

const real_T *u = (const real_T*) ssGetInputPortSignal(S,0);
real_T *y_1 = ssGetOutputPortSignal(S,0); // first port output vector
real_T *z_1 = ssGetOutputPortSignal(S,1); // second port output vector

for(i = 0; i < NUMBER_OF_ANALOG_IN_SENSORS_INTERFACEKIT; i++ )
{
CPhidgetInterfaceKit_getSensorValue(ifKit_1,i,&AnalogSensorValue[i]);
y_1[i] = AnalogSensorValue[i];
}

for(i = 0; i < NUMBER_OF_DIGITAL_IN_SENSORS_INTERFACEKIT; i++ )
{
CPhidgetInterfaceKit_getInputState(ifKit_1,i,&DigitalSensorValue[i]);
z_1[i] = DigitalSensorValue[i];
}


}



#define MDL_UPDATE /* Change to #undef to remove function */
#if defined(MDL_UPDATE)

static void mdlUpdate(SimStruct *S, int_T tid)
{
}
#endif /* MDL_UPDATE */



#define MDL_DERIVATIVES /* Change to #undef to remove function */
#if defined(MDL_DERIVATIVES)

static void mdlDerivatives(SimStruct *S)
{
}
#endif /* MDL_DERIVATIVES */

static void mdlTerminate(SimStruct *S)
{

CPhidget_close((CPhidgetHandle)ifKit_1);
CPhidget_delete((CPhidgetHandle)ifKit_1);


}

#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


mphi
Phidgetly
Posts: 39
Joined: Tue Nov 16, 2010 4:27 pm
Contact:

Re: Simulink s-functions

Postby mphi » Wed Aug 03, 2011 11:13 am

Hello,

I see that you are using events in your C S function. From my understanding, MATLAB does not support event handling. Doing so may lead to crashes.

Furthermore, I had a glance at your code, and the crash and unexpected results may be due to how Simulink manages the memory of the C S functions.

In the mdlStart function, you can see if the Phidget actually attached by calling CPhidget_getSerialNumber. You can also see the memory location of ifKit_1 by:

Code: Select all

const real_T *u = (const real_T*) ssGetInputPortSignal(S,0);
int result, serial;
printf("\n--->mdlStart");
printf("\n Serial to open: %f", u[0]);
CPhidgetInterfaceKit_create(&ifKit_1);
result = CPhidget_open((CPhidgetHandle)ifKit_1, u[0]);
CPhidget_waitForAttachment((CPhidgetHandle)ifKit_1, 10000);
CPhidget_getSerialNumber((CPhidgetHandle)ifKit_1, &serial);
printf("Serial #: %d", serial);
printf("The handle address is: %lu", ifKit_1);


Do you see the same address or two different addresses?

Now, try printing the handle address again in mdlOutputs. Do you see the same address or two different addresses for both blocks?

In my findings, I found that mdlStart produced two different addresses. But in mdlOutputs, I only saw the most recent address location. So, it seems that the first address got overwritten.


Return to “Matlab”

Who is online

Users browsing this forum: No registered users and 1 guest