Combining TDS sensor code and fuzzy logic

I am a complete novice to coding but am building a hydroponics drip feeder system which is supposed to use fuzzy logic control to automatically change the pH and nutrient levels of the water before it gets pumped back into the tank above. There is a source tank above which uses gravity to make the water flow down through the drip emitters then into the bottom tank where the sensors/actuators are set up. When the top tank in empty as defined by the ultrasonic sensor then the code will start and the fuzzy logic will use readings from the TDS, temp and pH sensors to determine how long the solenoid valves for the nutrients and pH up/down solution will stay open for. A small pump will mix and if the levels are reached (pH between 5.5 and 6.5 and nutrients above 850 ppm) then a second pump will turn on to transfer the water back to the top tank.

I have had endless problems with this and the equipment (although it seems that the issue was in fact the arduino as it has somehow been storing code and is not resetting itself properly so I have had to purchase a new one). My big issue now I want to combine the code for the nutrient sensor into the main code but it makes the output of the fuzzy logic zero as soon as it is added. I have narrowed it down to this line "GravityTDS gravityTds;" as as soon as I add this the rest stops working. I don't know enough about coding to figure out what it actually does and have had no success with online research. I wonder if anyone can shed some light onto this. Please bear in mind I am a complete novice and know very little about coding. I have currently set the ultrasonic senor to give a reading of 36 so I can see the code run and the same for the two inputs for the fuzzy logic being fixed values rather than using the sensor values (and also because every time I set the equipment up something else seems to have broken down so I am now at a stage of just being desperate just to at least show I can get the code to work even if I can no longer show the practical side).


#include <Fuzzy.h>

#define Nutrients 8
#define pHup 9
#define pHdown 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, 50, 450);
FuzzySet *Medium = new FuzzySet(50, 450, 450, 850);
FuzzySet *High = new FuzzySet(450, 850, 1000, 1000);

// FuzzyOutput pH
FuzzySet *Short = new FuzzySet(0, 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(0, 0, 0, 7);
FuzzySet *M2 = new FuzzySet(0, 7, 7, 14);
FuzzySet *L2 = new FuzzySet(7, 14, 15, 15);


void setup() {

  Serial.begin(9600);

  //Actuators
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, 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(Medium);
  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(M2);
  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);



  // Building FuzzyRule 21 ph and 22 TDS
  FuzzyRuleAntecedent *ifpHVeryAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHVeryAcidicAndTDSMedium->joinWithAND(VeryAcidic, Medium);

  FuzzyRuleConsequent *thenT2M2 = new FuzzyRuleConsequent();
  thenT2M2->addOutput(M2);

  FuzzyRule *fuzzyRule21 = new FuzzyRule(21, ifpHVeryAcidicAndTDSMedium, thenTimeMiddle);
  fuzzy->addFuzzyRule(fuzzyRule21);

  FuzzyRule *fuzzyRule22 = new FuzzyRule(22, ifpHVeryAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule22);



  // Building FuzzyRule 23 ph and 24 TDS
  FuzzyRuleAntecedent *ifpHAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHAcidicAndTDSMedium->joinWithAND(Acidic, Medium);

  FuzzyRule *fuzzyRule23 = new FuzzyRule(23, ifpHAcidicAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule23);

  FuzzyRule *fuzzyRule24 = new FuzzyRule(24, ifpHAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule24);



  // Building FuzzyRule 25 pH and 26 TDS
  FuzzyRuleAntecedent *ifpHSlighltyAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHSlighltyAcidicAndTDSMedium->joinWithAND(SlightlyAcidic, Medium);

  FuzzyRule *fuzzyRule25 = new FuzzyRule(25, ifpHSlighltyAcidicAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule4);

  FuzzyRule *fuzzyRule26 = new FuzzyRule(26, ifpHSlighltyAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule26);



  // Building FuzzyRule 27 pH and 28 TDS
  FuzzyRuleAntecedent *ifpHAlkalineAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHAlkalineAndTDSMedium->joinWithAND(Alkaline, Medium);

  FuzzyRule *fuzzyRule27 = new FuzzyRule(27, ifpHAlkalineAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule27);

  FuzzyRule *fuzzyRule28 = new FuzzyRule(28, ifpHAlkalineAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule28);



  // Building FuzzyRule 29 pH and 30 TDS
  FuzzyRuleAntecedent *ifpHVeryAlkalineAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHVeryAlkalineAndTDSMedium->joinWithAND(VeryAlkaline, Medium);

  FuzzyRule *fuzzyRule29 = new FuzzyRule(29, ifpHVeryAlkalineAndTDSMedium, thenTimeMiddle);
  fuzzy->addFuzzyRule(fuzzyRule29);

  FuzzyRule *fuzzyRule30 = new FuzzyRule(30, ifpHVeryAlkalineAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule30);
}
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.58 * 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 = 36;
  delay(2000);
  Serial.print(distance);
  Serial.print(" cm");

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

    // Fuzzy logic
    int input1 = 6;
    int input2 = 550;

    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("\n\tTDS: Low-> ");
    Serial.print(Low->getPertinence());
    Serial.print("\tTDS: Medium-> ");
    Serial.print(Medium->getPertinence());
    Serial.print(",  High-> ");
    Serial.println(High->getPertinence());

    float output1 = fuzzy->defuzzify(1);
    float output2 = fuzzy->defuzzify(2);

    Serial.println("\nOutput 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("\nOutput nutrient acutuator: ");
    Serial.print("\tT2: Short-> ");
    Serial.print(S2->getPertinence());
    Serial.print(", Middle-> ");
    Serial.print(M2->getPertinence());
    Serial.print(", Long-> ");
    Serial.println(L2->getPertinence());


    Serial.println("\nResult: ");
    Serial.print(output1);
    Serial.println("\nResult: ");
    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(200);
      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);
  }
}

