Multiple instances of c_block in one Scilab/Xcos simulation

212 Views Asked by At

I have hit a problem regarding the Xcos c_block usage. I have developed a c_block with following C code:

#include <machine.h>
#include <math.h>

void Ramp(flag,nevprt,t,xd,x,nx,z,nz,tvec,
             ntvec,rpar,nrpar,ipar,nipar
      ,u1,nu1,y1,ny1)
 
 
      double *t,xd[],x[],z[],tvec[];
      int *flag,*nevprt,*nx,*nz,*ntvec,*nrpar,ipar[],*nipar,*nu1,*ny1;
      double rpar[],u1[],y1[];
/* modify below this line */
{

static double target     = 0;
static double inputDelta = 0;
static double out        = 0;

if(u1[0] != target)
{
        target = u1[0];

        if(target - y1[0] < 0)
        {
                inputDelta = y1[0] - target;
        }
        else
        {
                inputDelta = target - y1[0];
        }
}

if(target > y1[0])
{
        out += inputDelta*rpar[2]/rpar[0];
        if(out > target)
        {
                out = target;
        }
}
else if(target < y1[0])
{
        out -= inputDelta*rpar[2]/rpar[1];
        if(out < target)
        {
                out = target;
        }
}
       
y1[0] = out;

}

Xcos simulation containing this block works:

enter image description here

My problem is that I need to have multiple instances of this block in one Xcos simulation (each instance with different set of parameters). I have tried to make several copies of this block and set different values of parameters for each copy. This naive approach resulted in wrong behavior of all the instances (all the instances gave exactly the same output but this output did not correspond to any set of parameters).

My question is whether it is ever possible to have multiple instances of one c_block in one simulation? If so, can anybody give me an advice how to do that?

1

There are 1 best solutions below

0
On BEST ANSWER

The answer is that it is possible to have multiple instances of one block containing the c code in a given simulation. I have got up and running that with the CBLOCK4 block and usage of the work pointer in the scicos_block structure. This pointer contains address somewhere on the heap where the persistent data of the CBLOCK4 are stored. Below is the modification of the code above

#include "scicos_block4.h"

#define U  ((double *)GetRealInPortPtrs(block, 1))
#define Y  ((double *)GetRealOutPortPtrs(block, 1))

// parameters
#define Tu (GetRparPtrs(block)[0])
#define Td (GetRparPtrs(block)[1])
#define T  (GetRparPtrs(block)[2])

typedef struct
{
    double target;
    double inputDelta;
    double out;
}Ramp_work;

void Ramp(scicos_block *block, int flag)
{
 
  Ramp_work *work;

  if(flag == 4) 
  {
    /* init */
    if((*(block->work) = (Ramp_work*)scicos_malloc(sizeof(Ramp_work))) == NULL)
    {
        set_block_error(-16);
        return;
    }
    work = *(block->work);          
    work->target      = 0;
        work->inputDelta  = 0;
    work->out         = 0;

  }
  else if(flag == 1) 
  {

    work = *(block->work);  

    /* output computation */ 
    if(U[0] != work->target)
    {
        work->target = U[0];
        
        if(work->target - Y[0] < 0)
        {
            work->inputDelta = Y[0] - work->target;
        }
        else
        {
            work->inputDelta = work->target - Y[0];
        }
    }
    
    if(work->target > Y[0])
    {
        work->out += work->inputDelta*T/Tu;
        if(work->out > work->target)
        {
            work->out = work->target;
        }
    }
    else if(work->target < Y[0])
    {
        work->out -= work->inputDelta*T/Td;
        if(work->out < work->target)
        {
            work->out = work->target;
        }
    }
    
    Y[0] = work->out;  

  } 
  else  if (flag == 5) 
  {
    /* ending */
    scicos_free(*(block->work));
  }

}