BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Help in blynk terminal setup

hello everyone i am new to blynk and i am trying to use it to monitor and control Ph of water … so i working with esp32 and i was trying to add this code from DFRobot_ESP_PH_BY_GREENPONIK
but this code is using serial monitor in arduino app to enter commands to set the ph calibration as the following

 * file DFRobot_ESP_PH.cpp * @ https://github.com/GreenPonik/DFRobot_ESP_PH_BY_GREENPONIK
 *
 * Arduino library for Gravity: Analog pH Sensor / Meter Kit V2, SKU: SEN0161-V2
 * 
 *
 * ##################################################
 * ##################################################
 * ########## Fork on github by GreenPonik ##########
 * ############# ONLY ESP COMPATIBLE ################
 * ##################################################
 * ##################################################
 * 
 * version  V1.0
 * date  2019-05
 */

#include "Arduino.h"
#include "DFRobot_ESP_PH.h"
#include "EEPROM.h"


#define PH_3_VOLTAGE 2010

DFRobot_ESP_PH::DFRobot_ESP_PH()
{
    this->_temperature = 25.0;
    this->_phValue = 7.0;
    this->_acidVoltage = 2032.44;   //buffer solution 4.0 at 25C
    this->_neutralVoltage = 1500.0; //buffer solution 7.0 at 25C
    this->_voltage = 1500.0;
}

DFRobot_ESP_PH::~DFRobot_ESP_PH()
{
}

void DFRobot_ESP_PH::begin()
{
    //check if calibration values (neutral and acid) are stored in eeprom
    this->_neutralVoltage = EEPROM.readFloat(PHVALUEADDR); //load the neutral (pH = 7.0)voltage of the pH board from the EEPROM
    if (this->_neutralVoltage == float() || isnan(this->_neutralVoltage))
    {
        this->_neutralVoltage = 1500.0; // new EEPROM, write typical voltage
        EEPROM.writeFloat(PHVALUEADDR, this->_neutralVoltage);
        EEPROM.commit();
    }

    this->_acidVoltage = EEPROM.readFloat(PHVALUEADDR + sizeof(float)); //load the acid (pH = 4.0) voltage of the pH board from the EEPROM
    if (this->_acidVoltage == float() || isnan(this->_acidVoltage))
    {
        this->_acidVoltage = 2032.44; // new EEPROM, write typical voltage
        EEPROM.writeFloat(PHVALUEADDR + sizeof(float), this->_acidVoltage);
        EEPROM.commit();
    }
}

float DFRobot_ESP_PH::readPH(float voltage, float temperature)
{
    // Serial.print("_neutraVoltage:");
    // Serial.print(this->_neutralVoltage);
    // Serial.print(", _acidVoltage:");
    // Serial.print(this->_acidVoltage);
    float slope = (7.0 - 4.0) / ((this->_neutralVoltage - 1500.0) / 3.0 - (this->_acidVoltage - 1500.0) / 3.0); // two point: (_neutralVoltage,7.0),(_acidVoltage,4.0)
    float intercept = 7.0 - slope * (this->_neutralVoltage - 1500.0) / 3.0;
    // Serial.print(", slope:");
    // Serial.print(slope);
    // Serial.print(", intercept:");
    // Serial.println(intercept);
    this->_phValue = slope * (voltage - 1500.0) / 3.0 + intercept; //y = k*x + b
    Serial.print("[readPH]... phValue ");
    Serial.println(this->_phValue);
    return this->_phValue;
    terminal.print("[readPH]... phValue");    // gendiaaa add
    terminal.println( this->_phValue);     //
    

}

void DFRobot_ESP_PH::calibration(float voltage, float temperature, char *cmd)
{
    this->_voltage = voltage;
    this->_temperature = temperature;
    strupr(cmd);
    phCalibration(cmdParse(cmd)); // if received Serial CMD from the serial monitor, enter into the calibration mode
}

void DFRobot_ESP_PH::calibration(float voltage, float temperature)
{
    this->_voltage = voltage;
    this->_temperature = temperature;
    if (cmdSerialDataAvailable() > 0)
    {
        phCalibration(cmdParse()); // if received Serial CMD from the serial monitor, enter into the calibration mode
    }
}

