The error shows that you are passing three FuzzySet to joinWithAND() but the library can only join ONE FuzzySet to One FuzzyRuleAntecedent or join two FuzzyRuleAntecedent together.
Your sketch compiles without error or warning for me. I'm using Arduino 1.8.13 and an Arduino UNO. What version of Arduino are you using? What Arduino board are you compiling for?
I have V1.4.1 of eFFL installed. What version of the library are you using?
I tried running your sketch on an Arduino UNO and ran out of memory at "rule 7". Here is a version of Fuzzy.cpp that checks for and reports various errors caused by running out of memory. Put it in the eFLL library.
/*
* Robotic Research Group (RRG)
* State University of Piauí (UESPI), Brazil - Piauí - Teresina
*
* Fuzzy.cpp
*
* Author: AJ Alves <aj.alves@zerokol.com>
* Co authors: Dr. Ricardo Lira <ricardor_usp@yahoo.com.br>
* Msc. Marvin Lemos <marvinlemos@gmail.com>
* Douglas S. Kridi <douglaskridi@gmail.com>
* Kannya Leal <kannyal@hotmail.com>
*/
#include "Fuzzy.h"
#include <Arduino.h>
// CONTRUCTORS
Fuzzy::Fuzzy()
{
// Initializing pointers with NULL
// FuzzyInput
this->fuzzyInputs = NULL;
// FuzzyOutput
this->fuzzyOutputs = NULL;
// FuzzyRule
this->fuzzyRules = NULL;
}
// DESTRUCTOR
Fuzzy::~Fuzzy()
{
this->cleanFuzzyInputs(this->fuzzyInputs);
this->cleanFuzzyOutputs(this->fuzzyOutputs);
this->cleanFuzzyRules(this->fuzzyRules);
}
// PUBLIC METHODS
// Method to include a new FuzzyInput into Fuzzy
bool Fuzzy::addFuzzyInput(FuzzyInput *fuzzyInput)
{
if (fuzzyInput == NULL)
{
// return false if in out of memory
Serial.println("NULL fuzzyInput in Fuzzy::addFuzzyInput()");
return false;
}
// auxiliary variable to handle the operation
fuzzyInputArray *newOne;
// allocating in memory
if ((newOne = (fuzzyInputArray *)malloc(sizeof(fuzzyInputArray))) == NULL)
{
// return false if in out of memory
Serial.println("Memory alloction failed in Fuzzy::addFuzzyInput()");
return false;
}
// building the object
newOne->fuzzyInput = fuzzyInput;
newOne->next = NULL;
// if it is the first FuzzyInput, set it as the head
if (this->fuzzyInputs == NULL)
{
this->fuzzyInputs = newOne;
}
else
{
// auxiliary variable to handle the operation
fuzzyInputArray *aux = this->fuzzyInputs;
// find the last element of the array
while (aux != NULL)
{
if (aux->next == NULL)
{
// make the ralations between them
aux->next = newOne;
return true;
}
aux = aux->next;
}
}
return true;
}
// Method to include a new FuzzyOutput into Fuzzy
bool Fuzzy::addFuzzyOutput(FuzzyOutput *fuzzyOutput)
{
if (fuzzyOutput == NULL)
{
// return false if in out of memory
Serial.println("NULL fuzzyOutput in Fuzzy::addFuzzyOutput()");
return false;
}
// auxiliary variable to handle the operation
fuzzyOutputArray *newOne;
// allocating in memory
if ((newOne = (fuzzyOutputArray *)malloc(sizeof(fuzzyOutputArray))) == NULL)
{
// return false if in out of memory
Serial.println("Memory alloction failed in Fuzzy::addFuzzyOutput()");
return false;
}
// building the object
newOne->fuzzyOutput = fuzzyOutput;
newOne->next = NULL;
// sorting the fuzzyOutput
fuzzyOutput->order();
// if it is the first FuzzyOutput, set it as the head
if (this->fuzzyOutputs == NULL)
{
this->fuzzyOutputs = newOne;
}
else
{
// auxiliary variable to handle the operation
fuzzyOutputArray *aux = this->fuzzyOutputs;
// find the last element of the array
while (aux != NULL)
{
if (aux->next == NULL)
{
// make the ralations between them
aux->next = newOne;
return true;
}
aux = aux->next;
}
}
return true;
}
// Method to include a new FuzzyRule into Fuzzy
bool Fuzzy::addFuzzyRule(FuzzyRule *fuzzyRule)
{
if (fuzzyRule == NULL)
{
// return false if in out of memory
Serial.println("NULL fuzzyRule in Fuzzy::addFuzzyRule()");
return false;
}
// auxiliary variable to handle the operation
fuzzyRuleArray *newOne;
// allocating in memory
if ((newOne = (fuzzyRuleArray *)malloc(sizeof(fuzzyRuleArray))) == NULL)
{
// return false if in out of memory
Serial.print("Memory alloction failed in Fuzzy::addFuzzyRule() index ");
Serial.println(fuzzyRule->getIndex());
Serial.flush();
return false;
}
// building the object
newOne->fuzzyRule = fuzzyRule;
newOne->next = NULL;
// if it is the first FuzzyOutput, set it as the head
if (this->fuzzyRules == NULL)
{
this->fuzzyRules = newOne;
}
else
{
// auxiliary variable to handle the operation
fuzzyRuleArray *aux = this->fuzzyRules;
// find the last element of the array
while (aux != NULL)
{
if (aux->next == NULL)
{
// make the ralations between them
aux->next = newOne;
return true;
}
aux = aux->next;
}
}
return true;
}
// Method to set a crisp value to one FuzzyInput
bool Fuzzy::setInput(int fuzzyInputIndex, float crispValue)
{
// auxiliary variable to handle the operation
fuzzyInputArray *aux;
// instantiate with the first element from array
aux = this->fuzzyInputs;
// while not in the end of the array, iterate
while (aux != NULL)
{
// if the FuzzyInput index match with the desired
if (aux->fuzzyInput->getIndex() == fuzzyInputIndex)
{
// set crisp value for this FuzzyInput and return true
aux->fuzzyInput->setCrispInput(crispValue);
return true;
}
aux = aux->next;
}
// if no FuzzyInput was found, return false
Serial.print("No input found in Fuzzy::setInput(");
Serial.print(fuzzyInputIndex);
Serial.println(")");
return false;
}
// Method to start the calculate of the result
bool Fuzzy::fuzzify()
{
// auxiliary variable to handle the operation
fuzzyInputArray *fuzzyInputAux;
fuzzyOutputArray *fuzzyOutputAux;
fuzzyRuleArray *fuzzyRuleAux;
// to reset the data of all FuzzyInput and FuzzyOutput objects
// instantiate with first element of the array
fuzzyInputAux = this->fuzzyInputs;
// while not in the end of the array, iterate
while (fuzzyInputAux != NULL)
{
// for each FuzzyInput, reset its data
fuzzyInputAux->fuzzyInput->resetFuzzySets();
fuzzyInputAux = fuzzyInputAux->next;
}
// instantiate with first element of the array
fuzzyOutputAux = this->fuzzyOutputs;
// while not in the end of the array, iterate
while (fuzzyOutputAux != NULL)
{
// for each FuzzyOutput, reset its data
fuzzyOutputAux->fuzzyOutput->resetFuzzySets();
fuzzyOutputAux = fuzzyOutputAux->next;
}
// to calculate the pertinence of all FuzzyInput objects
// instantiate with first element of the array
fuzzyInputAux = this->fuzzyInputs;
// while not in the end of the array, iterate
while (fuzzyInputAux != NULL)
{
// for each FuzzyInput, calculate its pertinence
fuzzyInputAux->fuzzyInput->calculateFuzzySetPertinences();
fuzzyInputAux = fuzzyInputAux->next;
}
// to evaluate which rules were triggered
// instantiate with first element of the array
fuzzyRuleAux = this->fuzzyRules;
// while not in the end of the array, iterate
while (fuzzyRuleAux != NULL)
{
// for each FuzzyRule, evaluate its expressions
fuzzyRuleAux->fuzzyRule->evaluateExpression();
fuzzyRuleAux = fuzzyRuleAux->next;
}
// to truncate the output sets
// instantiate with first element of the array
fuzzyOutputAux = this->fuzzyOutputs;
// while not in the end of the array, iterate
while (fuzzyOutputAux != NULL)
{
// for each FuzzyOutput, truncate the result
fuzzyOutputAux->fuzzyOutput->truncate();
fuzzyOutputAux = fuzzyOutputAux->next;
}
return true;
}
// Method to verify if one specific FuzzyRule was triggered
bool Fuzzy::isFiredRule(int fuzzyRuleIndex)
{
// auxiliary variable to handle the operation
fuzzyRuleArray *aux;
// instantiate with first element of the array
aux = this->fuzzyRules;
// while not in the end of the array, iterate
while (aux != NULL)
{
// if the FuzzyRule index match with the desired
if (aux->fuzzyRule->getIndex() == fuzzyRuleIndex)
{
// return the calculated result
return aux->fuzzyRule->isFired();
}
aux = aux->next;
}
// if no FuzzyRule was found, return false
Serial.print("No rule found in Fuzzy::isFiredRule(");
Serial.print(fuzzyRuleIndex);
Serial.println(")");
return false;
}
// Method to retrieve the result of the process for one specific FuzzyOutput
float Fuzzy::defuzzify(int fuzzyOutputIndex)
{
// auxiliary variable to handle the operation
fuzzyOutputArray *aux;
// instantiate with first element of the array
aux = this->fuzzyOutputs;
// while not in the end of the array, iterate
while (aux != NULL)
{
// if the FuzzyOutput index match with the desired
if (aux->fuzzyOutput->getIndex() == fuzzyOutputIndex)
{
// return the calculated result
return aux->fuzzyOutput->getCrispOutput();
}
aux = aux->next;
}
Serial.print("No output found in Fuzzy::defuzzify(");
Serial.print(fuzzyOutputIndex);
Serial.println(")");
return 0;
}
// PRIVATE METHODS
// Method to recursively clean all FuzzyInput from memory
void Fuzzy::cleanFuzzyInputs(fuzzyInputArray *aux)
{
if (aux != NULL)
{
this->cleanFuzzyInputs(aux->next);
// emptying allocated memory
free(aux);
}
}
// Method to recursively clean all FuzzyOutput from memory
void Fuzzy::cleanFuzzyOutputs(fuzzyOutputArray *aux)
{
if (aux != NULL)
{
this->cleanFuzzyOutputs(aux->next);
// emptying allocated memory
free(aux);
}
}
// Method to recursively clean all FuzzyRule from memory
void Fuzzy::cleanFuzzyRules(fuzzyRuleArray *aux)
{
if (aux != NULL)
{
this->cleanFuzzyRules(aux->next);
// emptying allocated memory
free(aux);
}
}
forgive me sir, for the compile error I have solved it, now the error problem I mean is the result of processing not on compilation. I have checked again on Antecedents and Consequents but the result still error sir , currently I am using the latest version which is 1.4.1. for now i try to cek in arduino mega and proteus. in proteus the result can display but the result not for all can be print
Is there a possibility that this is caused by too many input-output and rules? because I use input 3 and output 4 for rules as much as 27. some people say it doesn't matter if it is used on an arduino mega but when I simulate the results are still not as expected
Yes. If there is not enough memory to hold all of your inputs, outputs, and rules you will get null pointers when trying to allocate memory. The sketch can crash if any of those pointers is accidentally used to store data.
EVERY time you call 'new()' to create a FuzzySet, FuzzyInput, FuzzyOutput, FuzzyRuleAntecedent, FuzzyRuleConsequent , or FuzzyRule you should make sure the resulting pointer is not NULL.
EVERY time you call 'fuzzy->addFuzzyRule()' to add a rule to the fuzzy logic you should make sure that the returned value is 'true' meaning that the add was successful.