The code for the nutrients which I want to add is:

				 
#include <EEPROM.h>
#include "GravityTDS.h"
#include <OneWire.h> 
#include <DallasTemperature.h>
 
#define ONE_WIRE_BUS 7
#define TdsSensorPin A1
 
OneWire oneWire(ONE_WIRE_BUS); 
GravityTDS gravityTds;
 
DallasTemperature sensors(&oneWire);
 
float tdsValue = 0;
 
 
 
void setup() {

			  
  Serial.begin(9600);
    sensors.begin();
    gravityTds.setPin(TdsSensorPin);
    gravityTds.setAref(5.0);  //reference voltage on ADC, default 5.0V on Arduino UNO
    gravityTds.setAdcRange(1024);  //1024 for 10bit ADC;4096 for 12bit ADC
    gravityTds.begin();  //initialization
															   
												 
}
 
void loop() {
    
    sensors.requestTemperatures();
 
    gravityTds.setTemperature(sensors.getTempCByIndex(0));  // set the temperature and execute temperature compensation
    gravityTds.update();  //sample and calculate
    tdsValue = gravityTds.getTdsValue();  // then get the value
    
    Serial.print(tdsValue,0);
    Serial.println("ppm");
    Serial.print("Temperature is: "); 
    Serial.print(sensors.getTempCByIndex(0));
        
  delay(1500);
}
											

If anyone could help shed some light onto this I would be really grateful

I’m unsure I would use the fuzzy route - surely it must have many iterations to settle to values , if it can .. This I could see taking a lot of time .
I haven’t followed your code , but I’m guessing you can only do the iteration once every fill , and at that specific time .