boolean DFRobot_ESP_PH::cmdSerialDataAvailable() /////////kjuhggfd
{
    char cmdReceivedChar;
    static unsigned long cmdReceivedTimeOut = millis();
    while (Serial.available() > 0)
    {
        if (millis() - cmdReceivedTimeOut > 500U)
        {
            this->_cmdReceivedBufferIndex = 0;
            memset(this->_cmdReceivedBuffer, 0, (ReceivedBufferLength));
        }
        cmdReceivedTimeOut = millis();
        cmdReceivedChar = Serial.read();
        if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex == ReceivedBufferLength - 1)
        {
            this->_cmdReceivedBufferIndex = 0;
            strupr(this->_cmdReceivedBuffer);
            return true;
        }
        else
        {
            this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
            this->_cmdReceivedBufferIndex++;
        }
    }
    
    // gendiaaa Add
    while (terminal.available() > 0)
    {
        if (millis() - cmdReceivedTimeOut > 500U)
        {
            this->_cmdReceivedBufferIndex = 0;
            memset(this->_cmdReceivedBuffer, 0, (ReceivedBufferLength));
        }
        cmdReceivedTimeOut = millis();
        cmdReceivedChar = terminal.read();
        if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex == ReceivedBufferLength - 1)
        {
            this->_cmdReceivedBufferIndex = 0;
            strupr(this->_cmdReceivedBuffer);
            return true;
        }
        else
        {
            this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
            this->_cmdReceivedBufferIndex++;
        }
    }
    // gendiaaa Add
    return false;
}

byte DFRobot_ESP_PH::cmdParse(const char *cmd)
{
    byte modeIndex = 0;
    if (strstr(cmd, "ENTERPH") != NULL)
    {
        modeIndex = 1;
    }
    else if (strstr(cmd, "EXITPH") != NULL)
    {
        modeIndex = 3;
    }
    else if (strstr(cmd, "CALPH") != NULL)
    {
        modeIndex = 2;
    }
    return modeIndex;
}

byte DFRobot_ESP_PH::cmdParse()
{
    byte modeIndex = 0;
    if (strstr(this->_cmdReceivedBuffer, "ENTERPH") != NULL)
    {
        modeIndex = 1;
    }
    else if (strstr(this->_cmdReceivedBuffer, "EXITPH") != NULL)
    {
        modeIndex = 3;
    }
    else if (strstr(this->_cmdReceivedBuffer, "CALPH") != NULL)
    {
        modeIndex = 2;
    }
    return modeIndex;
}

