/**
* 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
// temp (20-35 *c in Wokwi)
FuzzySet *cool = new FuzzySet(0, 0, 20, 27); //trapizoid MF (a,b,c,d)
FuzzySet *mid = new FuzzySet(20, 27, 27, 35);
FuzzySet *hot = new FuzzySet(27, 35, 50, 50);
// poputation (0-50 lux=> 1015-8 resistance value in wokwi)
FuzzySet *lowPop = new FuzzySet(0, 0, 20, 30);
FuzzySet *midPop = new FuzzySet(20, 30, 30, 40);
FuzzySet *highPop = new FuzzySet(27 ,40, 50, 50);
// Mortor
FuzzySet *off = new FuzzySet(0, 0, 0, 0);
FuzzySet *lowb = new FuzzySet(0, 0, 20, 40);
FuzzySet *midb = new FuzzySet(25, 40, 60, 80);
FuzzySet *highb = new FuzzySet(60, 80, 100, 100);
// variables
// variable temp with universe 0-400 as input
FuzzyInput *temp = new FuzzyInput(1);
temp->addFuzzySet(cool);
temp->addFuzzySet(mid);
temp->addFuzzySet(hot);
fuzzy->addFuzzyInput(temp);
// variable Pop with universe 0-1015 as input
FuzzyInput *Pop = new FuzzyInput(2);
Pop->addFuzzySet(lowPop);
Pop->addFuzzySet(midPop);
Pop->addFuzzySet(highPop);
fuzzy->addFuzzyInput(Pop);
// variable mortor with universe 0-255 as output
FuzzyOutput *mortor = new FuzzyOutput(1);
mortor->addFuzzySet(off);
mortor->addFuzzySet(lowb);
mortor->addFuzzySet(midb);
mortor->addFuzzySet(highb);
fuzzy->addFuzzyOutput(mortor);
// Rules 1
// if temp is cool and Pop is low then mortor is off
FuzzyRuleAntecedent *iftempcoolAndPopIsLow = new FuzzyRuleAntecedent();
iftempcoolAndPopIsLow->joinWithAND(cool, lowPop); //for Potentiometer highldr , for actual ldr => lowldr
FuzzyRuleConsequent *thenmortoroff = new FuzzyRuleConsequent();
thenmortoroff->addOutput(off); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule1 = new FuzzyRule(1, iftempcoolAndPopIsLow, thenmortoroff);
fuzzy->addFuzzyRule(fuzzyRule1);
// Rules 2
// if temp is cool and Pop is mid then mortor is mid
FuzzyRuleAntecedent *iftempcoolAndPopIsmid = new FuzzyRuleAntecedent();
iftempcoolAndPopIsmid->joinWithAND(cool, midPop); //for Potentiometer highldr , for actual ldr => lowldr
FuzzyRuleConsequent *thenmortormid = new FuzzyRuleConsequent();
thenmortormid->addOutput(midb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule2 = new FuzzyRule(2, iftempcoolAndPopIsmid, thenmortormid);
fuzzy->addFuzzyRule(fuzzyRule2);
// Rules 3
// if temp is cool and Pop is hi then mortor is hi
FuzzyRuleAntecedent *iftempcoolAndPopIshigh = new FuzzyRuleAntecedent();
iftempcoolAndPopIshigh->joinWithAND(cool, highPop); //for Potentiometer highldr , for actual ldr => lowldr
FuzzyRuleConsequent *thenmortorhigh= new FuzzyRuleConsequent();
thenmortorhigh->addOutput(highb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule3 = new FuzzyRule(3, iftempcoolAndPopIshigh, thenmortorhigh);
fuzzy->addFuzzyRule(fuzzyRule3);
// Rules 4
// if temp is mid and Pop is low then mortor is low
FuzzyRuleAntecedent *iftempmidAndPopIslow = new FuzzyRuleAntecedent();
iftempmidAndPopIslow->joinWithAND(mid, lowPop); //for Potentiometer highldr , for actual ldr => lowldr
FuzzyRuleConsequent *thenmortorlow = new FuzzyRuleConsequent();
thenmortorlow->addOutput(lowb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule4 = new FuzzyRule(4, iftempmidAndPopIslow, thenmortorlow);
fuzzy->addFuzzyRule(fuzzyRule4);
// Rules 5
// if temp is mid and Pop is mid then mortor is mid
FuzzyRuleAntecedent *iftempmidAndPopIsmid = new FuzzyRuleAntecedent();
iftempmidAndPopIsmid->joinWithAND(mid, midPop); //for Potentiometer highldr , for actual ldr => lowldr
thenmortormid->addOutput(midb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule5 = new FuzzyRule(5, iftempmidAndPopIsmid, thenmortormid);
fuzzy->addFuzzyRule(fuzzyRule5);
// Rules 6
// if temp is mid and Pop is high then mortor is high
FuzzyRuleAntecedent *iftempmidAndPopIshigh = new FuzzyRuleAntecedent();
iftempmidAndPopIshigh->joinWithAND(mid, highPop); //for Potentiometer highldr , for actual ldr => lowldr
thenmortorhigh->addOutput(highb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule6 = new FuzzyRule(6, iftempmidAndPopIshigh, thenmortorhigh);
fuzzy->addFuzzyRule(fuzzyRule6);
// Rules 7
// if temp is hot and Pop is mid then mortor is mid
FuzzyRuleAntecedent *ifTemphotAndPopIsLow = new FuzzyRuleAntecedent();
ifTemphotAndPopIsLow->joinWithAND(hot, midPop); //for Potentiometer highldr , for actual ldr => lowldr
thenmortormid->addOutput(midb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule7 = new FuzzyRule(7, ifTemphotAndPopIsLow, thenmortormid);
fuzzy->addFuzzyRule(fuzzyRule7);
// Rules 8
// if temp is hot and Pop is mid then mortor is mid
FuzzyRuleAntecedent *ifTemphotAndPopIsMid = new FuzzyRuleAntecedent();
ifTemphotAndPopIsMid->joinWithAND(hot, highPop); //for Potentiometer highldr , for actual ldr => lowldr
thenmortorhigh->addOutput(highb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule8 = new FuzzyRule(8, ifTemphotAndPopIsMid, thenmortorhigh);
fuzzy->addFuzzyRule(fuzzyRule8);
// Rules 9
// if temp is hot and Pop is mid then mortor is mid
FuzzyRuleAntecedent *ifTemphotAndPopIsHigh = new FuzzyRuleAntecedent();
ifTemphotAndPopIsHigh->joinWithAND(hot, highPop); //for Potentiometer highldr , for actual ldr => lowldr
thenmortorhigh->addOutput(highb); ////for Potentiometer lowb , for actual ldr => highb
FuzzyRule *fuzzyRule9 = new FuzzyRule(9, ifTemphotAndPopIsHigh, thenmortorhigh);
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("temp: ");
Serial.print(dist);
Serial.print(" pop: ");
Serial.print(light);
Serial.print(" => output: ");
Serial.print(output);
Serial.println();
delay(100);
}