Closed servetcoskun closed 3 years ago
Hello, I found some errors in your code when you was building the FuzzyAntecedent objects, take a look in this correction:
#include <Arduino.h>
#include <Fuzzy.h>
// Instantiating a Fuzzy object
Fuzzy *fuzzy = new Fuzzy();
//FuzzyInput
FuzzyInput *ph = new FuzzyInput(1);
//FuzzySet *phacid = new FuzzySet(0, 0, 5.5, 6.0);
//FuzzySet *phbase = new FuzzySet(5.5, 6.0, 14.0, 14.0);
FuzzySet *phACIDIC = new FuzzySet(0, 0, 5.5, 6.0);
FuzzySet *phALKALINE = new FuzzySet(5.5, 6.0, 14.0, 14.0);
FuzzyInput *ec = new FuzzyInput(2);
FuzzySet *ecLOW = new FuzzySet(0, 0, 500, 550);
FuzzySet *ecOPTIMAL = new FuzzySet(500, 550, 600, 650);
FuzzySet *ecHIGH = new FuzzySet(600, 650, 700, 700);
//FuzzyOutput
FuzzyOutput *ph_pumpaction = new FuzzyOutput(1);
FuzzySet *ph_pumpoff = new FuzzySet(0, 0, 0, 0);
FuzzySet *ph_pumpon = new FuzzySet(0, 1, 1, 1);
FuzzyOutput *ec_pumpaction = new FuzzyOutput(2);
FuzzySet *ec_pumpoff = new FuzzySet(0, 0, 0, 0);
FuzzySet *ec_pumpon = new FuzzySet(0, 1, 1, 1);
void setup()
{
// Set the Serial output
Serial.begin(9600);
// Set a random seed
randomSeed(analogRead(0));
ph->addFuzzySet(phACIDIC);
ph->addFuzzySet(phALKALINE);
fuzzy->addFuzzyInput(ph);
ec->addFuzzySet(ecLOW);
ec->addFuzzySet(ecOPTIMAL);
ec->addFuzzySet(ecHIGH);
fuzzy->addFuzzyInput(ec);
ph_pumpaction->addFuzzySet(ph_pumpoff);
ph_pumpaction->addFuzzySet(ph_pumpon);
fuzzy->addFuzzyOutput(ph_pumpaction);
ec_pumpaction->addFuzzySet(ec_pumpoff);
ec_pumpaction->addFuzzySet(ec_pumpon);
fuzzy->addFuzzyOutput(ec_pumpaction);
//building fuzzy rule for ph AND ec
// ACIDIC FIRST RULE
// if ph acidic AND eclow THEN ph pump OFF AND ec pump ON
FuzzyRuleAntecedent *phAcidicAndEcLow = new FuzzyRuleAntecedent();
phAcidicAndEcLow->joinWithAND(phACIDIC, ecLOW);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOn = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOn->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOn->addOutput(ec_pumpon);
FuzzyRule *fuzzyRule1 = new FuzzyRule(1, phAcidicAndEcLow, thenPhPumpOffAndEcPumpOn);
fuzzy->addFuzzyRule(fuzzyRule1);
// if ph acidic AND ecOPTIMAL THEN ph pump OFF and ec pump OFF
FuzzyRuleAntecedent *phAcidicAndEcOptimal = new FuzzyRuleAntecedent();
phAcidicAndEcOptimal->joinWithAND(phACIDIC, ecOPTIMAL);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOff = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOff->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOff->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule2 = new FuzzyRule(2, phAcidicAndEcOptimal, thenPhPumpOffAndEcPumpOff);
fuzzy->addFuzzyRule(fuzzyRule2);
// if ph acidic AND ecHIGH then ph pump OFF and ec pump OFF
FuzzyRuleAntecedent *phAcidicAndEcHigh = new FuzzyRuleAntecedent();
phAcidicAndEcHigh->joinWithAND(phACIDIC, ecHIGH);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOff2 = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOff2->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOff2->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule3 = new FuzzyRule(3, phAcidicAndEcHigh, thenPhPumpOffAndEcPumpOff2);
fuzzy->addFuzzyRule(fuzzyRule3);
}
void loop()
{
float input1 = 5.7;
float input2 = 400;
fuzzy->setInput(1, input1);
fuzzy->setInput(2, input2);
fuzzy->fuzzify();
// Running the Defuzzification
float output1 = fuzzy->defuzzify(1);
float output2 = fuzzy->defuzzify(2);
// Printing something
Serial.print("\n\n\n\n\n\nInput [input1, input2]: ");
Serial.print("\t[");
Serial.print(input1);
Serial.print("\t");
Serial.print(input2);
Serial.print("]");
Serial.print("\nOutput pertinence: ");
Serial.print("\t\t");
Serial.print(ph_pumpoff->getPertinence());
Serial.print("\t");
Serial.print(ph_pumpon->getPertinence());
Serial.print("\t");
Serial.print(ec_pumpoff->getPertinence());
Serial.print("\t");
Serial.print(ec_pumpon->getPertinence());
Serial.println();
Serial.print("Output ph pump [0=off, 1.0=on]: ");
Serial.print(output1);
Serial.println();
Serial.print("Output ec pump [0=off, 1.0=on]: ");
Serial.print(output2);
Serial.println();
Serial.print("\nInput pertinence [acid, alkaline, eclow, ecoptimal, echigh]");
Serial.print("\n[");
Serial.print(phACIDIC->getPertinence());
Serial.print("\t");
Serial.print(phALKALINE->getPertinence());
Serial.print("\t");
Serial.print(ecLOW->getPertinence());
Serial.print("\t");
Serial.print(ecOPTIMAL->getPertinence());
Serial.print("\t");
Serial.print(ecHIGH->getPertinence());
Serial.print("]");
Serial.print("\n");
// wait 12 seconds
delay(12000);
}
And the output:
Input [input1, input2]: [5.70 400.00]
Output pertinence: 0.60 0.00 0.00 0.60
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.63
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[0.60 0.40 1.00 0.00 0.00]
But looking your example, I see that something is strange (I guess we found a bug)!
I will check it deeply.
Thank you for helping! It works a lot more as expected now. I have ignored the "PH Alkaline" functions from https://imgur.com/a/Q20vhaK. So I end up with "The first rules" from https://imgur.com/a/Rk4qOhe, I have included the code below, but have removed the serial code for readability, I have instead included the serial monitor output. It looks a lot better! I am gonna run a couple of more tests and report back. The pump values are 0.67 as long as the pH and EC values are from the optimal values (in this case pHdesired: 5.5 and ECdesired: 550.0 < ec > 600.0).
...
// if ph acidic AND eclow THEN ph pump OFF AND ec pump ON
FuzzyRuleAntecedent *phAcidicAndEcLow = new FuzzyRuleAntecedent();
phAcidicAndEcLow->joinWithAND(phACIDIC, ecLOW);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOn = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOn->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOn->addOutput(ec_pumpon);
FuzzyRule *fuzzyRule1 = new FuzzyRule(1, phAcidicAndEcLow, thenPhPumpOffAndEcPumpOn);
fuzzy->addFuzzyRule(fuzzyRule1);
// if ph acidic AND ecOPTIMAL THEN ph pump OFF and ec pump OFF
FuzzyRuleAntecedent *phAcidicAndEcOptimal = new FuzzyRuleAntecedent();
phAcidicAndEcOptimal->joinWithAND(phACIDIC, ecOPTIMAL);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOff = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOff->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOff->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule2 = new FuzzyRule(2, phAcidicAndEcOptimal, thenPhPumpOffAndEcPumpOff);
fuzzy->addFuzzyRule(fuzzyRule2);
// if ph acidic AND ecHIGH then ph pump OFF and ec pump OFF
FuzzyRuleAntecedent *phAcidicAndEcHigh = new FuzzyRuleAntecedent();
phAcidicAndEcHigh->joinWithAND(phACIDIC, ecHIGH);
FuzzyRuleConsequent *thenPhPumpOffAndEcPumpOff2 = new FuzzyRuleConsequent();
thenPhPumpOffAndEcPumpOff2->addOutput(ph_pumpoff);
thenPhPumpOffAndEcPumpOff2->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule3 = new FuzzyRule(3, phAcidicAndEcHigh, thenPhPumpOffAndEcPumpOff2);
fuzzy->addFuzzyRule(fuzzyRule3);
// if ph alkaline AND ecHIGH then ph pump ON and ec pump OFF
FuzzyRuleAntecedent *phAlkalineAndEcHigh = new FuzzyRuleAntecedent();
phAlkalineAndEcHigh->joinWithAND(phALKALINE, ecHIGH);
FuzzyRuleConsequent *thenPhPumpOnAndEcPumpOff = new FuzzyRuleConsequent();
thenPhPumpOnAndEcPumpOff->addOutput(ph_pumpon);
thenPhPumpOnAndEcPumpOff->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule4 = new FuzzyRule(4, phAlkalineAndEcHigh, thenPhPumpOnAndEcPumpOff);
fuzzy->addFuzzyRule(fuzzyRule4);
// if ph alkaline AND ecOPTIMAL then ph pump ON and ec pump OFF
FuzzyRuleAntecedent *phAlkalineAndEcOptimal = new FuzzyRuleAntecedent();
phAlkalineAndEcOptimal->joinWithAND(phALKALINE, ecOPTIMAL);
FuzzyRuleConsequent *thenPhPumpOnAndEcPumpOff2 = new FuzzyRuleConsequent();
thenPhPumpOnAndEcPumpOff2->addOutput(ph_pumpon);
thenPhPumpOnAndEcPumpOff2->addOutput(ec_pumpoff);
FuzzyRule *fuzzyRule5 = new FuzzyRule(5, phAlkalineAndEcOptimal, thenPhPumpOnAndEcPumpOff2);
fuzzy->addFuzzyRule(fuzzyRule5);
// if ph alkaline AND ecLOW then ph pump ON and ec pump ON
FuzzyRuleAntecedent *phAlkalineAndEcLow = new FuzzyRuleAntecedent();
phAlkalineAndEcLow->joinWithAND(phALKALINE, ecLOW);
FuzzyRuleConsequent *thenPhPumpOnAndEcPumpOn = new FuzzyRuleConsequent();
thenPhPumpOnAndEcPumpOn->addOutput(ph_pumpon);
thenPhPumpOnAndEcPumpOn->addOutput(ec_pumpon);
FuzzyRule *fuzzyRule6 = new FuzzyRule(6, phAlkalineAndEcLow, thenPhPumpOnAndEcPumpOn);
fuzzy->addFuzzyRule(fuzzyRule6);
...
Input [input1, input2]: [7.18 368.40]
Output pertinence: 0.00 1.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.67
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[0.00 1.00 1.00 0.00 0.00]
Input [input1, input2]: [4.91 76.03]
Output pertinence: 1.00 0.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 1.00 0.00 0.00]
Input [input1, input2]: [6.07 567.40]
Output pertinence: 0.00 1.00 1.00 0.00
Output ph pump [0=off, 1.0=on]: 0.67
Output ec pump [0=off, 1.0=on]: 0.00
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[0.00 1.00 0.00 1.00 0.00]
Input [input1, input2]: [1.62 62.45]
Output pertinence: 1.00 0.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 1.00 0.00 0.00]
Input [input1, input2]: [5.17 26.88]
Output pertinence: 1.00 0.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 1.00 0.00 0.00]
Input [input1, input2]: [2.69 377.09]
Output pertinence: 1.00 0.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 1.00 0.00 0.00]
Input [input1, input2]: [2.03 574.29]
Output pertinence: 1.00 0.00 1.00 0.00
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.00
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 0.00 1.00 0.00]
Input [input1, input2]: [9.26 345.49]
Output pertinence: 0.00 1.00 0.00 1.00
Output ph pump [0=off, 1.0=on]: 0.67
Output ec pump [0=off, 1.0=on]: 0.67
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[0.00 1.00 1.00 0.00 0.00]
Input [input1, input2]: [4.49 526.31]
Output pertinence: 0.53 0.00 0.53 0.47
Output ph pump [0=off, 1.0=on]: 0.00
Output ec pump [0=off, 1.0=on]: 0.25
Input pertinence [acid, alkaline, eclow, ecoptimal, echigh]
[1.00 0.00 0.47 0.53 0.00]
I think it works fine now. Do you want me to keep it open or close it @zerokol ?
Great. Keep the issue open a bit more, until I finish one test.
Hi! Loving this library so far! I am trying to recreate the Fuzzy controller seen in the picture here https://imgur.com/a/Rk4qOhe, but I have just started using the library but never implemented a fuzzy controller before, I am pretty sure my outputs are not correct as of now. Here are the membership functions I am trying to recreate https://imgur.com/a/Q20vhaK
I have tried covering the cases in the "The first rules" -> "Acid High" but I am not seeing a proper output. The optimal ph should be 5.5 and the optimal ec range should be 550-600. I was expecting to see something from the output1 and output2 variables, but they are constantly 0. Can you help? Thank you!
Serial output