void DFRobot_ESP_PH::phCalibration(byte mode)
{
    char *receivedBufferPtr;
    static boolean phCalibrationFinish = 0;
    static boolean enterCalibrationFlag = 0;
    switch (mode)
    {
    case 0:
        if (enterCalibrationFlag)
        {
            Serial.println(F(">>>Command Error<<<"));
            terminal.println(">>>Command Error<<<");            // gendiaaa add           
            
        }
        break;

    case 1:
        enterCalibrationFlag = 1;
        phCalibrationFinish = 0;
        Serial.println();
        Serial.println(F(">>>Enter PH Calibration Mode<<<"));
        Serial.println(F(">>>Please put the probe into the 4.0 or 7.0 standard buffer solution<<<"));
        Serial.println();
        terminal.println(">>>Enter PH Calibration Mode<<<");            // gendiaaa add    
        terminal.println(">>>Please put the probe into the 4.0 or 7.0 standard buffer solution<<<");
    
        break;

    case 2:
        if (enterCalibrationFlag)
        {
            if ((this->_voltage > PH_8_VOLTAGE) && (this->_voltage < PH_6_VOLTAGE))
            { // buffer solution:7.0
                Serial.println();
                Serial.print(F(">>>Buffer Solution:7.0"));
                terminal.print(">>>Buffer Solution:7.0\"");            // gendiaaa add           
                
                this->_neutralVoltage = this->_voltage;
                Serial.println(F(",Send EXITPH to Save and Exit<<<"));
                Serial.println();
                terminal.print(",Send EXITPH to Save and Exit<<<\"");     // gendiaaa add           
                
                phCalibrationFinish = 1;
            }
            else if ((this->_voltage > PH_5_VOLTAGE) && (this->_voltage < PH_3_VOLTAGE))
            { //buffer solution:4.0
                Serial.println();
                Serial.print(F(">>>Buffer Solution:4.0"));
                terminal.print(">>>Buffer Solution:4.0\"");     // gendiaaa add           
               
                this->_acidVoltage = this->_voltage;
                Serial.println(F(",Send EXITPH to Save and Exit<<<"));
                Serial.println();
                terminal.print(",Send EXITPH to Save and Exit<<<\"");     // gendiaaa add           
               
                phCalibrationFinish = 1;
            }
            else
            {
                Serial.println();
                Serial.print(F(">>>Buffer Solution Error Try Again<<<"));
                Serial.println(); // not buffer solution or faulty operation
                terminal.print(">>>Buffer Solution Error Try Again<<<\"");     // gendiaaa add           
                
                phCalibrationFinish = 0;
            }
        }
        break;

    case 3: //store calibration value in eeprom
        if (enterCalibrationFlag)
        {
            Serial.println();
            if (phCalibrationFinish)
            {
                if ((this->_voltage > PH_8_VOLTAGE) && (this->_voltage < PH_5_VOLTAGE))
                {
                    EEPROM.writeFloat(PHVALUEADDR, this->_neutralVoltage);
                    EEPROM.commit();
                }
                else if ((this->_voltage > PH_5_VOLTAGE) && (this->_voltage < PH_3_VOLTAGE))
                {
                    EEPROM.writeFloat(PHVALUEADDR + sizeof(float), this->_acidVoltage);
                    EEPROM.commit();
                }
                Serial.print(F(">>>Calibration Successful"));
                terminal.print(">>>Calibration Successful\"");     // gendiaaa add           
                
            }
            else
            {
                Serial.print(F(">>>Calibration Failed"));
                terminal.print(">>>Calibration Failed\"");     // gendiaaa add           
                
            }
            Serial.println(F(",Exit PH Calibration Mode<<<"));
            Serial.println();
            terminal.print(",Exit PH Calibration Mode<<<\"");     // gendiaaa add           
            
            phCalibrationFinish = 0;
            enterCalibrationFlag = 0;
        }
        break;
    }
}

as you see i am trying to add terminal.print but its not decleared ! whatever in the main source
i included the blynk as shown here


#ifdef ESP8266
#include <BlynkSimpleEsp8266.h>
#elif defined(ESP32)
#include <BlynkSimpleEsp32.h>
#else
#error "Board not found"
#endif



credentials Credentials;

#include "DFRobot_ESP_PH.h"
#include "EEPROM.h"
WidgetTerminal terminal(V1);
DFRobot_ESP_PH ph;
#define ESPADC 4096.0   //the esp Analog Digital Convertion value
#define ESPVOLTAGE 3300 //the esp voltage supply value
#define PH_PIN 36    //the esp gpio data pin number
float voltage, phValue, temperature = 25;

//Variables
char auth_token[33];
bool connected_to_internet = 0;
const int Erasing_button = 15;


//Provide credentials for your ESP server
char* esp_ssid = "EgyReef";
char* esp_pass = "";


void setup()

{

  Serial.begin(115200);
  pinMode(Erasing_button, INPUT);


  for (uint8_t t = 4; t > 0; t--) {
    Serial.println(t);
    delay(1000);
  }

  // Press and hold the button to erase all the credentials
  if (digitalRead(Erasing_button) == LOW)
  {
    Credentials.Erase_eeprom();

  }

  String auth_string = Credentials.EEPROM_Config();
  auth_string.toCharArray(auth_token, 33);

  if (Credentials.credentials_get())
  {

    Blynk.config(auth_token);
    connected_to_internet = 1;

  }
  else
  {
    Credentials.setupAP(esp_ssid, esp_pass);
    connected_to_internet = 0;
  }


  if (connected_to_internet)
  {

    //SETUP FOR MY PH CODE 
     EEPROM.begin(32);//needed to permit storage of calibration value in eeprom
  ph.begin();
    //END SETUP FOR PH
    
  }



}



