I am trying to build a hydroponics control system using fuzzy logic which I have finally got to work but I cannot get the pump to switch off at the end of my code no matter what I try. It is set up so that it should check the pH and nutrients when my top tank is empty. Once it changes the levels and gets them within the parameters then the loop will stop and the pump will turn on to refill my tank. Once it reaches a specified level the pump should turn off but wont acknowledge the code. I have tried endless combinations of if, while, continue do...while, delay etc statements but they all seem to either make the pH/nutient loop start over again even when it is not supposed to if the pump is on, or it just ignores the turn off statement altogether. I am at a loss for what else to try.
#include <Fuzzy.h>
#define pHup 8
#define pHdown 9
#define Nutrients 10
#define Mixer 11
#define Pump 12
//pH Sensor
float calibration = 21.34 + 0.34; //change this value to calibrate
const int analogInPin = A0;
int sensorValue = 0;
unsigned long int avgValue;
float b;
int buf[10],temp;
// Fou ultrasonic sensor
const int trigPin = 6;
const int echoPin = 5;
long duration;
int distance;
int distanceThreshold = 0;
int cm = 0;
long readUltrasonicDistance(int triggerPin, int echoPin)
{
pinMode(trigPin, OUTPUT); // Clear the trigger
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigger pin to HIGH state for 10 microseconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
// Reads the echo pin, and returns the sound wave travel time in microseconds
return pulseIn(echoPin, HIGH);
delay (2000);
}
// Fuzzy
Fuzzy *fuzzy = new Fuzzy();
// FuzzyInput pH
FuzzySet *VeryAcidic = new FuzzySet(-0.5, -0.5, -0.5, 2.5);
FuzzySet *Acidic = new FuzzySet(-0.5, 2.5, 2.5, 5.5);
FuzzySet *SlightlyAcidic = new FuzzySet(2.5, 5.5, 6.5, 9.5);
FuzzySet *Alkaline = new FuzzySet(6.5, 9.5, 9.5, 12.5);
FuzzySet *VeryAlkaline = new FuzzySet(9.5, 12.5, 14, 14);
// FuzzyInput nutrients
FuzzySet *Low = new FuzzySet(0, 0, 450, 850);
FuzzySet *High = new FuzzySet(450, 850, 1000, 1000);
// FuzzyOutput pH
FuzzySet *Short = new FuzzySet(-4, 0, 0, 4);
FuzzySet *Middle = new FuzzySet(0, 4, 4, 8);
FuzzySet *Long = new FuzzySet(4, 8, 9, 9);
// FuzzyOutput nutrients ppm
FuzzySet *S2 = new FuzzySet(-4, 0, 0, 4);
FuzzySet *L2 = new FuzzySet(4, 8, 9, 9);
void setup()
{
// Set the Serial output
Serial.begin(9600);
//Actuators
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
//Ultrasonic Sensor
{
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Open serial monitor at 9600 baud to see ping results.
pinMode(Pump, OUTPUT);
}
// Set a random seed
randomSeed(analogRead(0));
// Every setup must occur in the function setup()
// FuzzyInput
FuzzyInput *pH = new FuzzyInput(1);
pH->addFuzzySet(VeryAcidic);
pH->addFuzzySet(Acidic);
pH->addFuzzySet(SlightlyAcidic);
pH->addFuzzySet(Alkaline);
pH->addFuzzySet(VeryAlkaline);
fuzzy->addFuzzyInput(pH);
// FuzzyInput
FuzzyInput *TDS = new FuzzyInput(2);
TDS->addFuzzySet(Low);
TDS->addFuzzySet(High);
fuzzy->addFuzzyInput(TDS);
// FuzzyOutput time for pH actuator
FuzzyOutput *Time = new FuzzyOutput(1);
Time->addFuzzySet(Short);
Time->addFuzzySet(Middle);
Time->addFuzzySet(Long);
fuzzy->addFuzzyOutput(Time);
// FuzzyOutput time for nutriens actuator
FuzzyOutput *T2 = new FuzzyOutput(2);
T2->addFuzzySet(S2);
T2->addFuzzySet(L2);
fuzzy->addFuzzyOutput(T2);
// Building FuzzyRule 1 ph and 2 TDS
FuzzyRuleAntecedent *ifpHVeryAcidicAndTDSLow = new FuzzyRuleAntecedent();
ifpHVeryAcidicAndTDSLow->joinWithAND(VeryAcidic, Low);
FuzzyRuleConsequent *thenTimeLong = new FuzzyRuleConsequent();
thenTimeLong->addOutput(Long);
FuzzyRuleConsequent *thenT2L2 = new FuzzyRuleConsequent();
thenT2L2->addOutput(L2);
FuzzyRule *fuzzyRule1 = new FuzzyRule(1, ifpHVeryAcidicAndTDSLow, thenTimeLong);
fuzzy->addFuzzyRule(fuzzyRule1);
FuzzyRule *fuzzyRule2 = new FuzzyRule(2, ifpHVeryAcidicAndTDSLow, thenT2L2);
fuzzy->addFuzzyRule(fuzzyRule2);
// Building FuzzyRule 3 ph and 4 TDS
FuzzyRuleAntecedent *ifpHVeryAcidicAndTDSHigh = new FuzzyRuleAntecedent();
ifpHVeryAcidicAndTDSHigh->joinWithAND(VeryAcidic, High);
FuzzyRuleConsequent *thenT2S2 = new FuzzyRuleConsequent();
thenT2S2->addOutput(S2);
FuzzyRule *fuzzyRule3 = new FuzzyRule(3, ifpHVeryAcidicAndTDSHigh, thenTimeLong);
fuzzy->addFuzzyRule(fuzzyRule3);
FuzzyRule *fuzzyRule4 = new FuzzyRule(4, ifpHVeryAcidicAndTDSHigh, thenT2S2);
fuzzy->addFuzzyRule(fuzzyRule4);
// Building FuzzyRule 5 pH and 6 TDS
FuzzyRuleAntecedent *ifpHAcidicAndTDSLow = new FuzzyRuleAntecedent();
ifpHAcidicAndTDSLow->joinWithAND(Acidic, Low);
FuzzyRuleConsequent *thenTimeMiddle = new FuzzyRuleConsequent();
thenTimeMiddle->addOutput(Middle);
FuzzyRule *fuzzyRule5 = new FuzzyRule(5, ifpHAcidicAndTDSLow, thenTimeMiddle);
fuzzy->addFuzzyRule(fuzzyRule4);
FuzzyRule *fuzzyRule6 = new FuzzyRule(6, ifpHAcidicAndTDSLow, thenT2L2);
fuzzy->addFuzzyRule(fuzzyRule6);
// Building FuzzyRule 7 pH and 8 TDS
FuzzyRuleAntecedent *ifpHAcidicAndTDSHigh = new FuzzyRuleAntecedent();
ifpHAcidicAndTDSHigh->joinWithAND(Acidic, High);
FuzzyRule *fuzzyRule7 = new FuzzyRule(7, ifpHAcidicAndTDSHigh, thenTimeMiddle);
fuzzy->addFuzzyRule(fuzzyRule7);
FuzzyRule *fuzzyRule8 = new FuzzyRule(8, ifpHAcidicAndTDSHigh, thenT2S2);
fuzzy->addFuzzyRule(fuzzyRule8);
// Building FuzzyRule 9 pH and 10 TDS
FuzzyRuleAntecedent *ifpHSlightlyAcidicAndTDSLow = new FuzzyRuleAntecedent();
ifpHSlightlyAcidicAndTDSLow->joinWithAND(SlightlyAcidic, Low);
FuzzyRuleConsequent *thenTimeShort = new FuzzyRuleConsequent();
thenTimeShort->addOutput(Short);
FuzzyRule *fuzzyRule9 = new FuzzyRule(9, ifpHSlightlyAcidicAndTDSLow, thenTimeShort);
fuzzy->addFuzzyRule(fuzzyRule9);
FuzzyRule *fuzzyRule10 = new FuzzyRule(10, ifpHSlightlyAcidicAndTDSLow, thenT2L2);
fuzzy->addFuzzyRule(fuzzyRule10);
// Building FuzzyRule 11 pH and 12 TDS
FuzzyRuleAntecedent *ifpHSlightlyAcidicAndTDSHigh = new FuzzyRuleAntecedent();
ifpHSlightlyAcidicAndTDSHigh->joinWithAND(SlightlyAcidic, High);
FuzzyRule *fuzzyRule11 = new FuzzyRule(11, ifpHSlightlyAcidicAndTDSHigh, thenTimeShort);
fuzzy->addFuzzyRule(fuzzyRule11);
FuzzyRule *fuzzyRule12 = new FuzzyRule(12, ifpHSlightlyAcidicAndTDSHigh, thenT2S2);
fuzzy->addFuzzyRule(fuzzyRule12);
// Building FuzzyRule 13 pH and 14 TDS
FuzzyRuleAntecedent *ifpHAlkalineAndTDSLow = new FuzzyRuleAntecedent();
ifpHAlkalineAndTDSLow->joinWithAND(Alkaline, Low);
FuzzyRule *fuzzyRule13 = new FuzzyRule(13, ifpHAlkalineAndTDSLow, thenTimeShort);
fuzzy->addFuzzyRule(fuzzyRule13);
FuzzyRule *fuzzyRule14 = new FuzzyRule(14, ifpHAlkalineAndTDSLow, thenT2L2);
fuzzy->addFuzzyRule(fuzzyRule14);
// Building FuzzyRule 15 pH and 16 TDS
FuzzyRuleAntecedent *ifpHAlkalineAndTDSHigh = new FuzzyRuleAntecedent();
ifpHAlkalineAndTDSHigh->joinWithAND(Alkaline, High);
FuzzyRule *fuzzyRule15 = new FuzzyRule(15, ifpHAlkalineAndTDSHigh, thenTimeMiddle);
fuzzy->addFuzzyRule(fuzzyRule15);
FuzzyRule *fuzzyRule16 = new FuzzyRule(16, ifpHAlkalineAndTDSHigh, thenT2S2);
fuzzy->addFuzzyRule(fuzzyRule16);
// Building FuzzyRule 17 pH and 18 TDS
FuzzyRuleAntecedent *ifpHVeryAlkalineAndTDSLow = new FuzzyRuleAntecedent();
ifpHVeryAlkalineAndTDSLow->joinWithAND(VeryAlkaline, Low);
FuzzyRule *fuzzyRule17 = new FuzzyRule(17, ifpHVeryAlkalineAndTDSLow, thenTimeLong);
fuzzy->addFuzzyRule(fuzzyRule17);
FuzzyRule *fuzzyRule18 = new FuzzyRule(18, ifpHVeryAlkalineAndTDSLow, thenT2L2);
fuzzy->addFuzzyRule(fuzzyRule18);
// Building FuzzyRule 19 pH and 20 TDS
FuzzyRuleAntecedent *ifpHVeryAlkalineAndTDSHigh = new FuzzyRuleAntecedent();
ifpHVeryAlkalineAndTDSHigh->joinWithAND(VeryAlkaline, High);
FuzzyRule *fuzzyRule19 = new FuzzyRule(19, ifpHVeryAlkalineAndTDSHigh, thenTimeLong);
fuzzy->addFuzzyRule(fuzzyRule19);
FuzzyRule *fuzzyRule20 = new FuzzyRule(20, ifpHAlkalineAndTDSHigh, thenT2S2);
fuzzy->addFuzzyRule(fuzzyRule20);
}
void loop()
{
//pH Sensor
for(int i=0;i<10;i++)
{
buf[i]=analogRead(analogInPin);
delay(30);
}
for(int i=0;i<9;i++)
{
for(int j=i+1;j<10;j++)
{
if(buf[i]>buf[j])
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=2;i<8;i++)
avgValue+=buf[i];
float pHVol=(float)avgValue*5.0/1024/6;
float phValue = -5.70 * pHVol + calibration;
Serial.print("sensor = ");
Serial.println(phValue);
delay(500);
//for ultrasonic sensor
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance= (duration/2)/29.1;
delay (2000);
Serial.print(distance);
Serial.print(" cm");
if (distance > 35 && digitalRead(Pump) == LOW) {
// Fuzzy logic
int input1 = random(4, 7);
int input2 = random(850, 1000);
Serial.println("\n\n\nTest: ");
Serial.print("\t\t\tpH: ");
Serial.print(input1);
Serial.print(" and TDS: ");
Serial.print(input2);
fuzzy->setInput(1, input1);
fuzzy->setInput(2, input2);
fuzzy->fuzzify();
Serial.println("Input: ");
Serial.print("\tpH: VeryAcidic-> ");
Serial.print(VeryAcidic->getPertinence());
Serial.print(", Acidic-> ");
Serial.print(Acidic->getPertinence());
Serial.print(", SlightlyAcidic-> ");
Serial.println(SlightlyAcidic->getPertinence());
Serial.print(", Alkaline-> ");
Serial.print(Alkaline->getPertinence());
Serial.print(", VeryAlkaline-> ");
Serial.println(VeryAlkaline->getPertinence());
Serial.print("\tTDS: Low-> ");
Serial.print(Low->getPertinence());
Serial.print(", High-> ");
Serial.println(High->getPertinence());
float output1 = fuzzy->defuzzify(1);
float output2 = fuzzy->defuzzify(2);
Serial.println("Output pH actuator: ");
Serial.print("\tTime: Short-> ");
Serial.print(Short->getPertinence());
Serial.print(", Middle-> ");
Serial.print(Middle->getPertinence());
Serial.print(", Long-> ");
Serial.println(Long->getPertinence());
Serial.println("Output nutrient acutuator: ");
Serial.print("\tT2: Short-> ");
Serial.print(S2->getPertinence());
Serial.print(", Long-> ");
Serial.println(L2->getPertinence());
Serial.println("Result: ");
Serial.print(output1);
Serial.println("Result: ");
Serial.print(output2);
do
{
if (input1 < 5.5)digitalWrite(pHup, HIGH);
delay (output1*1000);
digitalWrite(pHup, LOW);
if (input1 > 6.5)digitalWrite(pHdown, HIGH);
delay (output1*1000);
digitalWrite(pHdown, LOW);
if (input2 < 850)digitalWrite(Nutrients, HIGH);
delay (output2*1000);
digitalWrite(Nutrients, LOW);
digitalWrite(Mixer, HIGH);
delay (2000);
digitalWrite(Mixer, LOW);
}
while (input1 < 5.5 && input1 > 6.5 && input2 < 850 && distance > 35);
if (input1 >= 5.5 && input1 <= 6.5 && input2 >= 850 && distance > 35)
{digitalWrite(Pump, HIGH);}
if (distance < 25)
{digitalWrite(Pump, LOW);
}
}
}
type or paste code here
