How to calibrate PH sensor and TDS sensor using ESP32

Why?

If you’d read (and understood) the link I provided in post #2 of this topic then you wouldn’t be asking this question.

Pete.

1 Like

I’m trying to put notification in my blynk. The concept of my project is that it can monitor the ph reading, tds reading and water level of water using blynk. I can now see the readings of each sensor. Now this time I want to add notification that if for example, the reading of pH sensor is less than the desired value, it will notify me with gmail. I added some code in my sketch but the error is this.

Compilation error: conversion from 'int' to 'const String' is ambiguous

This is the code that I uploaded

// Fill-in information from your Blynk Template here
#define BLYNK_TEMPLATE_ID "TMPL7li3j7BK"
#define BLYNK_DEVICE_NAME "PH TDS and FLOAT sensor"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

// Uncomment your board, or configure a custom board in Settings.h
#define USE_WROVER_BOARD
//#define USE_TTGO_T7
//#define USE_ESP32C3_DEV_MODULE
//#define USE_ESP32S2_DEV_KIT

#include "BlynkEdgent.h"

BlynkTimer timer; // Announcing the timer

#define PH_Pin 33          //pH meter Analog output to Arduino Analog Input 
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;

int fl_Sensor=32;
int fval=0;
int Redled=5;

int f;  // for float value to string converstion
float val; // also works with double. 
char buff2[10];
String valueString = "";
String PH_Val = ""; 

int DSPIN = 14; // Dallas Temperature Sensor
int TDS_Sensor = 34;
float Aref = 2.3;

float ec_Val = 0;
unsigned int tds_value = 0;
float ecCal = 1;

WidgetLED ledglow(V5); // add virtual LED to V5

void float_Data()
{
 fval = digitalRead(fl_Sensor);  
 if (fval == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "WATER LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "WATER LEVEL - LOW" ); 
  }

  /*
  if(fval = 1)
    {
      Blynk.email("capstonegroup718@gmail.com","Alert","Water Level High!");
      Blynk.logEvent("float_sensor","Water Level High!");
    }  
*/   


}

void TDS_Data()
{
  // double wTemp = TempRead()* 0.0625;  // conversion accuracy is 0.0625 / LSB
  double wTemp= 27;
  float V_level= Aref / 3500.0;
  float rawEc = analogRead(TDS_Sensor) * V_level;  // Raw  data of EC
  float T_Cof = 1.0 + 0.02 * (wTemp - 25.0);  // Temperature Coefficient
  
  ec_Val = (rawEc / T_Cof) * ecCal;// temperature and calibration compensation
  tds_value = (133.42 * pow(ec_Val, 3) - 255.86 * ec_Val * ec_Val + 857.39 * ec_Val) * 0.5; 
  double Far= (((wTemp *9)/5) + 32); // Temp in Far*
  
  Serial.print("TDS:"); Serial.println(tds_value);
  Serial.print("EC:"); Serial.println(ec_Val, 2);
  Serial.print("Temperature (oC):"); Serial.println(wTemp,2);   
  Serial.print("Temperature (oF):"); Serial.println(Far,2);
  Serial.print("");
 
/*
  if(tds_value < 150)
    {
      Blynk.email("capstonegroup718@gmail.com","Alert","Low Nutrients!");
      Blynk.logEvent("nutrient_warning","Low Nutrients!");
    }  
*/ 

  Blynk.virtualWrite(V1, wTemp);
  Blynk.virtualWrite(V2, Far);
  Blynk.virtualWrite(V3, tds_value);
  Blynk.virtualWrite(V4, ec_Val);

}
void PH_Data()
{
  for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(PH_Pin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    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++)                      //take the average value of 6 center sample
  avgValue+=buf[i];
  float phValue=(float)avgValue*3.0/1024/14; //convert the analog into millivolt
  phValue=4.5*phValue;                      //convert the millivolt into pH value
  
  PH_Val =  dtostrf(phValue, 4, 2, buff2);  //4 is mininum width, 6 is precision
  Serial.print(PH_Val);
  valueString = "";
  delay(1000);
  


  Blynk.virtualWrite(V0, PH_Val);

  
  if (PH_Val < 4)
    {
      Blynk.email("capstonegroup718@gmail.com","Alert","PH reading low level!");
      Blynk.logEvent("ph_warning","PH reading low level!");
    }  
}

void setup()
{
  Serial.begin(9600);
  delay(100);
  pinMode(fl_Sensor, INPUT_PULLUP); // Float Sensor
  pinMode(Redled, OUTPUT); // Red LED
  timer.setInterval(1000L, PH_Data); //timer will run every sec 
  timer.setInterval(1000L, TDS_Data); //timer will run every sec 
  timer.setInterval(1000L, float_Data); //timer will run every sec 
  BlynkEdgent.begin();
}

void loop() {
  BlynkEdgent.run();
  timer.run();        // run timer every second
}

It is no longer necessary to include Blynk.email because Blynk.logEvent has taken its place.

Thank you sir. But I get this error

C:\Users\ADDESSA\Documents\Arduino\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino: In function 'void PH_Data()':
C:\Users\ADDESSA\Documents\Arduino\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:144:13: error: no match for 'operator<' (operand types are 'String' and 'double')
   if(PH_Val < 4.5)
      ~~~~~~~^~~~~
In file included from C:\Users\ADDESSA\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\cores\esp32/Arduino.h:166,
                 from C:\Users\ADDESSA\AppData\Local\Temp\arduino-sketch-26F673C7896A6972839E191F7C8B1308\sketch\FINAL!!!Edgent_ESP32_Sensors.ino.cpp:1:
C:\Users\ADDESSA\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\cores\esp32/WString.h:219:23: note: candidate: 'unsigned char String::operator<(const String&) const'
         unsigned char operator <(const String &rhs) const;
                       ^~~~~~~~
C:\Users\ADDESSA\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\cores\esp32/WString.h:219:23: note:   no known conversion for argument 1 from 'double' to 'const String&'
Multiple libraries were found for "BlynkSimpleEsp32_SSL.h"
  Used: C:\Users\ADDESSA\Documents\Arduino\libraries\Blynk
  Not used: C:\Users\ADDESSA\Documents\Arduino\libraries\blynk-library-master
exit status 1

Compilation error: no match for 'operator<' (operand types are 'String' and 'double')

4.5 is a double type, while PH_Val is a String type.
The PH_Val should be changed to a double or integer instead.

This is part of a function which is called once every second.
Blynk has a limit of 100 events per 24 hour period, so if PH < 4 for more than 100 seconds then you’ll have used-up your quota of events, and associated notifications/emails attached to that event.

The solution is to use a ‘flag’ variable so that you only log one event for each situation where PH < 4

Read this for more info…

Pete.

I changed it to double. This is the error

C:\Users\Admin\Desktop\LM\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:43:17: error: cannot convert 'const char*' to 'double' in initialization
 double PH_Val = ""; 
                 ^
C:\Users\Admin\Desktop\LM\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino: In function 'void PH_Data()':
C:\Users\Admin\Desktop\LM\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:138:10: error: cannot convert 'char*' to 'double' in assignment
   PH_Val =  dtostrf(phValue, 4, 2, buff2);  //4 is mininum width, 6 is precision
          ^

exit status 1

Compilation error: cannot convert 'const char*' to 'double' in initialization

@JemJem would you please explain why you appear to be using two usernames on this forum?

Pete.

Sorry I’m using my laptop 4h ago. Now I’m using my computer. I forgot to change the account.

That hasn’t explained to me why you have two accounts.

One of your accounts is going to be locked. Please tell me which one you’d like this to be.

Pete

Blocked the Ricky1 account. I’m sorry

The dtostrf() function converts the float into a string. There’s no need to use it. You can get rid of it.

This is the code after editing the sketch. Is this true?

#define BLYNK_TEMPLATE_ID "TMPL7li3j7BK"
#define BLYNK_DEVICE_NAME "PH TDS and FLOAT sensor"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

// Uncomment your board, or configure a custom board in Settings.h
#define USE_WROVER_BOARD
//#define USE_TTGO_T7
//#define USE_ESP32C3_DEV_MODULE
//#define USE_ESP32S2_DEV_KIT

#include "BlynkEdgent.h"

BlynkTimer timer; // Announcing the timer

#define PH_Pin 33          //pH meter Analog output to Arduino Analog Input 
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;

int fl_Sensor=32;
int fval=0;
int Redled=5;
//BlynkTimer timer;
int f;  // for float value to string converstion
float val; // also works with double. 
char buff2[10];
double valueString = "";
double PH_Val = ""; 

int DSPIN = 14; // Dallas Temperature Sensor
int TDS_Sensor = 34;
float Aref = 2.3;

float ec_Val = 0;
unsigned int tds_value = 0;
float ecCal = 1;

WidgetLED ledglow(V5); // add virtual LED to V5

void float_Data()
{
 fval = digitalRead(fl_Sensor);  
 if (fval == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "WATER LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "WATER LEVEL - LOW" ); 
  }

  
  if(fval = 1)
    {
      Blynk.logEvent("float_sensor","Water Level High!");
    }  
     


}

void TDS_Data()
{
  // double wTemp = TempRead()* 0.0625;  // conversion accuracy is 0.0625 / LSB
  double wTemp= 27;
  float V_level= Aref / 3500.0;
  float rawEc = analogRead(TDS_Sensor) * V_level;  // Raw  data of EC
  float T_Cof = 1.0 + 0.02 * (wTemp - 25.0);  // Temperature Coefficient
  
  ec_Val = (rawEc / T_Cof) * ecCal;// temperature and calibration compensation
  tds_value = (133.42 * pow(ec_Val, 3) - 255.86 * ec_Val * ec_Val + 857.39 * ec_Val) * 0.5; 
  double Far= (((wTemp *9)/5) + 32); // Temp in Far*
  
  Serial.print("TDS:"); Serial.println(tds_value);
  Serial.print("EC:"); Serial.println(ec_Val, 2);
  Serial.print("Temperature (oC):"); Serial.println(wTemp,2);   
  Serial.print("Temperature (oF):"); Serial.println(Far,2);
  Serial.print("");
 

  if(tds_value < 150)
    {
      Blynk.logEvent("nutrient_warning","Low Nutrients!");
    }  
   

  Blynk.virtualWrite(V1, wTemp);
  Blynk.virtualWrite(V2, Far);
  Blynk.virtualWrite(V3, tds_value);
  Blynk.virtualWrite(V4, ec_Val);

}
void PH_Data()
{
  for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(PH_Pin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    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++)                      //take the average value of 6 center sample
  avgValue+=buf[i];
  float phValue=(float)avgValue*3.0/1024/14; //convert the analog into millivolt
  phValue=4.5*phValue;                      //convert the millivolt into pH value
  
  //PH_Val =  dtostrf(phValue, 4, 2, buff2);  //4 is mininum width, 6 is precision
  Serial.print(PH_Val);
  valueString = "";
  delay(1000);
  
  
  if(PH_Val < 4.5)
    {
      Blynk.logEvent("ph_warning","PH reading low level!");
    }  
  

  Blynk.virtualWrite(V0, PH_Val);
}


void setup()
{
  Serial.begin(9600);
  delay(100);
  pinMode(fl_Sensor, INPUT_PULLUP); // Float Sensor
  pinMode(Redled, OUTPUT); // Red LED
  timer.setInterval(1000L, PH_Data); //timer will run every sec 
  timer.setInterval(1000L, TDS_Data); //timer will run every sec 
  timer.setInterval(1000L, float_Data); //timer will run every sec 
  BlynkEdgent.begin();
}

void loop() {
  BlynkEdgent.run();
  timer.run();        // run timer every second
}

Should be

double valueString;
double PH_Val; 

Should be

PH_Value=4.5*phValue;

You shouldn’t use delay because it’s a blocking function. Get rid of it.

Three separate functions being called at the same time might lead to problems later. You can change it to

timer.setInterval(1000L, PH_Data); //timer will run every sec 
  timer.setInterval(2000L, TDS_Data); //timer will run every sec 
  timer.setInterval(3000L, float_Data); //timer will run every sec

@JemJem I’ve merged this topic with the one that you created using your other (now deactivated) username.

The two topics are clearly about the same piece of code, and issues already raised are being repeated again here.

Pete.

Thank you John93

1 Like

Okay Pete

I am trying to add 3 additional float sensor in this project. I edited the sketch but it says error. This is the code:

/*
 * PH Sensor- 33
 * TDS Sensor- 32
 * Float Sensor1- 34
 * Float Sensor2- 35
 * Float Sensor3- 25
 * Float Sensor4- 26
 * Led - 5 // Red Led
 */


// Fill-in information from your Blynk Template here
#define BLYNK_TEMPLATE_ID "TMPL7li3j7BK"
#define BLYNK_DEVICE_NAME "PH TDS and FLOAT sensor"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

// Uncomment your board, or configure a custom board in Settings.h
#define USE_WROVER_BOARD
//#define USE_TTGO_T7
//#define USE_ESP32C3_DEV_MODULE
//#define USE_ESP32S2_DEV_KIT

#include "BlynkEdgent.h"

BlynkTimer timer; // Announcing the timer
//PH SENSOR
#define PH_Pin 33          //pH meter Analog output to Arduino Analog Input 
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;

//FLOAT SENSOR 
int fl_Sensor=34;
int fval=0;
int Redled=5;

int fl_Sensor2=35;
int fval2=0;

int fl_Sensor3=25;
int fval3=0;

int fl_Sensor4=26;
int fval4=0;

//BlynkTimer timer;
int f;  // for float value to string converstion
float val; // also works with double. 
char buff2[10];
double valueString;
double PH_Val; 

int DSPIN = 14; // Dallas Temperature Sensor
int TDS_Sensor = 32;
float Aref = 2.3;

float ec_Val = 0;
unsigned int tds_value = 0;
float ecCal = 1;

WidgetLED ledglow(V5); // add virtual LED to V5

void float_Data1()
{
// WATER LEVEL
 fval = digitalRead(fl_Sensor);  
 if (fval == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "WATER LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "WATER LEVEL - LOW" ); 
  }

   if(fval = 1)
    {
      Blynk.logEvent("water_float","WATER Level High!");
    }
}

WidgetLED ledglow(V6); // add virtual LED to V6

void float_Data2()
{
// NUTRIENTS
  fval2 = digitalRead(fl_Sensor2);  
 if (fval2 == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "NUTRIENT LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "NUTRIENT LEVEL - LOW" ); 
  }

  if(fval2 = 0)
    {
      Blynk.logEvent("nutrient_float","NUTRIENT Level Low!");
    }
}

WidgetLED ledglow(V2); // add virtual LED to V2

void float_Data3()
{
// ACID
fval3 = digitalRead(fl_Sensor3);  
 if (fval3 == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "PH ACID LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "PH ACID LEVEL - LOW" ); 
  }

  if(fval3 = 0)
    {
      Blynk.logEvent("phacid_float","PH ACID Level Low!");
    }
}

WidgetLED ledglow(V1); // add virtual LED to V1

void float_Data4()
{
// BASE
fval4 = digitalRead(fl_Sensor4);  
 if (fval4 == LOW) 
  { 
    digitalWrite(Redled, HIGH);
    ledglow.on();
    Serial.println( "PH BASE LEVEL - HIGH"); 
  } 
  else 
  { 
    digitalWrite(Redled, LOW);
    ledglow.off();
    Serial.println( "PH BASE LEVEL - LOW" ); 
  }
  
  if(fval4 = 0)
    {
      Blynk.logEvent("phbase_float","PH BASE Level Low!");
    }  
}

void TDS_Data()
{
  // double wTemp = TempRead()* 0.0625;  // conversion accuracy is 0.0625 / LSB
  double wTemp= 27;
  float V_level= Aref / 3500.0;
  float rawEc = analogRead(TDS_Sensor) * V_level;  // Raw  data of EC
  float T_Cof = 1.0 + 0.02 * (wTemp - 25.0);  // Temperature Coefficient
  
  ec_Val = (rawEc / T_Cof) * ecCal;// temperature and calibration compensation
  tds_value = (133.42 * pow(ec_Val, 3) - 255.86 * ec_Val * ec_Val + 857.39 * ec_Val) * 0.5; 
  double Far= (((wTemp *9)/5) + 32); // Temp in Far*
  
  Serial.print("TDS:"); Serial.println(tds_value);
  Serial.print("EC:"); Serial.println(ec_Val, 2);
  Serial.print("Temperature (oC):"); Serial.println(wTemp,2);   
  Serial.print("Temperature (oF):"); Serial.println(Far,2);
  Serial.print("");

  if(tds_value < 150)
    {
      Blynk.logEvent("nutrient_warning","Low Nutrients!");
    }  
   
  Blynk.virtualWrite(V1, wTemp);
  Blynk.virtualWrite(V2, Far);
  Blynk.virtualWrite(V3, tds_value);
  Blynk.virtualWrite(V4, ec_Val);

}

void PH_Data()
{
  for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(PH_Pin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    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++)                      //take the average value of 6 center sample
  avgValue+=buf[i];
  float phValue=(float)avgValue*3.0/1024/14; //convert the analog into millivolt
  PH_Val=4.5*phValue;                      //convert the millivolt into pH value
  
  //PH_Val =  dtostrf(phValue, 4, 2, buff2);  //4 is mininum width, 6 is precision
  Serial.print(PH_Val);
  valueString;
  //delay(1000);
  
  
  if(PH_Val < 4.5)
    {
      Blynk.logEvent("ph_warning","PH reading low level!");
    }  
  

  Blynk.virtualWrite(V0, PH_Val);
}


void setup()
{
  Serial.begin(9600);
  delay(100);
  pinMode(fl_Sensor, INPUT_PULLUP); // Float Sensor
  pinMode(Redled, OUTPUT); // Red LED
  timer.setInterval(1000L, PH_Data); //timer will run every sec 
  timer.setInterval(2000L, TDS_Data); //timer will run every sec 
  timer.setInterval(3000L, float_Data1); //timer will run every sec
  timer.setInterval(4000L, float_Data2); //timer will run every sec
  timer.setInterval(5000L, float_Data3); //timer will run every sec
  timer.setInterval(6000L, float_Data4); //timer will run every sec
  BlynkEdgent.begin();
}

void loop() {
  BlynkEdgent.run();
  timer.run();        // run timer every second
}

This is the error:

L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:92:18: error: redefinition of 'WidgetLED ledglow'
 WidgetLED ledglow(V6); // add virtual LED to V6
                  ^
L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:67:11: note: 'WidgetLED ledglow' previously declared here
 WidgetLED ledglow(V5); // add virtual LED to V5
           ^~~~~~~
L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:117:18: error: redefinition of 'WidgetLED ledglow'
 WidgetLED ledglow(V2); // add virtual LED to V2
                  ^
L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:67:11: note: 'WidgetLED ledglow' previously declared here
 WidgetLED ledglow(V5); // add virtual LED to V5
           ^~~~~~~
L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:142:18: error: redefinition of 'WidgetLED ledglow'
 WidgetLED ledglow(V1); // add virtual LED to V1
                  ^
L:\FINAL!!!Edgent_ESP32_Sensors\FINAL!!!Edgent_ESP32_Sensors.ino:67:11: note: 'WidgetLED ledglow' previously declared here
 WidgetLED ledglow(V5); // add virtual LED to V5
           ^~~~~~~
Multiple libraries were found for "BlynkSimpleEsp32_SSL.h"
  Used: C:\Users\ADDESSA\Documents\Arduino\libraries\Blynk
  Not used: C:\Users\ADDESSA\Documents\Arduino\libraries\blynk-library-master
exit status 1

Compilation error: redefinition of 'WidgetLED ledglow'

This line of code is effectively saying “let me refer to the LED widget attached to pin V5 as “ledglow” in the rest of this sketch”.

But then you’re saying…

which is saying that you now want to refer to the LED attached to pin V6 as “ledglow” instead.

The compiler is complaining because these widget alias names need to be unique and yours are all the same.

However, the whole WidgetLED is really a legacy hangover and is recommend you don’t use it anyway. Simply do a Blynk.virtualWrite to the virtual pin, or define an alias for the pin and do a Blynk.virtualWrite to that alias name.

Pete.