void loop()
{
  Credentials.server_loops();

  if (connected_to_internet)
  {


    //LOOP CODE FOR PH
    static unsigned long timepoint = millis();
  if (millis() - timepoint > 1000U) //time interval: 1s
  {
    timepoint = millis();
    //voltage = rawPinValue / esp32ADC * esp32Vin
    voltage = analogRead(PH_PIN) / ESPADC * ESPVOLTAGE; // read the voltage
    Serial.print("voltage:");
    Serial.println(voltage, 4);
    
    //temperature = readTemperature();  // read your temperature sensor to execute temperature compensation
    Serial.print("temperature:");
    Serial.print(temperature, 1);
    Serial.println("^C");

    phValue = ph.readPH(voltage, temperature); // convert voltage to pH with temperature compensation
    Serial.print("pH:");
    Serial.println(phValue, 4);
    Blynk.virtualWrite(V3, phValue);
    
  }
  ph.calibration(voltage, temperature); // calibration process by Serail CMD
}


    //END LOOP FOR PH
    
    Blynk.run();
     
  
}

@gendiaaa please edit your post, using the pencil icon at the bottom, and add triple backticks at the beginning and end of your code so that it displays correctly.
Triple backticks look like this:
```

Pete.

1 Like

thank you for help :slight_smile: i can write here now i wish i can write by blink code well :slight_smile:

I don’t understand your question.

There are two ways to send data to the Terminal widget…

You can either use the standard Blynk.virtualWrite(vPin,value) command to send data direct to the virtual pin that the Terminal widget is attached to.

Or

You can use the wrapper functionality and declare a widget terminal object like this:
WidgetTerminal terminal(VPin);
The use the terminal.print functionality.

Pete.

OKAY i used WidgetTerminal terminal(V1); the code is using the serial monitor to send command to the board in this program you can see ENTERPH if i write this in the arduino serial monitor the code will run the calibration function … so the code is consist of three files the .ino file and .cpp and .h in the .cpp file the code written like that

{
    char cmdReceivedChar;
    static unsigned long cmdReceivedTimeOut = millis();
    while (Serial.available() > 0)
    {
        if (millis() - cmdReceivedTimeOut > 500U)
        {
            this->_cmdReceivedBufferIndex = 0;
            memset(this->_cmdReceivedBuffer, 0, (ReceivedBufferLength));
        }
        cmdReceivedTimeOut = millis();
        cmdReceivedChar = Serial.read();
        if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex == ReceivedBufferLength - 1)
        {
            this->_cmdReceivedBufferIndex = 0;
            strupr(this->_cmdReceivedBuffer);
            return true;
        }
        else
        {
            this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
            this->_cmdReceivedBufferIndex++;
        }
    }

and i added another one like that

while (terminal.available() > 0)
    {
        if (millis() - cmdReceivedTimeOut > 500U)
        {
            this->_cmdReceivedBufferIndex = 0;
            memset(this->_cmdReceivedBuffer, 0, (ReceivedBufferLength));
        }
        cmdReceivedTimeOut = millis();
        cmdReceivedChar = terminal.read();
        if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex == ReceivedBufferLength - 1)
        {
            this->_cmdReceivedBufferIndex = 0;
            strupr(this->_cmdReceivedBuffer);
            return true;
        }
        else
        {
            this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
            this->_cmdReceivedBufferIndex++;
        }
    }
  
    return false;
}

but when i do that error like that
E:\Arduino\arduino-nightly\libraries\DFRobot_ESP_PH_BY_GREENPONIK-master\src\DFRobot_ESP_PH.cpp: In member function ‘float DFRobot_ESP_PH::readPH(float, float)’:
E:\Arduino\arduino-nightly\libraries\DFRobot_ESP_PH_BY_GREENPONIK-master\src\DFRobot_ESP_PH.cpp:76:5: error: ‘terminal’ was not declared in this scope
terminal.print("[readPH]… phValue ");

So, are you saying that you are trying to enter data into the Blynk Terminal widget, and that you want to receive and process this data in the same way as if it were entered via the serial monitor?

If so, you need to use the BLYNK_WRITE(V1) callback and one of the param.asvariable type commands.

However, there are much neater ways of doing this with other Blynk widgets instead of the Terminal widget.

But, have you searched the forum for other projects made with Blynk which monitor Ph values (there are a few)?

Pete.

first : yes i want to receive and process data like done in serial monitor … and the beauty of this code i am using its sense what is the calibration solution ph and and adjust the reading accordingly…
second: yes please can you help me how to use the BLYNK_WRITE(V1) callback and one of the param.asvariable type commands … i used terminal.available() and also terminal.print in the .cpp file but its making error even when i put Blynk.virtualWrite(v1) in the .ino file

Read this:

There is no terminal.available, and terminal.print isn’t designed to be used in that way.

Pete.

1 Like

thank you sir :star_struck: its very useful and easy to understand i will try to implement that in the code

now i am starting to understand after reading through your posts and really i appreciate your kindly help … now i done it well getting both ph and temperature in the blynk app using also OTABlynkCredentials
i will post the code here so any one can use it and go through it

#include "OTABlynkCredentials.h"

#ifdef ESP8266
#include <BlynkSimpleEsp8266.h>
#elif defined(ESP32)
#include <BlynkSimpleEsp32.h>
#else
#error "Board not found"
#endif

#include <WiFi.h>
#include <WiFiClient.h>
credentials Credentials;



//Variables
char auth_token[33];
bool connected_to_internet = 0;
const int Erasing_button = 0;


//Provide credentials for your ESP server
char* esp_ssid = "Egyreef.com";
char* esp_pass = "";

//
#include "DFRobot_ESP_PH.h"
#include "EEPROM.h"
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;

DFRobot_ESP_PH ph;
#define ESPADC 4096.0   //the esp Analog Digital Convertion value
#define ESPVOLTAGE 3300 //the esp voltage supply value
#define PH_PIN 35    //the esp gpio data pin number

float voltage, phValue, temperature = 0;
BlynkTimer timer;
void myTimerEvent()
{
 Serial.print("Requesting temperatures...");
 sensors.requestTemperatures(); // Send the command to get temperatures
 Serial.println("DONE");
 temperature = sensors.getTempCByIndex(0); // Save the reading to use later
 Serial.print("Temperature is: ");
 Serial.println(temperature); // print the reading that we just took
 Blynk.virtualWrite(V1, temperature); // and send the same reading to virtual pin 5
}


void myTimerEvent2()
{
 static unsigned long timepoint = millis();
 if (millis() - timepoint > 1000U) //time interval: 1s
 {
   timepoint = millis();
   //voltage = rawPinValue / esp32ADC * esp32Vin
   voltage = analogRead(PH_PIN) / ESPADC * ESPVOLTAGE; // read the voltage
   phValue = ph.readPH(voltage, temperature); // convert voltage to pH with temperature compensation
   Serial.print("pH:");
   Serial.println(phValue, 4);
   Blynk.virtualWrite(V3, phValue);
 }
 ph.calibration(voltage, temperature); // calibration process by Serail CMD
  
}


//
// .     Add your variables 
//
// .             HERE
// .
//
//





void setup()

{

 Serial.begin(115200);
 pinMode(Erasing_button, INPUT);


 for (uint8_t t = 4; t > 0; t--) {
   Serial.println(t);
   delay(1000);
 }

 // Press and hold the button to erase all the credentials
 if (digitalRead(Erasing_button) == LOW)
 {
   Credentials.Erase_eeprom();

 }

 String auth_string = Credentials.EEPROM_Config();
 auth_string.toCharArray(auth_token, 33);

 if (Credentials.credentials_get())
 {

   Blynk.config(auth_token);
   connected_to_internet = 1;

 }
 else
 {
   Credentials.setupAP(esp_ssid, esp_pass);
   connected_to_internet = 0;
 }


 if (connected_to_internet)
 {

    ph.begin();
 sensors.begin();
 timer.setInterval(1000L, myTimerEvent);
 timer.setInterval(1000L, myTimerEvent2);
   // .  Write the setup part of your code
   //
   // .             HERE
   // .
   //
   //

 }



}



void loop()
{
 Credentials.server_loops();

 if (connected_to_internet)
 {


   //
   //
   // .  Write the loop part of your code
   //
   // .             HERE
   // .
   //
   //


   Blynk.run();
   timer.run();
 }
}

now i wanna go through example for making routine with dosing pump, i mean i will run this pump like 4 times a day and it will dose amount based in the ph reading … i do not understand how to make pump/relay run in certain time everyday … i read the time example but still can not get it for how to activate a relay at certain time every day

Look at the RTC widget examples in the Sketch Builder.

Pete.

1 Like