Bueno, Hola a todos
Que pena por tener tan abandonado este foro, pero por cuestiones de mi Maestría no he tenido mucho tiempo de sentarme aquí y seguir compartiendo con todos ustedes.
Bueno ante la solicitud de algunos participantes del foro de que les envié el programa, tome la siguiente decisión:
Voy a poner acá en el foro, como pueden hacer un Sistema Lógico Difuso tipo Mamdani en C, especialmente para el PIC18F452, pero igual haciendo algunas modificaciones pues podrá ser valido para cualquier PIC 18F. no pondre el programa total que realize (FuzzyPic 1.0) por el momento, cuestiones de derecho de autor, pero si les pondre un ejemplo de un Sistema Lógico Difuso hecho en C y lo iré explicando paso a paso.
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.
Villavicencio, Bogotá, COLOMBIA