I would weigh how much liquid is in the “left over tank “ , measure your PH etc and then calculate what is needed to get the concentration right in the top tank after pumping ( or easier still measure it there where the volume is known .
If you want you could then add a controlled trim to reduce any errors .
You need to store any result control values , so it will work after switching off .

I’m assuming this is not a wacky baccy farm, or you need to sort it before your brain gets fuddled .

You need to post your attempt to combine the code. Otherwise no one can tell you what you did wrong.

You need to explain what exactly you mean by "stops working". We are not there in the room with you.

You need to tell the forum what type of Arduino you are using. Otherwise everyone will assume you are using an Uno R3. If you later tell the forum you are using some other Arduino model, that would be annoying.

Why not do the control accurately, with standard math?

That delay never gets executed.

And I'm sure I would have no clue as to how to do.

But @pixiepaj1 seems to be required, by to whomever she is to present the results of this inquiry, to do something that uses fuzzy logic.

Whether or not it is at all appropriate.

a7

Aaah !

Fuzzy logic has been around for decades, but I've never seen a problem that could not be solved without it.

Fuzzy logic must be good for something, or it would have gone away. Or maybe there are True Believers.

The fuzzy logic control is the essential part of the project. Its is an electrical engineering degree with the aim to create a control system so without this I fail as it is then too simplistic. No it is not for a whacky backy farm although I find it very funny that is what everyone thinks of as soon as I mention hydroponics. It is to take into account the renewable energy part of my degree and as an option for vertical farming for domestic properties. When I add the code for the TDS sensor the two results which should show different values, are coming out as zero even though the fuzzy logic control values are still changing. It means the pH up/down and nutrient solenoid valves are not going to open as the time is always zero regardless of what the pH and nutrient levels are. It is an arduino uno I am using but also an eleg uno r3 since the arduino uno was retaining code. It seems to work the same way in both though

Full code is:


#include <Fuzzy.h>
#include <EEPROM.h>
#include "GravityTDS.h"
#include <OneWire.h>
#include <DallasTemperature.h>

#define Nutrients 8
#define pHup 9
#define pHdown 10
#define Mixer 11
#define Pump 12

#define ONE_WIRE_BUS 7
#define TdsSensorPin A1

//TDS and temp
OneWire oneWire(ONE_WIRE_BUS);
GravityTDS gravityTds;

DallasTemperature sensors(&oneWire);

float tdsValue = 0;

//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, 50, 450);
FuzzySet *Medium = new FuzzySet(50, 450, 450, 850);
FuzzySet *High = new FuzzySet(450, 850, 1000, 1000);

// FuzzyOutput pH
FuzzySet *Short = new FuzzySet(0, 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(0, 0, 0, 7);
FuzzySet *M2 = new FuzzySet(0, 7, 7, 14);
FuzzySet *L2 = new FuzzySet(7, 14, 15, 15);


void setup() {
  //TDS and temp
  Serial.begin(9600);
  sensors.begin();
  gravityTds.setPin(TdsSensorPin);
  gravityTds.setAref(5.0);       //reference voltage on ADC, default 5.0V on Arduino UNO
  gravityTds.setAdcRange(1024);  //1024 for 10bit ADC;4096 for 12bit ADC
  gravityTds.begin();            //initialization

  //Actuators
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, 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(Medium);
  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(M2);
  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);



  // Building FuzzyRule 21 ph and 22 TDS
  FuzzyRuleAntecedent *ifpHVeryAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHVeryAcidicAndTDSMedium->joinWithAND(VeryAcidic, Medium);

  FuzzyRuleConsequent *thenT2M2 = new FuzzyRuleConsequent();
  thenT2M2->addOutput(M2);

  FuzzyRule *fuzzyRule21 = new FuzzyRule(21, ifpHVeryAcidicAndTDSMedium, thenTimeMiddle);
  fuzzy->addFuzzyRule(fuzzyRule21);

  FuzzyRule *fuzzyRule22 = new FuzzyRule(22, ifpHVeryAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule22);



  // Building FuzzyRule 23 ph and 24 TDS
  FuzzyRuleAntecedent *ifpHAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHAcidicAndTDSMedium->joinWithAND(Acidic, Medium);

  FuzzyRule *fuzzyRule23 = new FuzzyRule(23, ifpHAcidicAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule23);

  FuzzyRule *fuzzyRule24 = new FuzzyRule(24, ifpHAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule24);



  // Building FuzzyRule 25 pH and 26 TDS
  FuzzyRuleAntecedent *ifpHSlighltyAcidicAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHSlighltyAcidicAndTDSMedium->joinWithAND(SlightlyAcidic, Medium);

  FuzzyRule *fuzzyRule25 = new FuzzyRule(25, ifpHSlighltyAcidicAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule4);

  FuzzyRule *fuzzyRule26 = new FuzzyRule(26, ifpHSlighltyAcidicAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule26);



  // Building FuzzyRule 27 pH and 28 TDS
  FuzzyRuleAntecedent *ifpHAlkalineAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHAlkalineAndTDSMedium->joinWithAND(Alkaline, Medium);

  FuzzyRule *fuzzyRule27 = new FuzzyRule(27, ifpHAlkalineAndTDSMedium, thenTimeShort);
  fuzzy->addFuzzyRule(fuzzyRule27);

  FuzzyRule *fuzzyRule28 = new FuzzyRule(28, ifpHAlkalineAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule28);



  // Building FuzzyRule 29 pH and 30 TDS
  FuzzyRuleAntecedent *ifpHVeryAlkalineAndTDSMedium = new FuzzyRuleAntecedent();
  ifpHVeryAlkalineAndTDSMedium->joinWithAND(VeryAlkaline, Medium);

  FuzzyRule *fuzzyRule29 = new FuzzyRule(29, ifpHVeryAlkalineAndTDSMedium, thenTimeMiddle);
  fuzzy->addFuzzyRule(fuzzyRule29);

  FuzzyRule *fuzzyRule30 = new FuzzyRule(30, ifpHVeryAlkalineAndTDSMedium, thenT2M2);
  fuzzy->addFuzzyRule(fuzzyRule30);
}
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.58 * 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 = 36;
  delay(2000);
  Serial.print(distance);
  Serial.print(" cm");

  //TDS sensor and temp
  sensors.requestTemperatures();

  gravityTds.setTemperature(sensors.getTempCByIndex(0));  // set the temperature and execute temperature compensation
  gravityTds.update();                                    //sample and calculate
  tdsValue = gravityTds.getTdsValue();                    // then get the value

  Serial.print(tdsValue, 0);
  Serial.println("ppm");
  Serial.print("Temperature is: ");
  Serial.print(sensors.getTempCByIndex(0));

  delay(1500);

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

    // Fuzzy logic
    int input1 = 6;
    int input2 = 550;

    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("\n\tTDS: Low-> ");
    Serial.print(Low->getPertinence());
    Serial.print("\tTDS: Medium-> ");
    Serial.print(Medium->getPertinence());
    Serial.print(",  High-> ");
    Serial.println(High->getPertinence());

    float output1 = fuzzy->defuzzify(1);
    float output2 = fuzzy->defuzzify(2);

    Serial.println("\nOutput 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("\nOutput nutrient acutuator: ");
    Serial.print("\tT2: Short-> ");
    Serial.print(S2->getPertinence());
    Serial.print(", Middle-> ");
    Serial.print(M2->getPertinence());
    Serial.print(", Long-> ");
    Serial.println(L2->getPertinence());


    Serial.println("\nResult: ");
    Serial.print(output1);
    Serial.println("\nResult: ");
    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(200);
      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);
  }
}

