Ejemplo de S-Function de Matlab: Leer entrada double y escribir a archivo

Este es un ejemplo de una S-Function de Matlab Level-2 que lee una sola entrada continua de tipo double y la escribe al archivo out.txt como CSV time,value. El archivo se abre en la función mdlStart y se cierra en la función mdlTerminate. El valor de entrada se lee en la función mdlUpdate.

Ver también Ejemplo de Matlab Level 2 S-Function: Onda senoidal (salida continua).

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

// Definir constantes
#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 puerto de entrada con 1 elemento
    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

    // Sin puertos de salida
    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

    // Hacer el bloque S-function capaz de ser usado en un modelo generado por Real-Time Workshop
    ssSetOptions(S, 0);
}

#define MDL_START
static void mdlStart(SimStruct *S) {
    // Abrir el archivo "out.txt" para escritura
    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:
//    Inicializar los sample times a 1ms (1kHz)
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, 1.0 / SAMPLING_RATE);  // 1kHz sampling rate
    ssSetOffsetTime(S, 0, 0.0);
}

// No necesario para este ejemplo
static void mdlOutputs(SimStruct *S, int_T tid) {
    // No hacer nada
}

#define MDL_UPDATE
static void mdlUpdate(SimStruct *S, int_T tid)
{
    real_T time = ssGetT(S);  // Get the current simulation time

    // Obtener el valor de entrada
    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

    // Obtener el puntero de archivo del 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)
{
    // Cerrar el archivo
    FILE *file = (FILE*) ssGetPWorkValue(S, 0);
    if (file != NULL) {
        fclose(file);
    }
}

// Trailer requerido de S-function
#ifdef MATLAB_MEX_FILE
#include "simulink.c"   // MEX-file interface mechanism
#else
#include "cg_sfun.h"    // Code generation interface
#endif

Echa un vistazo a artículos similares por categoría: