Está en la página 1de 9

El siguiente programa en C, lo generó la herramienta que diseñe (FuzzyPic 1.

0) de acuerdo a un
SLD configurado con el ToolBox de Logica Difusa de Matlab, mas adelante les explico en mas
detalle, por ahora se los pongo para que lo miren bien y tengan una idea general de la manera
como esta hecho el Sistema Lógico Difuso tipo Mamdani en C y me comenten.

Como buenos colegas, caballeros y personas de bien que somos, y como estudiante de Maestría
y amante de la Ciencia, les digo que saber reconocer el trabajo de los demás es cuestión de ética
y honradez, así que si a alguien le sirve lo mencionado acá, sepan referenciar y respetar los
derechos de autor. Muchas gracias.

El siguiente Sistema Lógico Difuso es un Control de Temperatura para una Incubadora, mas
adelante les visualizo bien los conjuntos difusos, las reglas, etc.

/*******************************************************************************
*
*   FUZZY PIC 1.0 - SISTEMA LOGICO DIFUSO TIPO MAMDANI PARA EL PIC18F452        *
*   Entradas: 2 Salidas: 1                                          *
********************************************************************************
*
*   Autor: Sebastian F. Puente Reyes                      *
*   Trabajo De Grado: Modulo de desarrollo para la implementacion en   *
*                     microcontrolador,de Sistemas Logicos Difusos tipo Mamdani   *
*   Universidad de los Llanos. Mayo de 2007, Villavicencio - Colombia                  *
********************************************************************************
/

//-------------------------------------------------------------------------------
#include <p18f452.h>
#include <adc.h>
#include <math.h>
#include <delays.h>

//-------------------------------------------------------------------------------
#pragma config OSC = HSPLL, OSCS = OFF
#pragma config WDT = OFF
#pragma config PWRT = ON
#pragma config LVP = OFF

//-------------------------------------------------------------------------------
int in1,in2;
float norma1,norma2;
char tipo_conjunto;
unsigned char n;
unsigned char f;
unsigned char limite;
unsigned char muestras = 80;
const float paso = 0.0125;
float maxana = 1023;
float maxdig = 255;
float a,b,c,d;
float
grado,
area,
pond,
sal_regla,
soporte,
tempo,
crisp
;

//-------------------------------------------------------------------------------
#pragma udata bigdata
float salida[80];
#pragma udata

#pragma romdata segdata1


rom float conj11[] = {0.2017,0.138,0,0,3};
rom float conj12[] = {0.1062,0.5,0,0,3};
rom float conj13[] = {0.1168,0.863,0,0,3};
#pragma romdata

#pragma romdata segdata2


rom float conj21[] = {0.1344,0.092,0,0,3};
rom float conj22[] = {0.07088,0.333,0,0,3};
rom float conj23[] = {0.07219,0.5,0,0,3};
rom float conj24[] = {0.07054,0.667,0,0,3};
rom float conj25[] = {0.07797,0.908,0,0,3};
#pragma romdata

#pragma idata consal = 0x100


float sal1[] = {0,0,0.12667,0.5,2,0,0.5};
float sal2[] = {0.12667,0.5,0.87333,0,1,0.12667,0.87333};
float sal3[] = {0.5,0.87333,1,1,2,0.5,1};
#pragma idata
#pragma idata grado = 0x200
float per1[] = {0,0,0};
float per2[] = {0,0,0,0,0};
#pragma idata

//-------------------------------------------------------------------------------
void setup(void);
void salida_cero(void);
void conversor(void);
void fusificacion(void);
void reglas(void);
void inferencia(float uno, float dos, float *conjsal);
float desfusificacion(float *fp);
float evaluafp(float num, rom float *param, float *parametros);

//-------------------------------------------------------------------------------
void main(void)
{
   setup();
   while(1)
   {
      salida_cero();
      conversor();
      fusificacion();
      reglas();
      crisp = desfusificacion(salida);
      PORTD = crisp * 255;
   }
}

//-------------------------------------------------------------------------------
void setup(void)
{
   TRISD = 0;
}

//-------------------------------------------------------------------------------
float evaluafp(float num, rom float *param, float *parametros)
{
   if(param == 0)
   {
      a = parametros[0];
      b = parametros[1];
      c = parametros[2];
      d = parametros[3];
      tipo_conjunto = parametros[4];
   }
   else
   {
      a = param[0];
      b = param[1];
      c = param[2];
      d = param[3];
      tipo_conjunto = param[4];
   }

   switch(tipo_conjunto)
   {
      case 1:      if(num < a)
               { grado = 0; break; }
               if(num > c)
               { grado = 0; break; }
               if(num >= a && num <=b)
               { grado = (num - a) / (b - a); break; }
               if(num >= b && num <= c)
               { grado = (c - num) / (c - b); break; }
               break;

      case 2:      if(num < a)


               { grado = 0; break; }
               if(num > d)
               { grado = 0; break; }
               if(num >= b && num <=c)
               { grado = 1; break; }
               if(num >= a && num <= b)
               { grado = (num - a) / (b - a); break; }
               if(num >= c && num <= d)
               { grado = (d - num) / (d - c); break; }
               break;

      case 3:      grado = ((num - b) * (num - b)) / (2 * a * a);


               grado = exp(-grado);
               break;
      default:   grado = 0;
               break;
   }
   return(grado);
}

//-------------------------------------------------------------------------------
void fusificacion(void)
{
   norma1 = in1 / maxana;
   norma2 = in2 / maxana;

   per1[0] = evaluafp(norma1,conj11,0);
   per1[1] = evaluafp(norma1,conj12,0);
   per1[2] = evaluafp(norma1,conj13,0);

   per2[0] = evaluafp(norma2,conj21,0);
   per2[1] = evaluafp(norma2,conj22,0);
   per2[2] = evaluafp(norma2,conj23,0);
   per2[3] = evaluafp(norma2,conj24,0);
   per2[4] = evaluafp(norma2,conj25,0);
}

//-------------------------------------------------------------------------------
void reglas(void)
{
   inferencia(per1[0],per2[0],sal3);
   inferencia(per1[0],per2[1],sal3);
   inferencia(per1[0],per2[2],sal3);
   inferencia(per1[0],per2[3],sal2);
   inferencia(per1[0],per2[4],sal1);
   inferencia(per1[1],per2[0],sal2);
   inferencia(per1[1],per2[1],sal2);
   inferencia(per1[1],per2[2],sal1);
   inferencia(per1[1],per2[3],sal1);
   inferencia(per1[1],per2[4],sal1);
   inferencia(per1[2],per2[0],sal1);
   inferencia(per1[2],per2[1],sal1);
   inferencia(per1[2],per2[2],sal1);
   inferencia(per1[2],per2[3],sal1);
   inferencia(per1[2],per2[4],sal1);
}

//-------------------------------------------------------------------------------
void inferencia(float uno, float dos, float *conjsal)
{
   if(uno == 0 || dos == 0) return;

   if(uno > 0 && dos > 0)


   {
      if(uno < dos) sal_regla = uno;
      else sal_regla = dos;
   }

   soporte = conjsal[5];
   f = conjsal[5] * muestras;
   limite = conjsal[6] * muestras;

   for(f; f < limite; f++)


   {
      tempo = evaluafp(soporte,0,conjsal);
      if(tempo >= sal_regla) tempo = sal_regla;
      if(tempo > salida[f]) salida[f] = tempo;
      soporte = soporte + paso;
   }
}

//-------------------------------------------------------------------------------
float desfusificacion(float *fp)
{
   area = 0;
   pond = 0;
   soporte = 0;

   for(n = 0; n < muestras; n++)


   {
      if(fp[n] == 0)
      {
         soporte = soporte + paso;
         continue;
      }
      area = fp[n] + area;
      pond = fp[n]*soporte + pond;
      soporte = soporte + paso;
   }

   if(pond == 0 && area == 0) return(0);


   else return(pond / area);
}

//-------------------------------------------------------------------------------
void conversor(void)
{
   OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_7ANA_1REF,
         ADC_CH0 & ADC_INT_OFF);
   Delay10TCYx(10);
   ConvertADC();
   while ( BusyADC() );
   in1 = ReadADC();

   SetChanADC( ADC_CH1 );
   Delay10TCYx(10);
   ConvertADC();
   while( BusyADC() );
   in2 = ReadADC();
}

//-------------------------------------------------------------------------------
void salida_cero(void)
{
   for(n = 0; n < muestras; n++)
   {
      salida[n] = 0;
   }
}

Este programa es propiedad intelectual de Sebastian Puente Reyes


y hace parte del trabajo de grado: Módulo de desarrollo para la implementación
en microcontrolador, de Sistemas Lógicos Difusos tipo Mamdani del mismo autor.
Bien, si se hace la lógica difusa en matlab se necesita crear una tabla de datos que relacione las
entradas y la salida o look up table, que es la que se inserta en el micro.
Para hacer esto, se necesita crear un pequeño programa en el mismo matlab que vaya evaluando
cada entrada para ver el resultado de salida. El comando que se utiliza para evaluar el archivo *.fis
es el evalfis() y debe ser guardado en una matriz donde se muestren los valores evaluados de
entradas con su correspondiente salida.

El proyecto es de la siguiente Manera:

A este Sistema lo llame FuzzyPic 1.0

Involucra dos subsistemas o partes, las cuales, poseen las siguientes especificaciones
generales.

Especificaciones Del Sistema Lógico Difuso Tipo Mamdani General

Como parte fundamental del Módulo se desarrollo el código en C para un Sistema Lógico
Difuso tipo Mamdani en forma general. Algunas partes del código son modificadas por
medio del software del Módulo de acuerdo a las características fijadas por el usuario. Las
partes que se modifican son las siguientes:

   Definición de los conjuntos difusos. Esta parte se modifica de acuerdo al número de


conjuntos difusos, al tipo de cada uno de los conjuntos y a sus respectivos parámetros.

   Obtención de las entradas. De acuerdo al tipo de entradas; análogas o digitales, el


código será modificado para la debida lectura de cada una de las entradas del Sistema.

   Base de Reglas. De acuerdo a las reglas difusas establecidas durante el diseño del
Sistema Lógico Difuso por el usuario, se creará la base de reglas específica siguiendo la
forma general establecida en la creación del código general o estándar para el Sistema
Lógico Difuso (SLD).

   Ajustes específicos. Las partes del código que dependen del número de entradas, los
respectivos conjuntos y el número de reglas, el código será ajustado de acuerdo a estas
características.

El código general del SLD puede manejar las siguientes características: (Bueno Aclaro que
esto lo fije de acuerdo al PIC18F452 viendo sus prestaciones y limitaciones)

   Tipos de conjuntos difusos: triangular, trapezoidal y gaussiano.


   Número de entradas: Se pueden tener como máximo 3 entradas.
   Tipo de SLD: Tipo Mamdani.
   Tipo de Sistemas: Sistemas tipo MISO (Múltiples entradas y única salida).
   Conector Antecedentes de las reglas: conector AND.
   Evaluación Antecedentes: Operador MÍNIMO.
   Método Implicación: Operador MÍNIMO.
   Método Agregación: Operador MÁXIMO.
   Método Desdifusión: CENTROIDE.

Especificaciones Del Software Del Modulo

El software para el Módulo denominado FuzzyPic 1.0 es el encargado de recibir todas las
características específicas; definición de las variables de entrada y la variable de salida,
definición de los conjuntos difusos que conforman cada variable, reglas difusas o base de
conocimiento, tipos de conjuntos difusos a usar entre otras, requeridas por el usuario para el
diseño del Sistema Lógico Difuso (SLD) deseado.

El diseño del SLD se realiza mediante la integración de las diferentes funciones que ofrece
el Fuzzy Logic Toolbox de Matlab. Después de especificar el SLD deseado, el software
procede a verificar todas las características vistas en la sección anterior para proceder a
crear el código en C del SLD. En la figura 3.1 pude verse el diagrama en bloques del
software desarrollado en Matlab para el Módulo.

Diagrama en Bloques general del software para el Módulo.

Requerimientos de Sistema

Debido a que el software se desarrollo en Matlab, los requerimientos de sistema necesarios,


son los mismos que los de este lenguaje. Necesita por supuesto, que Matlab esté instalado
en la PC.

yo pude lograr todo eso, pero la tabla no la puedo declarar en el micro y no se cual es la razón!!!
estoy trabajando con un pic 16f877 y estoy programando en C. si alguien me puede ayudar a
resolver este inconveniente se lo agradecería muchísimo.

También podría gustarte