[C][Scilab]Conversion d'un programme Scilab en C

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’essaie de convertir ce programme scilab qui effectue une simulation de régulation et qui fonctionne:

// essai MPC kindergarten ordre 1 ave perturbatio,

clear; xdel(winsid());
tf= 1500; w=1:1:tf; // uuree
tech=1;
// nitialisation
u=zeros(1,tf);
MV=u; CV=u; sm=u; DV=u; SP=u; r=200;
// odele et process
taum=35; am=exp(-tech/taum); bm=1-am; Km=1.7; // modele
taup=35; ap=exp(-tech/taup); bp=1-ap; Kp=1.7; // process
// acteur essentielle de reglage temps de reponse desire boucle ferme
TRBF=45; lh=1-exp(-tech*3/TRBF); 
//
for ii=2+r:1:tf
    if ii<700 then DV(ii)=0; else DV(ii)=20; end; // erturbation
    SP(ii)=100; // consigne
    CV(ii)=ap*CV(ii-1)+bp*(Kp*MV(ii-1-r)+DV(ii)); // process
    sm(ii)=am*sm(ii-1)+bm*Km*MV(ii-1); // modele
    spred=CV(ii)+(sm(ii)-sm(ii-r))*1; // prediction
    d=(SP(ii)-spred)*lh+sm(ii)*bm;
    MV(ii)=d/(Km*bm); // ariable manipule
    // limites physique systeme
    if MV(ii)>70 then MV(ii)=70; end;
    if MV(ii)>MV(ii-1)+4 then MV(ii)=MV(ii-1)+4; end;
    if MV(ii)<MV(ii-1)-4 then MV(ii)=MV(ii-1)-4; end;
end
//
scf(0);
plot(w,MV,"b",w,CV,"r",w,SP,"k",w,DV,"m");
a=gca(); a.grid=[1,1]; a.tight_limits="on"; a.data_bounds=[1,0;1500,150];
xlabel("sec");
title("MV bleu, CV rouge consigne noir, DV m, R=200 !, limites: abs=60 / vitesse=4");

en un programme en C. J’ai essayé de séparer la partie simulation du régulateur car maintenant que je l’ai testé en simulation, j’aimerai l’utiliser pour des applications réelles:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

float PFC(int,int,int,float,float,float,float *);

int main(void)
{
  float sortie_precedente[200];//buffer= r*tech
  float SP=100;
  int tech=1;
  int trbf=45;
  int i=0;//variable de gestion de tableau

  //Simulation processus
  int t=0;//variable simulation temps
  //process
  int taup=35;
  float ap=exp(-tech/taup);
  float bp=1-ap;
  float Kp=1.7;
  int r=200;
  float PV[1500];
  float MV[1500];

  //initialisation tableau de sortie_modele sortie_precedente
  for (i=0;i<200;i++)
  {
    sortie_precedente[i]=0;
  }

  //initialisation PV
  for (i=0;i<200;i++)
  {
    PV[i]=0;
  }

  //initialisation MV
  for (i=0;i<200;i++)
  {
    MV[i]=0;
  }

  //Simulation regulation processus
  for(t=(2+r);t<=1500;t++)
  {
    PV[t]=ap*PV[t-1]+bp*(Kp*MV[t-1-r]); // process
    MV[t]=PFC(tech,trbf,r,PV[t],SP,MV[t-1],sortie_precedente);
  }

  //Affichage de quelques valeurs pour comparer avec simulation scilab
  for(i=0;i<1500;i+=100)
  {
    printf("PV[%d] = %f \n",i,PV[i]);
  }
  return 0;
}
float PFC(int tech,int trbf,int retard,float PV,float SP,float MV_1,float *sortie_precedente)
{

  //initialisation variables
  int i=0;//Variable de gestion du tableau
  int temps=0;
  float d,MV,sm,spred=0;
  float taum=30.0;
  float km=1.0;
  float sm_r=0;

  //Paramètres du modèle
  float am=exp(-tech/taum);
  float bm=1-am;
  float lh=1-exp(-tech*3/trbf);

  //sortie modèle
  sm=am*sortie_precedente[0]+MV_1*bm*km;

  // prediction
  spred=PV+(sm-sortie_precedente[retard-1])*1;

  //Calcul de la MV
  d=(SP-spred)*lh+sm*bm;
  MV=d/(km*bm);

  //Mise a jour du buffer sortie_precedente
  for(i=199;i>0;i--)
  {
      sortie_precedente[i]=sortie_precedente[i-1];
  }
  sortie_precedente[0]=sm;


  //Contraintes liés à la vitesse réelle de l'actionneur
  if (MV>(MV_1+4))
  {
    MV=MV_1+4;
  }
  if (MV<(MV_1-4))
  {
    MV=MV_1-4;
  }

  return MV;
}

