Matlab S-Function example: Read double input and write to file
This is an example for a Matlab Level-2 S-Function which reads a single continous input of type double and writes it to the file out.txt as CSV time,value. The file is opened in the mdlStart function and closed in the mdlTerminate function. The input value is read in the mdlUpdate function.
Also se Matlab Level 2 S-Function example: Sine wave (continous output).
single_input_write_to_file.cpp
#define S_FUNCTION_NAME single_input_write_to_file
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include <cstdio> // For file handling
// Define constants
#define SAMPLING_RATE 1000 // 1kHz
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0); // No parameters
ssSetNumContStates(S, 0); // No continuous states
ssSetNumDiscStates(S, 0); // No discrete states
// 1 input port with 1 element
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1); // Input port width = 1
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 0, COMPLEX_NO);
ssSetInputPortRequiredContiguous(S, 0, 1); // Require contiguous input port memory
// ssSetInputPortDirectFeedThrough(S, 0, 1); // Direct feedthrough
// No output ports
if (!ssSetNumOutputPorts(S, 0)) return;
// Sample times
ssSetNumSampleTimes(S, 1); // Single sample time
// Work vectors
ssSetNumRWork(S, 0); // Real work vector
ssSetNumIWork(S, 0); // Integer work vector
ssSetNumPWork(S, 1); // Pointer work vector for file pointer
ssSetNumModes(S, 0); // Mode vector
ssSetNumNonsampledZCs(S, 0); // Zero crossings
// Make the S-function block capable of being used in a Real-Time Workshop-generated model
ssSetOptions(S, 0);
}
#define MDL_START
static void mdlStart(SimStruct *S) {
// Open the file "out.txt" for writing
FILE *file = fopen("out.txt", "w");
if (file == NULL) {
ssSetErrorStatus(S, "Failed to open file 'out.txt'");
return;
}
const real_T *u = (const real_T*) ssGetInputPortSignal(S, 0); // Input pointer
real_T input_value = u == nullptr ? -1 : u[0]; // Read the input value
ssSetPWorkValue(S, 0, file);
}
// Function: mdlInitializeSampleTimes =========================================
// Abstract:
// Initialize the sample times to be 1ms (1kHz)
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, 1.0 / SAMPLING_RATE); // 1kHz sampling rate
ssSetOffsetTime(S, 0, 0.0);
}
// Not needed for this example
static void mdlOutputs(SimStruct *S, int_T tid) {
// Do nothing
}
#define MDL_UPDATE
static void mdlUpdate(SimStruct *S, int_T tid)
{
real_T time = ssGetT(S); // Get the current simulation time
// Get the input value
const real_T *u = (const real_T*) ssGetInputPortRealSignal(S, 0); // Input pointer
real_T input_value = u == nullptr ? -1 : u[0]; // Read the input value
// Get the file pointer from the work vector
FILE *file = (FILE*) ssGetPWorkValue(S, 0);
if (file != NULL) {
fprintf(file, "%f,%f\n", time, input_value); // Write the input value to the file
}
}
static void mdlTerminate(SimStruct *S)
{
// Close the file
FILE *file = (FILE*) ssGetPWorkValue(S, 0);
if (file != NULL) {
fclose(file);
}
}
// Required S-function trailer
#ifdef MATLAB_MEX_FILE
#include "simulink.c" // MEX-file interface mechanism
#else
#include "cg_sfun.h" // Code generation interface
#endifCheck out similar posts by category:
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow