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