quarta-feira, 19 de junho de 2013

Arduino, Lógica Fuzzy!!! Sensacional!!

O arduino, é uma plataforma de desenvolvimento muito simples para grandes aplicações de engenharia.

Mas, a verdadeira beleza das coisas está na simplicidade.

E apesar de inicialmente parecer uma coisa bastante complexa, a lógica fuzzy é bastante simples de implementar utilizando o arduino.

A principal referência está endereço: http://www.zerokol.com/2012/09/arduinofuzzy-uma-biblioteca-fuzzy-para.html. É um excelente tutorial sobre uma biblioteca de lógica fuzzy para qualquer microcontrolador. Para os curiosos, no link acima, tem uma breve explicação sobre fuzzy, um tutorial explicando como instalar a biblioteca, e também algumas explicações e dicas.


Acabei de desenvolver um sistema de controle de luminosidade utilizando lógica fuzzy.

É bem simples!!

Figura 1 - Sistema Iluminação Automática com Fuzzy

O sistema da figura 1 é composto por um divisor de tensão formado por um LDR e uma resistencia, alimentados no +5V (Figura 2). E como fonte de luz, um led com um resistor de limitação de corrente.
Figura 2 - Divisor de tensão com o LDR
 Depois que instalei a biblioteca no meu arduino, começei a editar o exemplo e consegui executar o programa.

Gostaria de compartilhar aqui as regras de  entrada.

No Fuzzy, a programação é assim, por exemplo: Se Escuro Então BrilhoLED Elevado.

Primeiro, criei 3 situações para a  Iluminação : Escuro, Normal e Iluminado. Lembrando que Iluminação é a saída do sensor LDR. E é portanto a variável de entrada do sistema.

E depois criei 3 condições de saída, ou seja, para o brilho do led: Baixo, Medio, Elevado.

E por fim, criei as regras:

          "SE iluminacao = escuro ENTAO Brilho do LED = elevado"

           "SE iluminacao = normal ENTAO Brilho do LED = medio"

           "SE iluminacao = Iluminado ENTAO Brilho do LED = baixo"


Bem, Definidas as minhas regras, aí os próximos passos, vou apenas citar, mas prometo que num próximo tutorial explico tudo, mas adianto que no link que citei no anterior do artigo tem algumas explicações. Em fim, os passos são:

Fuzzyficar, Inferir, Defuzzificar.

No arduino, os comandos utilizados foram:

  float iluminacao_medida = (analogRead(LDR))*0.09765;  //0.09765 = 100/1024
 
  fuzzy->setInput(1,iluminacao_medida  ); // iluminação medida é a variável de entrada
     
  fuzzy->fuzzify();

 int output = fuzzy->defuzzify(1);

   analogWrite(9,output); // onde output é a saída PWM e varia de 0-255

//***********


Resultados Obtidos

Na figura 3a e 3b, o sistema  encontra - se no escuro, logo o Brilho é Elevado.

Figura 3a - Sensor no Escuro - Brilho Elevado 
Na figura 3b, a forma de onda amarela é o sinal de saída do PWM que aciona o LED. E a forma de onda azul é o sinal de tensão divisor de tensão, tal como mostrado na figura 2. 

A forma de onda amarela é o PWM ( 0 à 255) e a curva azul é a tensão do sensor
Figura 3b - Formas de onda - Escuro
 Na figuras 4a e 4b, o sensor está um ambiente iluminado, logo o pwm (curva amarela) é menor, tal como na figura 4b

Figura 4a - Ambiente Iluminado
Figura 4b - Ambiente iluminado -> Brilho Baixo
 A figura 5a mostra uma tentativa de simular uma condição de baixa luminosidade (tampei o sensor com o dedo), mas o sistema não está totalmente escuro.

Figura 5a - Condição de Baixa luminosidade
E por fim, as formas de onda. A tensão no sensor  caiu e o pwm aumentou, aumentando assim o briho do led. 

Figura 5b - Aumento do brilho do LED
***********************************************************************************
Finalizo deixando aqui o código para que você tenha acesso à informação assim como eu tive. Perdoe-me por erros indevidos, e também por algumas coisas que não consegui deixar claro, principalmente em relação ao processo fuzzy. Apesar disso, estou à disposição para tirar dúvidas por email.

Um abraço

**********
#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>


int iluminacao_saida = 0;

int LDR = 5;// Sensor de iluminacao

int initPin = 13;

unsigned long pulseTime = 0;

// Instanciando um objeto da biblioteca
Fuzzy* fuzzy = new Fuzzy();

