Carro Controlado mediante Lógica Difusa
Hola chicos!!, Bienvenidos nuevamente a mi blog, el día de hoy les explicare como armar un carro controlado mediante la Lógica Difusa, cuya programación será en Arduino.
El control Fuzzy esta basado en la toma de decisiones, esto lo hace una tecnología accesible, ya que las reglas están mas cerca del sentido común que de algún modelo matemático o ecuaciones.
Varios artefactos que usamos hoy en día, están basados en la lógica difusa, por ejemplo, nuestras lavadoras las programamos para que el agua que utilicemos para lavar nuestra ropa este a 37°C, si el agua que entra esta abajo de esta temperatura, automáticamente el calefactor se prenderá para poder llegar a esta temperatura, una vez alcanzado los 37°C el calefactor automáticamente se apagara.
Con estas mismas reglas esta basado el funcionamiento del carro, el carro avanzará a una velocidad alta a una media y lenta, para que cuando el carro mediante el sensor ultrasónico llegue a detectar un objeto a una distancia de 15cm., el auto se detenga; la distancia de paro puede ser variada modificando los conjuntos difusos.
Explicaré paso a paso como programar cada una de las etapas en Arduino.
Carro controlado mediante lógica difusa |
Materiales
* Sensor ultrasónico SFR05* Arduino UNO
* Carro con 3 llantas, la de frente es una rueda loca, y un par de llantas traseras con motoreductores
Procedimiento
Escribimos las librerías en Arduino que perteneces al Control Fuzzy y al sensor ultrasónico.
//
*** ADRIANA ***
//
// ***
CONTROL NEURODIFUSO
*** //
// *** CARRO CONTROLADO CON LOGICA DIFUSA ***
//
#include <FuzzyRule.h>
#include <FuzzyComposition.h>
#include <Fuzzy.h>
#include <FuzzyRuleConsequent.h>
#include <FuzzyOutput.h>
#include <FuzzyInput.h>
#include <FuzzyIO.h>
#include <FuzzySet.h>
#include <FuzzyRuleAntecedent.h>
#include
"Ultrasonic.h"
Asignamos los pines del Arduino donde estarán conectados a los pines de entrada de nuestro puente-H, de esta manera podremos controlar ambos motoreductores.
const int enPin = 5; // PWM se conecta al pin 1 del puente-H
const int in1Pin = 2; // Entrada 2 del
puente-H
const int in2Pin = 4; // Entrada 7 del
puente-H
Y el sensor ultrasónico.
Ultrasonic ultrasonico(7,8);
Fuzzy* fuzzy = new Fuzzy(); //Iniciando objeto
Creamos los conjuntos difusos.
FuzzySet* demcerca = new FuzzySet(-20, -10, 5,
9); //Conjunto difuso Distancia
demasiado cerca
FuzzySet* muycerca = new FuzzySet(14.5, 15,
15.5, 16); //Conjunto difuso Distancia
muy cerca
FuzzySet* cerca = new FuzzySet(15.5, 20, 40,
50); //Conjunto difuso Distancia
cerca
FuzzySet* media = new FuzzySet(45, 50, 70,
80); //Conjunto difuso Distancia
promedio
FuzzySet* lejos = new FuzzySet(75, 80, 103,
103); //Conjunto difuso Distancia lejos
FuzzySet* Alto = new
FuzzySet(0, 0, 0, 0); //
Velocidad para detener
FuzzySet* Suave = new FuzzySet(0,
200, 500, 700); // Velocidad
suave
FuzzySet* Media = new FuzzySet(600, 1200,
1800, 2000); // Velocidad medio
FuzzySet* Rapida = new FuzzySet(1900, 2200,
3000, 3500); // Velocidad rápido
int dist;
Después de haber creado los conjuntos difusos, dentro del void setup() crearemos las entradas y las salidas de nuestros conjuntos DISTANCIA y VELOCIDAD.
void setup(){
Serial.begin(9600);
pinMode(in1Pin, OUTPUT); //Configura in1Pin
como salida
pinMode(in2Pin, OUTPUT); //Configura in2Pin como salida
//Crear composición de
entrada difusa distancia
FuzzyInput* distance = new FuzzyInput(1);
distance->addFuzzySet(demcerca); //Agrega
fuzzyset demasiado cerca a distancia
distance->addFuzzySet(muycerca); //Agrega
fuzzyset muy cerca a distancia
distance->addFuzzySet(cerca); //Agrega fuzzyset cerca a distancia
distance->addFuzzySet(media); //Agrega fuzzyset media a distancia
distance->addFuzzySet(lejos); //Agrega fuzzyset lejos a distancia
fuzzy->addFuzzyInput(distance); //Agrega entrada difusa al objeto difuso
//Crear composición de entrada difusa vel
FuzzyInput* vel = new FuzzyInput(2);
vel->addFuzzySet(Alto); // Agregar
fuzzyset paro
vel->addFuzzySet(Suave);// Agregar
fuzzyset lento
vel->addFuzzySet(Media);// Agregar fuzzyset medio
vel->addFuzzySet(Rapida);//Agregar
fuzzyset rapido
fuzzy->addFuzzyInput(vel);// Agrega
entrada difusa al objeto difuso
//Crear composición de
salida difusa velocidad
FuzzyOutput* salPWM = new
FuzzyOutput(1); //Crea salida difusa
velocidad
FuzzySet* rev = new FuzzySet(-4, -4, -3, 0);
salPWM->addFuzzySet(rev);// Agregar
fuzzyset paro a velocidad
FuzzySet* paro = new FuzzySet(-.5, 1, 1.5,
4);
salPWM->addFuzzySet(paro);// Agregar fuzzyset paro a
velocidad
FuzzySet* lenta = new FuzzySet(3.9,
5, 5.5, 6);
salPWM->addFuzzySet(lenta);// Agregar
fuzzyset lento a velocidad
FuzzySet* medio = new FuzzySet(5.5, 6, 7, 8);
salPWM->addFuzzySet(medio);// Agregar
fuzzyset medio a velocidad
FuzzySet* rapido = new FuzzySet(7.5, 9, 9,
9);
salPWM->addFuzzySet(rapido);//Agregar fuzzyset
rapido a velocidad
fuzzy->addFuzzyOutput(salPWM);// Agrega entrada difusa al objeto difuso
Una vez realizada la fuzzificación evaluamos las reglas difusas.
// Arma las reglas difusas. (Distancia)
// FuzzyRule 1 "IF distancia = muy cerca THEN salPWM = Paro"
FuzzyRuleAntecedent* ifdistancemuycerca = new
FuzzyRuleAntecedent(); // Inicializando antecedente de la expresión
ifdistancemuycerca->joinSingle(muycerca);
// Agregando FuzzySet correspondiente al antecedente
FuzzyRuleConsequent* thensalPWMparo = new
FuzzyRuleConsequent(); // Inicializando consecuencia de la expresión
thensalPWMparo->addOutput(paro); //
Agregando FuzzySet correspondiente a la consecuencia
// Instantiating a FuzzyRule object
FuzzyRule* fuzzyRule01 = new
FuzzyRule(1, ifdistancemuycerca, thensalPWMparo);
fuzzy->addFuzzyRule(fuzzyRule01); // Agrega regla
difusa al objeto difuso.
// FuzzyRule
"IF distance = cerca THEN salPWM = lenta"
FuzzyRuleAntecedent* ifdistancecerca = new
FuzzyRuleAntecedent(); // Inicializando antecedente de la expresión
ifdistancecerca->joinSingle(cerca); //
Agregando FuzzySet correspondiente al antecedente
FuzzyRuleConsequent* thensalPWMlenta = new
FuzzyRuleConsequent(); // Inicializando consecuencia de la expresión
thensalPWMlenta->addOutput(lenta);//
Agregando FuzzySet correspondiente a la consecuencia
// Instantiating a FuzzyRule object
FuzzyRule* fuzzyRule02 = new
FuzzyRule(2, ifdistancecerca, thensalPWMlenta);
fuzzy->addFuzzyRule(fuzzyRule02); // Agrega regla
difusa al objeto difuso.
de la misma manera creamos las reglas difusas para la distancia media, distancia cerca y demasiado cerca.
Programación del Sensor Ultrasónico SFR05
void loop(){
float dist = ultrasonico.Ranging(CM);
int rpm=getRPM();
Serial.println(rpm, DEC);
fuzzy->setInput(1, dist); //Agrega variable de
entrada dist al objeto difuso
fuzzy->setInput(2, rpm); //Agrega variable
de entrada dist al objeto difuso
float a;
float b;
float c;
float d;
a= muycerca->getPertinence();
b= cerca->getPertinence();
c= media->getPertinence();
d= lejos->getPertinence();
fuzzy->fuzzify(); // Fuzificación
Finalmente escribimos los Serial.print(); necesarios para poder mostrar los resultados en nuestro Monitor Serial.
Serial.print("Distancia:
");
Serial.print(dist);
Serial.println(" cm");
Serial.print("Pertenencia a demasiado cerca
(reversa): ");
Serial.println(demcerca->getPertinence());
//Imprime pertencia a conjunto demasiado cerca
Serial.print("Pertenencia a ideal: ");
Serial.println(muycerca->getPertinence());
//Imprime pertencia a conjunto muy cerca
Serial.print("Pertenencia a cerca: ");
Serial.println(cerca->getPertinence()); //Imprime pertencia a conjunto cerca
Serial.print("Pertenencia a media:
");
Serial.println(media->getPertinence()); //Imprime pertencia a conjunto media
Serial.print("Pertenencia a lejos:
");
Serial.println(lejos->getPertinence()); //Imprime pertencia a conjunto lejos
Serial.print("RPM:
");
Serial.println(rpm);
Serial.print("Pertenencia a Alto: ");
Serial.println(Alto->getPertinence());
Serial.print("Pertenencia a Lenta: ");
Serial.println(Suave->getPertinence());
Serial.print("Pertenencia a Media:
");
Serial.println(Media->getPertinence());
Serial.print("Pertenencia a Rapida:
");
Serial.println(Rapida->getPertinence());
Serial.print("Salida:
");
Serial.println(output1);
Serial.println("");
int ch = output1;
int speed = map(ch, 0, 9, 0, 255);
if ((ch <= 0))
{
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,HIGH);
Serial.println(speed);
analogWrite(enPin, speed); }
else if ((ch >= 0))
{
digitalWrite(in1Pin,HIGH);
digitalWrite(in2Pin,LOW);
Serial.println(speed);
analogWrite(enPin, speed);
}
delay(200);
}
Para que nuestro auto tenga un
sentido de giro con forme a las manecillas del reloj y anti horario,
caracterizamos la salida mapeando con valores de 0 a 9, los cuales hacen
referencia el rango que va de 0 a 255 bits del PWM, donde el 9 es el valor más
rápido y cero el mínimo valor.
Como pueden ver, el sistema de control del carro está basado en la evaluación de reglas, utilizando lógica difusa, su implementación es muy sencilla, ya que describimos su comportamiento mediante reglas, no es necesario realizar una modelización exacta, sino que basta con entender conceptualmente su comportamiento. Está característica lo hace particularmente apropiado para sistemas muy alineales, cuya modelización por los métodos tradicionales suele ser compleja. Diseñar sistemas borrosos es fácil, ya que reflejan de una manera general lo que la gente realmente piensa de un problema.
Gracias por leerme :)
Que tengan lindo día.