//this project is based on the article below
//https://medium.com/it-paragon/fuzzy-logic-approximating-imprecise-statement-54d444237820
//reference FIS project:
//https://wokwi.com/projects/376037130101397505?utm_source=chatgpt.com
#include <Fuzzy.h>
Fuzzy *fuzzy = new Fuzzy();
// Declare fuzzy set pointers
FuzzySet *tempFreezing, *tempCool, *tempWarm, *tempHot;
FuzzySet *cloudSunny, *cloudPartly, *cloudOvercast;
FuzzySet *speedSlow, *speedFast;
void setup() {
Serial.begin(115200);
// ----------- TEMPERATURE (°F) -----------
FuzzyInput *temperature = new FuzzyInput(1);
tempFreezing = new FuzzySet(0, 10, 30, 50); // Freezing: gradual fade to 50
tempCool = new FuzzySet(30, 50, 50, 70); // Cool: triangle, peak at 50
tempWarm = new FuzzySet(50, 70, 70, 90); // Warm: triangle, peak at 70
tempHot = new FuzzySet(70, 90, 110, 110); // Hot: trapezoid from 70 to 110
temperature->addFuzzySet(tempFreezing);
temperature->addFuzzySet(tempCool);
temperature->addFuzzySet(tempWarm);
temperature->addFuzzySet(tempHot);
fuzzy->addFuzzyInput(temperature);
// ----------- CLOUD COVER (%) -----------
FuzzyInput *cloud = new FuzzyInput(2);
cloudSunny = new FuzzySet(0, 0, 20, 40);
cloudPartly = new FuzzySet(20, 50, 80, 80);
cloudOvercast = new FuzzySet(60, 80, 100, 100);
cloud->addFuzzySet(cloudSunny);
cloud->addFuzzySet(cloudPartly);
cloud->addFuzzySet(cloudOvercast);
fuzzy->addFuzzyInput(cloud);
// ----------- SPEED (mph) -----------
FuzzyOutput *speed = new FuzzyOutput(1);
speedSlow = new FuzzySet(0, 0, 25, 75);
speedFast = new FuzzySet(25, 75, 100, 100);
speed->addFuzzySet(speedSlow);
speed->addFuzzySet(speedFast);
fuzzy->addFuzzyOutput(speed);
// ----------- FUZZY RULES -----------
// Rule 1: Freezing & Overcast → Slow
FuzzyRuleAntecedent* r1 = new FuzzyRuleAntecedent();
r1->joinWithAND(tempFreezing, cloudOvercast);
FuzzyRuleConsequent* r1c = new FuzzyRuleConsequent();
r1c->addOutput(speedSlow);
fuzzy->addFuzzyRule(new FuzzyRule(1, r1, r1c));
// Rule 2: Cool & Partly Cloudy → Slow
FuzzyRuleAntecedent* r2 = new FuzzyRuleAntecedent();
r2->joinWithAND(tempCool, cloudPartly);
FuzzyRuleConsequent* r2c = new FuzzyRuleConsequent();
r2c->addOutput(speedSlow);
fuzzy->addFuzzyRule(new FuzzyRule(2, r2, r2c));
// Rule 3: Warm & Sunny → Fast
FuzzyRuleAntecedent* r3 = new FuzzyRuleAntecedent();
r3->joinWithAND(tempWarm, cloudSunny);
FuzzyRuleConsequent* r3c = new FuzzyRuleConsequent();
r3c->addOutput(speedFast);
fuzzy->addFuzzyRule(new FuzzyRule(3, r3, r3c));
// Rule 4: Hot & Sunny → Fast
FuzzyRuleAntecedent* r4 = new FuzzyRuleAntecedent();
r4->joinWithAND(tempHot, cloudSunny);
FuzzyRuleConsequent* r4c = new FuzzyRuleConsequent();
r4c->addOutput(speedFast);
fuzzy->addFuzzyRule(new FuzzyRule(4, r4, r4c));
// Rule 5: Freezing & Sunny → Slow
FuzzyRuleAntecedent* r5 = new FuzzyRuleAntecedent();
r5->joinWithAND(tempFreezing, cloudSunny);
FuzzyRuleConsequent* r5c = new FuzzyRuleConsequent();
r5c->addOutput(speedSlow);
fuzzy->addFuzzyRule(new FuzzyRule(5, r5, r5c));
// Rule 6: Hot & Overcast → Slow
FuzzyRuleAntecedent* r6 = new FuzzyRuleAntecedent();
r6->joinWithAND(tempHot, cloudOvercast);
FuzzyRuleConsequent* r6c = new FuzzyRuleConsequent();
r6c->addOutput(speedSlow);
fuzzy->addFuzzyRule(new FuzzyRule(6, r6, r6c));
}
void loop() {
// Simulated analog input from sliders
int rawTemp = analogRead(34); // 0–4095
int rawCloud = analogRead(35); // 0–4095
float tempF = (rawTemp / 4095.0) * 100.0 + 10.0; // Scale to 10–110 °F
float cloudCover = (rawCloud / 4095.0) * 100.0; // Scale to 0–100 %
fuzzy->setInput(1, tempF);
fuzzy->setInput(2, cloudCover);
fuzzy->fuzzify();
float result = fuzzy->defuzzify(1);
Serial.print("Temp (°F): ");
Serial.print(tempF, 1);
Serial.print("\tCloud (%): ");
Serial.print(cloudCover, 1);
Serial.print("\t→ Speed: ");
Serial.print(result, 1);
Serial.println(" mph");
delay(2000);
}