/**
* fuzzy_controller.ino
**/
// eFLL includes
#include <Fuzzy.h>
#include <FuzzyComposition.h>
#include <FuzzyInput.h>
#include <FuzzyIO.h>
#include <FuzzyOutput.h>
#include <FuzzyRule.h>
#include <FuzzyRuleAntecedent.h>
#include <FuzzyRuleConsequent.h>
#include <FuzzySet.h>
// pins
#define LDR A0
#define TRIGGER 4
#define ECHO 5
#define LED 6
// object library
Fuzzy *fuzzy = new Fuzzy();
void setup() {
// set console and pins
Serial.begin(9600);
pinMode(LDR, INPUT);
pinMode(TRIGGER, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(LED, OUTPUT);
// fuzzy sets
// input1 temp
FuzzySet *cool = new FuzzySet(0, 0, 15, 25); //trapizoid MF (a,b,c,d)
FuzzySet *midt = new FuzzySet(15, 25, 25, 32);
FuzzySet *hot = new FuzzySet(25, 32, 50, 50);
// lnput2 pop
// ldr (0-100000 lux=> 1015-8 resistance value in wokwi)
FuzzySet *low = new FuzzySet(0, 0, 15, 25);
FuzzySet *mid = new FuzzySet(15, 25, 25, 35);
FuzzySet *high = new FuzzySet(25 ,35, 50, 50);
// output1 air comp
FuzzySet *off = new FuzzySet(0, 0, 0, 0);
FuzzySet *lowb = new FuzzySet(0, 0, 25, 40);
FuzzySet *midb = new FuzzySet(25, 40, 60, 75);
FuzzySet *highb = new FuzzySet(62, 75, 100, 100);
// variables
// add input1 to fuzzy input1
FuzzyInput *temp = new FuzzyInput(1);
temp->addFuzzySet(cool);
temp->addFuzzySet(midt);
temp->addFuzzySet(high);
fuzzy->addFuzzyInput(temp);
// add input2 to fuzzy input2
FuzzyInput *pop = new FuzzyInput(2);
pop->addFuzzySet(low);
pop->addFuzzySet(mid);
pop->addFuzzySet(hot);
fuzzy->addFuzzyInput(pop);
// add output1 to fuzzy output1
FuzzyOutput *airCom = new FuzzyOutput(1);
airCom->addFuzzySet(off);
airCom->addFuzzySet(lowb);
airCom->addFuzzySet(midb);
airCom->addFuzzySet(highb);
fuzzy->addFuzzyOutput(airCom);
// Rules 1
// if temp is cool and pop is low then aircom is off
FuzzyRuleAntecedent *ifTempIsCoolAndPopIsLow = new FuzzyRuleAntecedent();
ifTempIsCoolAndPopIsLow->joinWithAND(cool, low); //for Potentiometer highldr , for actual ldr => lowldr
FuzzyRuleConsequent *thenAirComOff = new FuzzyRuleConsequent();
thenAirComOff->addOutput(off); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule1 = new FuzzyRule(1, ifTempIsCoolAndPopIsLow, thenAirComOff);
fuzzy->addFuzzyRule(fuzzyRule1);
// Rules 2
// if temp is cool and pop is mid then aircom is mid
FuzzyRuleAntecedent *ifTempIsCoolAndPopIsMid = new FuzzyRuleAntecedent();
ifTempIsCoolAndPopIsMid->joinWithAND(cool, mid);
FuzzyRuleConsequent *thenAirComMid = new FuzzyRuleConsequent();
thenAirComMid->addOutput(mid);
FuzzyRule *fuzzyRule2 = new FuzzyRule(2, ifTempIsCoolAndPopIsMid, thenAirComMid);
fuzzy->addFuzzyRule(fuzzyRule2);
// Rules 3
// if temp is cool and pop is high then aircom is high
FuzzyRuleAntecedent *ifTempIsCoolAndPopIsHigh = new FuzzyRuleAntecedent();
ifTempIsCoolAndPopIsHigh->joinWithAND(cool, high);
FuzzyRuleConsequent *thenAirComHigh = new FuzzyRuleConsequent();
thenAirComHigh->addOutput(high);
FuzzyRule *fuzzyRule3 = new FuzzyRule(3, ifTempIsCoolAndPopIsHigh, thenAirComHigh);
fuzzy->addFuzzyRule(fuzzyRule3);
// Rules 4
// if temp is mid and pop is low then aircom is low
FuzzyRuleAntecedent *ifTempIsMidAndPopIsLow = new FuzzyRuleAntecedent();
ifTempIsMidAndPopIsLow->joinSingle(mid, low);
FuzzyRuleConsequent *thenAirComLow = new FuzzyRuleConsequent();
thenAirComLow->addOutput(low);
FuzzyRule* fuzzyRule4 = new FuzzyRule(4, ifTempIsMidAndPopIsLow, thenAirComLow);
fuzzy->addFuzzyRule(fuzzyRule4);
// Rules 5
// if temp is mid and pop is mid then aircom is mid
FuzzyRuleAntecedent *ifTempIsMIdAndPopIsMid = new FuzzyRuleAntecedent();
ifTempIsMIdAndPopIsMid->joinSingle(mid, mid);
FuzzyRule* fuzzyRule5 = new FuzzyRule(5, ifTempIsMIdAndPopIsMid, thenAirComMid);
fuzzy->addFuzzyRule(fuzzyRule5);
// Rules 6
// if temp is mid and pop is high then aircom is high
FuzzyRuleAntecedent *ifTempIsMidAndPopIsHigh = new FuzzyRuleAntecedent();
ifTempIsMidAndPopIsHigh->joinSingle(mid, high);
FuzzyRule* fuzzyRule6 = new FuzzyRule(6, ifTempIsMidAndPopIsHigh, thenAirComHigh);
fuzzy->addFuzzyRule(fuzzyRule6);
// Rules 7
// if temp is hot and pop is low then aircom is mid
FuzzyRuleAntecedent *ifTempIsHotAndPopIsLow = new FuzzyRuleAntecedent();
ifTempIsHotAndPopIsLow->joinSingle(hot, low);
FuzzyRule* fuzzyRule7 = new FuzzyRule(7, ifTempIsHotAndPopIsLow, thenAirComMid);
fuzzy->addFuzzyRule(fuzzyRule7);
// Rules 8
// if temp is hot and pop is mid then aircom is high
FuzzyRuleAntecedent *ifTempIsHotAndPopIsMid = new FuzzyRuleAntecedent();
ifTempIsHotAndPopIsMid->joinSingle(hot, mid);
FuzzyRule* fuzzyRule8 = new FuzzyRule(8, ifTempIsHotAndPopIsMid, thenAirComHigh);
fuzzy->addFuzzyRule(fuzzyRule8);
// Rules 9
// if temp is hot and pop is high then aircom is high
FuzzyRuleAntecedent *ifTempIsHotAndPopIsHigh = new FuzzyRuleAntecedent();
ifTempIsHotAndPopIsHigh->joinSingle(hot, high);
FuzzyRule* fuzzyRule9 = new FuzzyRule(9, ifTempIsHotAndPopIsHigh, thenAirComHigh);
fuzzy->addFuzzyRule(fuzzyRule9);
}
// returns the distance
int distance() {
digitalWrite(TRIGGER, LOW);
delayMicroseconds(5);
digitalWrite(TRIGGER, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER, LOW);
long pulse = pulseIn(ECHO, HIGH) / 2;
return pulse * 10 / 292;
}
// returns the brightness
int brightness() {
return analogRead(LDR);
}
/*
// prints in serial monitor
void print(int dist, int light, int output) {
Serial.print("distance: ");
Serial.print(dist);
Serial.print(" light: ");
Serial.print(light);
Serial.print(" => output: ");
Serial.print(output);
Serial.println();
}
*/
// main method
void loop() {
// get distance and light
int dist = distance();
int light = brightness();
// if the inputs are weird, ignore them Miximum value
if (dist < 0 || dist > 400 || light > 1023) return;
// fuzzyfication
fuzzy->setInput(1, dist); // dist as fuzzy input 1 (distance)
fuzzy->setInput(2, light); // light as fuzzy input 2 (ldr)
fuzzy->fuzzify();
// defuzzyfication
int output = fuzzy->defuzzify(1); // defuzzify fuzzy output 1 (brightness)
analogWrite(LED, output);
//void print(int dist, int light, int output) {
Serial.print("distance: ");
Serial.print(dist);
Serial.print(" light: ");
Serial.print(light);
Serial.print(" => output: ");
Serial.print(output);
Serial.println();
delay(100);
}