input1 is an int variable.

Your code needs some serious trimming - you define a function to read the ultrasonic ranger, but don't appear to call it.
You do a bubble sort - why not use a sort from a library?

Did you breadboard the fuzzy logic code without the sensors?

Sorry I don't understand what you mean. Like I say I don't know much about coding. The ultrasonic sensor has been fixed to read set distance just to see the code working without having to constantly set up the whole system. It would normally have distance = (duration / 2) / 29.1; in place of distance = 36; so it does actually use it. the ph and TDS sensors would be used as input 1 and 2 but since they are not working I have set them to a value to test the code. I have no idea what a bubble sort is. I have set up all the components with the sensors on a breadboard and everything works until you add the code for the TDS and temp sensors. This code works fine on its own but not together with the rest. Likewise the fuzzy logic, pH and ultrasonic sensors all work together when tested on a breadboard with real sensors but as soon as I add the code for TDS then the output goes to zero and everything stops working

Which part?
The bit about the relative futility of comparing an int variable to a float value?

The bit about defining a function but not using it?

The bit about sorting, presumably to do some sort of median filter?

The bit about testing the fuzzy logic in isolation from the hardware?

I think @anon56112670 was drawing your attention to some serious mistaken logic.

Google

c++ operator precedence

The not operator ! has higher precedence then the greater than or equal to >= operator.

The above is the same as

( (!input1) >= 5.5)

and so with many others.

// (!input1 >= 5.5)
int input1;

void setup() {
  Serial.begin(115200);


  Serial.println("Hello Operator Precedence World\n\n");
    
  input1 = 4;
    
  if (!input1 >= 5) Serial.println("DOESNT input1 is not greater then or equal to 5\n");

  if (!(input1 >= 5)) Serial.println("DOES input1 is not greater then or equal to 5\n");
}

void loop(){}

Got some work to do. How well was this working before you added your additions?

a7

Thanks Alto777. Before I had this

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

which worked fine but someone pointed out that it could input 1 could never be true (although it behaved as it was supposed to). I am trying to make it that the code will loop only if the pH is NOT between 5.5 and 6.5 i.e. the loop will stop when running when the pH is between 5.5 and 6.5. It actually worked fine when I was using a random number generator like the fuzzy logic example code shows you to do. But I thought I thought it may cause a conflict so tried to change it

Input1 is an integer. For it to be true in a logical expression, all it has to be is non-zero.

So if input1 is, say 6, then !input1 is… false. Or 0.

I can't tell if you understand my point. Run the sketch I posted, then look at

    if (!input1 >= 5.5)…

No matter what input1 is, the first thing is false or true 0 or 1. That will never be greater than or equal to 5.5, so the hole condition is always false.

a7

I think I understand what you mean but I cannot get the code to work if I remove the int before input1. I want it to use the (phValue) for input1 and thought I had it all working fine when I tested it with the sensor but to be honest I have lost track now with the endless issues I have had with this project

I don't see anyone suggesting that.

In a program, variables have types, and those types should be chosen to reflect the roll the variable is going to play in the logic.

You may want integers if you were, say, counting something. You may want floating point variables if you were representing a value from the real world, like pH or mass or whatever.


I am still trying to make sure you understand the difference between

if (!input1 >= 5) 

and

  if (!(input1 >= 5))

both expressions do something. One does what it looks like you meant, the other does something different.

a7

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