void setup(){
  Serial.begin(9600);
 
  // set init pin as output
  pinMode(initPin, OUTPUT);
  // set sensor lm35 como entrada


  // create array loop to iterate over every item in the array
  for (int thisReading = 0; thisReading < numOfReadings; thisReading++) {
    readings[thisReading] = 0;
  }
 
  // Criando o FuzzyInput iluminacao
 
  FuzzyInput* iluminacao = new FuzzyInput(1);

  // Criando os FuzzySet que compoem o FuzzyInput iluminacao
 
  FuzzySet* escuro = new FuzzySet(0, 40, 40, 65); // iluminacao escuro 15° 35°
  iluminacao->addFuzzySet(escuro); // Adicionando o FuzzySet escuro em iluminacao

  FuzzySet* normal = new FuzzySet(30, 50, 50, 70); // iluminacao normal
  iluminacao->addFuzzySet(normal); // Adicionando o FuzzySet normal em iluminacao

  FuzzySet* Iluminado = new FuzzySet(60, 80, 80, 100); // iluminacao muito normal
  iluminacao->addFuzzySet(Iluminado); // Adicionando o FuzzySet Iluminado em iluminacao
 
  fuzzy->addFuzzyInput(iluminacao); // Adicionando o FuzzyInput no objeto Fuzzy
 
 
  // Criando o FuzzyOutput Brilho da LED
 
  FuzzyOutput* brilho = new FuzzyOutput(1);
   
    // Criando os FuzzySet que compoem o FuzzyOutput Brilho do LED
   
    FuzzySet* baixo = new FuzzySet(0, 80, 80, 130); // Brilho do LED baixo
    brilho->addFuzzySet(baixo); // Adicionando o FuzzySet baixo em brilho
   
    FuzzySet* medio = new FuzzySet(70, 150, 150, 200); // Brilho do LED normal
    brilho->addFuzzySet(medio); // Adicionando o FuzzySet medio em brilho
   
    FuzzySet* elevado = new FuzzySet(150, 190, 255, 255); // Brilho do LED elevado
    brilho->addFuzzySet(elevado); // Adicionando o FuzzySet elevado em brilho
 
    fuzzy->addFuzzyOutput(brilho); // Adicionando o FuzzyOutput no objeto Fuzzy
 
  //-------------------- Montando as regras Fuzzy
 
  // FuzzyRule "SE iluminacao = escuro ENTAO Brilho do LED = Elevado"
 
  FuzzyRuleAntecedent* ifiluminacaoescuro = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso
  ifiluminacaoescuro->joinSingle(escuro); // Adicionando o FuzzySet correspondente ao objeto Antecedente
 

    FuzzyRuleConsequent* thenbrilhoelevado = new FuzzyRuleConsequent(); // Instancinado um Consenormal para a expressao
  thenbrilhoelevado->addOutput(elevado);// Adicionando o FuzzySet correspondente ao objeto Consenormal
 
 
  // Instanciando um objeto FuzzyRule
  FuzzyRule* fuzzyRule01 = new FuzzyRule(1, ifiluminacaoescuro, thenbrilhoelevado); // Passando o Antecedente e o Consenormal da expressao
  fuzzy->addFuzzyRule(fuzzyRule01); // Adicionando o FuzzyRule ao objeto Fuzzy
 
  // FuzzyRule "SE iluminacao = normal ENTAO Brilho do LED = medio"
  FuzzyRuleAntecedent* ifiluminacaonormal = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso
  ifiluminacaonormal->joinSingle(normal); // Adicionando o FuzzySet correspondente ao objeto Antecedente
 
  FuzzyRuleConsequent* thenbrilhomedio = new FuzzyRuleConsequent(); // Instancinado um Consenormal para a expressao
  thenbrilhomedio->addOutput(medio);// Adicionando o FuzzySet correspondente ao objeto Consenormal
 
  // Instanciando um objeto FuzzyRule
  FuzzyRule* fuzzyRule02 = new FuzzyRule(2, ifiluminacaonormal, thenbrilhomedio); // Passando o Antecedente e o Consenormal da expressao
  fuzzy->addFuzzyRule(fuzzyRule02); // Adicionando o FuzzyRule ao objeto Fuzzy
 
  // FuzzyRule "SE iluminacao = Iluminado ENTAO Brilho do LED = baixo"
 
  FuzzyRuleAntecedent* ifiluminacaoIluminado = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso
  ifiluminacaoIluminado->joinSingle(Iluminado); // Adicionando o FuzzySet correspondente ao objeto Antecedente


   FuzzyRuleConsequent* thenbrilhobaixo = new FuzzyRuleConsequent(); // Instancinado um Consenormal para a expressao
  thenbrilhobaixo->addOutput(baixo);// Adicionando o FuzzySet correspondente ao objeto Consenormal
 
  // Instanciando um objeto FuzzyRule
 
  FuzzyRule* fuzzyRule03 = new FuzzyRule(3, ifiluminacaoIluminado, thenbrilhobaixo); // Passando o Antecedente e o Consenormal da expressao
  fuzzy->addFuzzyRule(fuzzyRule03); // Adicionando o FuzzyRule ao objeto Fuzzy
}

void loop(){
  // send 10 microsecond pulse
  digitalWrite(initPin, HIGH);
  // wait 10 microseconds before turning off
  delayMicroseconds(10);
  // stop sending the pulse
  digitalWrite(initPin, LOW);
 

  float iluminacao_medida = (analogRead(LDR))*0.09765;
 
  fuzzy->setInput(1,iluminacao_medida  );
     
  fuzzy->fuzzify();

 int output = fuzzy->defuzzify(1);
   analogWrite(9,output);

  Serial.print(" iluminacao: ");
  Serial.print(iluminacao_medida);
  Serial.print(" Brilho do LED: ");
  Serial.println(output*0.39215);
  Serial.print(" % ");
  // wait 100 milli seconds before looping again
  delay(100);
}