Malheureusement la sortie PV qui correspond à la variable à réguler reste à 0. Sauriez vous ce que j’ai fait de mal ?

Merci d’avance pour votre aide :)

+0 -0

En executant ton code dans un debuggeur (https://www.onlinegdb.com/online_c_compiler par exemple), on se rend compte qu’à la ligne 19 float ap=exp(-tech/taup); : exp(-1/35) est arrondi à 1. Donc ap = 1, donc bp = 0, et du coup PV[t] reste à 0.

On peut résoudre ça en remplaçant les int par des float (source : https://stackoverflow.com/a/2345909/3305789) :

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

float PFC(int,int,int,float,float,float,float *);

int main(void)
{
  float sortie_precedente[200];//buffer= r*tech
  float SP=100;
  float tech=1.0;
  float trbf=45.0;
  int i=0;//variable de gestion de tableau

  //Simulation processus
  int t=0;//variable simulation temps
  //process
  float taup=35.0;
  float ap=exp(-tech/taup);
  float bp=1-ap;
  float Kp=1.7;
  int r=200;
  float PV[1500];
  float MV[1500];

  //initialisation tableau de sortie_modele sortie_precedente
  for (i=0;i<200;i++)
  {
    sortie_precedente[i]=0;
  }

  //initialisation PV
  for (i=0;i<200;i++)
  {
    PV[i]=0;
  }

  //initialisation MV
  for (i=0;i<200;i++)
  {
    MV[i]=0;
  }

  //Simulation regulation processus
  for(t=(2+r);t<=1500;t++)
  {
    PV[t]=ap*PV[t-1]+bp*(Kp*MV[t-1-r]); // process
    MV[t]=PFC(tech,trbf,r,PV[t],SP,MV[t-1],sortie_precedente);
  }

  //Affichage de quelques valeurs pour comparer avec simulation scilab
  for(i=0;i<1500;i+=100)
  {
    printf("PV[%d] = %f \n",i,PV[i]);
  }
  return 0;
}
float PFC(int tech,int trbf,int retard,float PV,float SP,float MV_1,float *sortie_precedente)
{

  //initialisation variables
  int i=0;//Variable de gestion du tableau
  int temps=0;
  float d,MV,sm,spred=0;
  float taum=30.0;
  float km=1.0;
  float sm_r=0;

  //Paramètres du modèle
  float am=exp(-tech/taum);
  float bm=1-am;
  float lh=1-exp(-tech*3/trbf);

  //sortie modèle
  sm=am*sortie_precedente[0]+MV_1*bm*km;

  // prediction
  spred=PV+(sm-sortie_precedente[retard-1])*1;

  //Calcul de la MV
  d=(SP-spred)*lh+sm*bm;
  MV=d/(km*bm);

  //Mise a jour du buffer sortie_precedente
  for(i=199;i>0;i--)
  {
      sortie_precedente[i]=sortie_precedente[i-1];
  }
  sortie_precedente[0]=sm;


  //Contraintes liés à la vitesse réelle de l'actionneur
  if (MV>(MV_1+4))
  {
    MV=MV_1+4;
  }
  if (MV<(MV_1-4))
  {
    MV=MV_1-4;
  }

  return MV;
}

Après il reste un problème logique à la ligne 47 : PV[t]=ap*PV[t-1]+bp*(Kp*MV[t-1-r]); // process PV et MV étant initialisés à zéro sur leur 200 premières valeurs, tu vas toujours sommer 0 (en tout cas c’est ce que je constate en mode débug).

+1 -0

Bonjour, Merci pour ton aide, j’ai effectué les modifications du type de variables que tu m’as indiqué et j’ai aussi initialisé les tableaux MV et PV à 20.

La valeur de PV n’est alors plus 0 mais varie de cette façon:

PV[0] = 20.000000 
PV[100] = 20.000000 
PV[200] = 0.000000 
PV[300] = 31.990671 
PV[400] = 33.884636 
PV[500] = 1.946083 
PV[600] = 0.111769 
PV[700] = 0.006419 
PV[800] = 0.000369 
PV[900] = 0.000021 
PV[1000] = 0.000001 
PV[1100] = 0.000000 
PV[1200] = 0.000000 
PV[1300] = 0.000000 
PV[1400] = 0.000000 

Je vais vérifier les blocs de calcul afin de vérifier si l’erreur vient de la. Merci également pour le lien vers le débuggeur, je vais m’en servir pour la suite.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte