Cannot get my pump to stop

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

Welcome to the forum

Let's take one of your if statements as an example

  if (input1 > 6.5)digitalWrite(pHdown, HIGH);
    delay (output1*1000);
     digitalWrite(pHdown, LOW);

In the code above, which statements should only be executed if the test returns true and which should be executed unconditionally ?

not clear.

why "it should check the pH and nutrients when my top tank is empty." why when the tank is empty? what does the tank contain?

but it sounds like you have two modes of operation: 1) something that happens when the tank is empty and 2) something that happens when the tank is full

it would make sense to have two blocks of code, each doing one of the things above.

but probably key to you problem i conflicting conditions

    if (distance > 35 && digitalRead(Pump) == LOW) {
        .
        .
        .
        if (distance < 25) {
            digitalWrite (Pump, LOW);
        }
    }

the main part of you code only execute if distance > 35, yet within that is a test for distance < 25 which be true within that earlier condition

can you more clearly describe the (at least) 2 modes of operation?

Hi, @pixiepaj1
Welcome to the forum.

Why do you want to use Fuzzy logic?

Have you written NON-Fuzzy Logic code to prove your code and that you have control of the relay?

In other words did you write your code in stages and get each stage working before combining each stage and debug along the way?

Have you got an actual Ph sensor connected?

Can you please post a schematic?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

how can this condition ever be true? input1 < 5.5 && input1 > 6.5

You seem to have not yet understood how multiple lines of code are combined to be executed alltogether if an if.condition is true

You do not use auto-formatting by pressing ctrl-T to get all lines of code indented in the same way so that the indention shows which lines of code belong to the same block of code and which lines belong to a different block
all these lines have zero indention

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;
}
}
}

the real thing is this

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;
      }
    }
  }

more indented to the right means code is inside a block
example

This while-loop

    while (input1 < 5.5 && input1 > 6.5 && input2 < 850 && distance > 35);

runs empty in itself because there is a semicolon at the end
after auto-formatting

    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);
    }

you can see that the if-conditions are not more indented to the right
which means the if-conditions do not belong to the while loop
adding the semicolon at the end

while (input1 < 5.5 && input1 > 6.5 && input2 < 850 && distance > 35)[color=red]**;** [/color] 

is the same as

    while (input1 < 5.5 && input1 > 6.5 && input2 < 850 && distance > 35) {
      // totally empty while-loop
    }

I guess this is one reason why your code does other things that you think your code does

best regards Stefan

        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);

shouldn't the above (more appropriately formated) be

        digitalWrite (Mixer, On);
        do {
            // update input 1 ??
            if (input1 < 5.5)
                digitalWrite (pHup, On);
            else if (input1 > 6.5)
                digitalWrite (pHdown, On);

            delay (output1*1000);
            digitalWrite (pHup,   Off);
            digitalWrite (pHdown, Off);

            // update input 2 ??
            if (input2 < 850)
                digitalWrite (Nutrients, On);
                delay (output2*1000);
                digitalWrite (Nutrients, Off);

            }
        } while (input1 < 5.5 || input1 > 6.5 || input2 < 850);
        digitalWrite (Mixer, Off);

but why are the inputs random ??????

        // Fuzzy logic
        int input1 = random (4, 7);
        int input2 = random (850, 1000);

I guess that is a pre-condition for beeing "fuzzy"

1 Like

This particular part of the code is to operate an actuator for the pH down solution and runs for the time stated by the fuzzy logic control. It works and does not concern how the pump works

It is random to test the code works before using the sensors

ok, but there are better ways of doing this.

but more importantly ... what about

and also, important

I am building a drip feeder hydroponic system for my honours project which needs to have a fuzzy logic controller. The tank at the top is the source. The ultrasonic sensor is connected to this to tell when it runs empty (or near empty) and then the code will activate to check and change the pH and nutrient levels using 3 solenoid valves, one for pH up, pH down and nutrients. The fuzzy logic tells the solenoid valves how long to stay open depending on the current levels. A separate pump (the mixer) will stir the liquid for a certain length of time and when the values for the pH reach between 5.5 and 6.5 and the nutrients are 850 ppm or above the loop will stop and the pump will come on to tell it to refill the source tank again. The numbers I have for running times etc are not short so I can test the code with random inputs and ensure that it is doing what it is supposed to do. It all works fine except at the end of the cycle the pump wont turn off. It is the last two lines if the code which should run after the do..while loop has been satisfied. Once the pump turns off only the ultrasonic sensor will run until the tank has emptied again (I have not sorted the code for this yet). I am simply trying to find a way to get the pump to turn off so I can then work on updating the code and testing it for real with the sensors. It is considerably easier using a random number generator at the moment than setting up different flasks with different pHs etc.

Hi,
Sorry but had to spread it out in point form.

Tom... :smiley: :+1: :coffee: :australia:

If you say so, but could you please answer my question because I think, as others here do, that you do not understand how to execute a block of code that depends on a condition being true.

We will be able to tell when you answer my question and will be able to provide the appropriate advice to you

You have this if-condition

  if (distance > 35 && digitalRead(Pump) == LOW) {

    // Fuzzy logic
    int input1 = random(4, 7);
    int input2 = random(850, 1000);
    //......
    // many lines below you have this do-while-loop
    do {
      if (input1 < 5.5) {
        digitalWrite(pHup, HIGH);
      }
      // and more lines below you have these if-conditions
    if (input1 >= 5.5 && input1 <= 6.5 && input2 >= 850 && distance > 35) {
      digitalWrite(Pump, HIGH);
    }

    if (distance < 25) { 
      digitalWrite(Pump, LOW);
    }

the if-condition if (distance < 25) { is inside the code-block of the if-condition
if (distance > 35 && digitalRead(Pump) == LOW) {

this condition is true for distance 36

if (distance > 35 && digitalRead(Pump) == LOW) {
if (    36   > 35 && digitalRead(Pump) == LOW) {

this means the executing the if-condition

    if (distance < 25) { 

is only executed if distance is mimimum 36.
Whenever distance is smaller than 36
the if-condition

    if (distance < 25) { 

is

NOT executed!

and that is the reason why your pump never stops

You have to pay very close attention to which line of code is executed when
and using the auto-formatting tool by pressing ctrl-T is a big help to find such bugs

best regards Stefan

thanks for the explanation

so there are 2 tanks: i'll call them mixing and as you said source

so it sounds like there are actually 3 mode:

  • monitor the source tank fill level
  • mix the nutrients and pH balance stuff(?) in the mixing tank, and
  • fill, where the pump is turned on to replenish the source tank

not recognizing these 3 modes can make the code very difficult

but it wouldn't be too complicated to actually restart the mixing mode as soon as the source tank is replenished and begin the fill mode as soon as the source tank is emptied.

again, recognizing the three modes and doing each as necessary isn't that complicated when the code is properly organized

sure. but there are easier ways to do this

i've already commented on this

look this over. it simulates what i think you're trying to do
i've copied some pieces of your code, but restructured it to have 3 modes of operation: Monitor, Mix and Fill

here's the output -- primary to see if i understood what you described

 mode Mon, fill level = 31
 mode Mon, fill level = 32
 mode Mon, fill level = 33
 mode Mon, fill level = 34
 mode Mon, fill level = 35, set 11, HI
 mode Mix, fill level = 35, ph sensor = 19.60, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 17.17, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 15.01, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 13.10, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 11.39, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 9.86, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 8.49, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 7.27, set  9, HI, set  8, LO, set  9, LO
 mode Mix, fill level = 35, ph sensor = 6.17, set  8, LO, set  9, LO, set 11, LO, set 12, HI
 mode Fil, fill level = 34
 mode Fil, fill level = 33
 mode Fil, fill level = 32
 mode Fil, fill level = 31
 mode Fil, fill level = 30
 mode Fil, fill level = 29
 mode Fil, fill level = 28
 mode Fil, fill level = 27
 mode Fil, fill level = 26
 mode Fil, fill level = 25, set 12, LO
 mode Mon, fill level = 26
 mode Mon, fill level = 27
 mode Mon, fill level = 28
 mode Mon, fill level = 29
 mode Mon, fill level = 30
 mode Mon, fill level = 31

code


// hydroponic sytem: mix, fill, monitor

const byte PinPhSensor  = A4;

const byte PinTrig      = 2;
const byte PinEcho      = 3;

const byte PinPhUp      = 8;
const byte PinPhDown    = 9;
const byte PinNutrients = 10;
const byte PinMixer     = 11;
const byte PinPump      = 12;

enum { Off = LOW, On = HIGH };

const int   LevelEmpty  = 35;
const int   LevelFilled = 25;
int         fillLevel;

const float Calibration = 21.34 + 0.34; //change this value to calibrate
float pH;
int   phSensor;
float phSensorAvg  = 0;
float pHvol;

float nutrient;

unsigned long pHonMsec  = 1000;     // set by fuzzy

enum { Monitor, Mix, Fill };
const char *ModeStr [] = { "Mon", "Mix", "Fil" };

int mode = Monitor;

char s [80];

// -----------------------------------------------------------------------------
void
digWr (
    byte pin,
    byte state )
{
    digitalWrite (pin, state);
    sprintf (s, ", set %2d, %s", pin, state ? "HI" : "LO");
    Serial.print (s);
}

// -----------------------------------------------------------------------------
float
getDistance (void)
{
#if 1   // simulate source tank fill level
    static int dist = 30;

    if (digitalRead (PinPump))
        dist --;
    else
        dist++;

    if (LevelEmpty < dist)
        dist = LevelEmpty;
    return dist;

#else   // real sensor
    digitalWrite      (trigPin, HIGH);
    delayMicroseconds (10);
    digitalWrite      (trigPin, LOW);

    duration = pulseIn (echoPin, HIGH);
    distance = (duration/2)/29.1;

    Serial.print (distance);
    Serial.print (" cm");
#endif

    return 20;
}

// -----------------------------------------------------------------------------
void mix ()
{
    phSensor     = analogRead (PinPhSensor);
    phSensorAvg += (phSensor - phSensorAvg) / 10;

    pHvol   = phSensorAvg * 5.0 / 1024;   // 5V sensor, 10-bit value
    pH      = -5.70 * pHvol + Calibration;
    Serial.print   (", ph sensor = ");
    Serial.print   (pH);

    if (pH < 5.5) 
        digWr (PinPhUp, On);
    else if (pH > 6.5)
        digWr (PinPhDown, On);

    delay (pHonMsec);

    digWr (PinPhUp,   Off);
    digWr (PinPhDown, Off);

#if 0
    if (input2 < 850)
        digWr (Nutrients, On);
        delay (output2*1000);
        digWr (Nutrients, Off);
    }
#endif

 // if (5.5 <= pH && pH <= 6.5 || 850 <= nutrients);
    if (5.5 <= pH && pH <= 6.5)  {
        mode = Fill;
        digWr (PinMixer, Off);
        digWr (PinPump,  On);
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    Serial.print   (" mode ");
    Serial.print   (ModeStr [mode]);

    fillLevel = getDistance ();
    Serial.print   (", fill level = ");
    Serial.print   (fillLevel);

    switch (mode)  {
    case Fill:
        if (LevelFilled >= fillLevel)  {
            mode = Monitor;
            digWr (PinPump, Off);
        }
        delay (1000);           // slow prints
        break;

    case Mix:
        mix ();
        break;

    case Monitor:
        if (LevelEmpty <= fillLevel)  {
            mode = Mix;
            digWr (PinMixer, On);
        }
        delay (1000);           // slow prints
        break;
    }

    Serial.println ();
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    digitalWrite (PinPhUp,      Off);
    digitalWrite (PinPhDown,    Off);
    digitalWrite (PinNutrients, Off);
    digitalWrite (PinMixer,     Off);
    digitalWrite (PinPump,      Off);

    pinMode (PinPhUp,      OUTPUT);
    pinMode (PinPhDown,    OUTPUT);
    pinMode (PinNutrients, OUTPUT);
    pinMode (PinMixer,     OUTPUT);
    pinMode (PinPump,      OUTPUT);

    pinMode (PinTrig, OUTPUT);
    pinMode (PinEcho, INPUT);
}

Thank you for the help. The fuzzy logic is the critical part of my project (I fail my degree without this part) so I cannot omit it, but you have me see some issues. I am not a coder and have only ever used Arduino once before for my HND so it is very much a learning curve

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.