Professor Luciano Bertini

Professor da Universidade Federal Fluminense – Campus Rio das Ostras

E-mail: lbertini @id.uff.br
Departamento de Ciência da Computação (RCM)
Instituto de Ciência e Tecnologia (ICT)

Pólo Universitário de Rio das Ostras
Universidade Federal Fluminense

Controlador Fuzzy em C

O controlador apresentado abaixo foi testado no controle de velocidade de um motor BLDC de CDROM, no controle de velocidade. Foi comparado com um controlador PID implementado utilizando transformada Z e testado com diferentes parâmetros de integração. O resultado do controle e um caso de ativação de regras podem ser vistos nas figuras anbaixo:

 

Código:

/*
Codigo de um controlador Fuzzy com dois precedentes conectados pelo operador AND.
SISTEMAS EMBARCADOS E COMPUTAÇÃO UBÍQUA
MESTRADO EM ENGENHARIA DE PRODUÇÃO E SISTEMAS COMPUTACIONAIS – MESC
Luciano Bertini */


#include <stdio.h>

// Define a estrutura para um conjunto fuzzy triangular, sendo que a ou c podem ser +infinito ou -infinito (INF)
struct membership{
    float a;
    float b;
    float c;
};

//Definição de infinito
#define INF 1e+6

#define NUM1 5  //Numero de conjuntos na variavel de entrada 1
#define NUM2 5  //Numero de conjuntos na variavel de entrada 2
#define NUM3 5  //Numero de conjuntos na variavel de saida

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

// Função membership de entrada. r[] é o vetor de pertinencias que será preenchido.
// x é o valor sendo fuzificado. z[] é o vetor de conjuntos fuzzy em todo universo de discurso X
// n é o tamanho do vetor
void test_membership_in(float r[], float x, struct membership z[], int n)
{
    int i;
    for(i=0;i<n;i++)
    {
         if(x<=z[i].a||x>=z[i].c)
            r[i] = 0.0;
         else if(x>z[i].a&&x<=z[i].b)
            r[i] = (x-z[i].a)/(z[i].b-z[i].a);
         else if(x>z[i].b&&x<z[i].c)
            r[i] = (z[i].c-x)/(z[i].c-z[i].b);
    }
}


// Obtem o valor da membership de saida após a inferência fuzzy. O vetor r[] é entrada e cada valor é 
// o nível de ativação de cada conjunto fuzzy, obtido na inferencia. Variando-se x em todo universo de discurso, 
// obtem-se a membership de saida
float test_membership_out(float r[],float x, struct membership z[], int n)
{
    float v, ret=0.0;
    int i;
    for(i=0;i<n;i++)
    {
         if(x<=z[i].a||x>=z[i].c)
            v = 0.0;
         else if(x>z[i].a&&x<=z[i].b)
            v = MIN((x-z[i].a)/(z[i].b-z[i].a),r[i]); // seleciona o minimo entre o nivel de ativação e o triangulo do conjunto fuzzy
         else if(x>z[i].b&&x<z[i].c)
            v = MIN((z[i].c-x)/(z[i].c-z[i].b),r[i]); // seleciona o minimo entre o nivel de ativação e o triangulo do conjunto fuzzy
         ret=MAX(ret,v); // O maximo aqui faz o OU entre dois conjuntos fuzzy i-1 e i
    }
    return ret;
}
main()
{
    int i,j;
    float de=1.7, e=-1.4;
    float x,sum1=0.0,sum2=0.0, val, v;
    float mi1[NUM1],mi2[NUM2],out[NUM3]={0,0,0,0,0};

   // Definição dos conjuntos fuzzy
   struct membership e1[NUM1]={
        { -INF, -8.0, -4.0},
        { -5.0, -3.0, -1.0},
        { -2.0,  0.0,  2.0},
        {  1.0,  3.0,  5.0},
        {  4.0,  8.0,  INF}};

    struct membership e2[NUM2]={
        { -INF, -8.0, -4.0},
        { -5.0, -3.0, -1.0},
        { -2.0,  0.0,  2.0},
        {  1.0,  3.0,  5.0},
        {  4.0,  8.0,  INF}};

    struct membership s[NUM3]={
        {-20.0, -10.0, -6.0},
        { -7.0,  -4.0, -1.0},
        { -2.0,   0.0,  2.0},
        {  1.0,   4.0,  7.0},
        {  6.0,  10.0, 20.0}};


    // Mapa de regras
    int regras[NUM1][NUM2]={ //horizontal Delta do erro
        {4,4,3,3,2},         //vertical erro
        {4,3,3,2,1},
        {3,3,2,1,1},
        {3,2,1,1,0},
        {2,1,1,0,0}};

    // Inicialização
    sum1=0;
    sum2=0;
    for(i=0;i<NUM3;i++)out[i]=0;

    // Fuzificação
    test_membership_in(mi1,e,e1,NUM1);
    test_membership_in(mi2,de,e2,NUM2);

    // Inferencia Fuzzy
    // O minimo aqui pega o menor dos graus de pertinencias, supondo regras com dois precedentes conectados pelo operador AND
    // O máximo aqui é util quando um certo conjunto fuzzy de saída já foi ativado antes por outra regra e neste caso deve-se selecionar o maior (OR).
    for(i=0;i<NUM1;i++)
        for(j=0;j<NUM2;j++)
            if(mi1[i]>0&&mi2[j]>0)
                out[regras[i][j]] = MAX(MIN(mi1[i],mi2[j]), out[regras[i][j]]); 

    // Defuzificação
    // Calculo do centroide
    for(x=-10.0;x<=10.01;x+=0.05)
    {
        val=test_membership_out(out, x, s, NUM3);
        sum1+=x*val;
        sum2+=val;
    }
    x=sum1/sum2;
    printf("saida=%f\n",x);
}

 

 

Copyright ©2017 - STI - Todos os direitos reservados

Skip to content