Hi,
I believe this title is somewhat overused in the community, but I have read the topics and none of them seems to solve the problem with my project.
—Project Details (I guess)—
I am working on a water monitoring device connected to the Blynk server so that I can view the water quality values on my phone anywhere. My hardware setup is an Arduino Uno wired to an ESP-01, like a WiFi shield (I used external 3.3V regulator AMS1117 connected to Vin of Arduino Uno to power it). I am viewing the data on my Android phone with version 5.1. My Blynk Library version is 0.6.1.
The sensor I am using are DS18B20 Temperature Sensor, pH sensor, TDS sensor, Turbidity sensor and a Dissolved Oxygen Sensor (haven’t bought the sensor yet thanks to its high cost but the code is in the sketch)
I also wired a speaker so that it can produce a siren or something when some sensor values exceed their thresholds.
—The problem—
The app works until I uncomment the line where it will send the dissolved oxygen values to the server. The Blynk App on my phone says that the device disconnected. Shortly, the app says the device is connected and the process repeats.
This is the code I am using:
#define BLYNK_MAX_SENDBYTES 256 // increase number of bytes that can be sent for email and notifications
#define BLYNK_PRINT Serial // uncomment it to view connection logs, comment it to disable print and save space
//Importing necessary libraries
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>
//defining IO pins and other stuff
#define ESP8266_BAUD 9600 // Baud rate to communicate with ESP-01
#define tempSen 4 // DS18B20 Temperature Sensor
#define spkPin 6 // Speaker
#define relayPin 7 // Relay that controls an oxygen air pump
#define loudAlarm 8 // ne555 beeping circuit
#define pHSen A0 // pH Sensor
#define tdsEcSen A1 // TDS EC sensor
#define turbiSen A2 // Turbidity sensor
#define doSen A3 // Dissolved oxygen sensor
#define vRef 5000 //VREF (mv)
#define adcRes 1024 //ADC Resolution
#define twoPointCalib 0 //Single-point calibration Mode=0 OR Two-point calibration Mode=1
//Single point calibration needs to be filled CAL1_V and CAL1_T
#define cal1V (131) //mv
#define cal1T (25) //Celsius
//Two-point calibration needs to be filled CAL2_V and CAL2_T
//CAL1 High temperature point, CAL2 Low temperature point
#define cal2V (1300) //mv
#define cal2T (15) //Celsius
//variables
char auth[] = "insertauth"; // auth token
char ssid[] = "insertssid"; // WiFi SSID.
char pass[] = "insertpass"; // WiFi password. Set password to "" for open networks.
const unsigned long period = 60000;
unsigned long int avgValue; // Store the average value of the sensor feedback
unsigned long tempStartTime;
unsigned long pHStartTime;
unsigned int tds = 0; // total dissolved solids value
int tempTrig = 0;
int pHTrig = 0;
int senValue = 0; // variable to store the value coming from the sensor
float ad7 = 366.0; // change this value to the one on serial monitor when in pH7 buffer
float ad4 = 144.0; // change this value to the one on serial monitor when in pH4 buffer
float temp = 0;
float volt = 0;
float ntu;
float ec = 0;
float pH;
float ecCalibration = 1;
uint16_t adcVoltage;
float dO = 0;
const uint16_t doTable[41] = {
14460, 14220, 13820, 13440, 13090, 12740, 12420, 12110, 11810, 11530,
11260, 11010, 10770, 10530, 10300, 10080, 9860, 9660, 9460, 9270,
9080, 8900, 8730, 8570, 8410, 8250, 8110, 7960, 7820, 7690,
7560, 7430, 7300, 7180, 7070, 6950, 6840, 6730, 6630, 6530, 6410
};
int16_t readDO(uint32_t voltageMv, uint8_t temperatureC) {
#if twoPointCalib == 00
uint16_t vSaturation = (uint32_t)cal1V + (uint32_t)35 * temperatureC - (uint32_t)cal1T * 35;
return (voltageMv * doTable[temperatureC] / vSaturation);
#else
uint16_t vSaturation = (int16_t)((int8_t)temperatureC - cal2T) * ((uint16_t)cal1V - cal2V) / ((uint8_t)cal1T - cal2T) + cal2V;
return (voltageMv * doTable[temperatureC] / vSaturation);
#endif
}
float roundToDp( float inValue, int decimalPlace ) {
float multiplier = powf( 10.0f, decimalPlace );
inValue = roundf( inValue * multiplier ) / multiplier;
return inValue;
}
//objects
SoftwareSerial EspSerial(2, 3); // RX, TX
ESP8266 wifi(&EspSerial);
BlynkTimer timer;
OneWire oneWire(tempSen);
DallasTemperature tempObj(&oneWire);
//obtain temperature
void getTemp() {
tempObj.requestTemperatures();
temp = tempObj.getTempCByIndex(0);
Blynk.virtualWrite(V0, temp);
}
//functions
//obtain total dissolved solids and electrical conductivity
void getTdsEc() {
float rawEc = analogRead(tdsEcSen) * (vRef / 1000) / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
float tempCoefficient = 1.0 + 0.02 * (temp - 25.0); // temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
ec = (rawEc / tempCoefficient) * ecCalibration; // temperature and calibration compensation
tds = (133.42 * pow(ec, 3) - 255.86 * ec * ec + 857.39 * ec) * 0.5; //convert voltage value to tds value (not needed for now)
Blynk.virtualWrite(V1, ec);
}
//obtain water turbidity
void getTurbidity() {
for (int i = 0; i < 800; i++) {
volt += ((float)analogRead(turbiSen) / 1023) * 5;
}
volt /= 800;
volt = roundToDp(volt, 2);
if (volt < 2.5) {
ntu = 3000;
} else {
ntu = -1120.4 * sq(volt) + 5742.3 * volt - 4353.8;
}
Blynk.virtualWrite(V2, ntu);
}
//obtain water pH
void getpH() {
int currValue = 0;
for (int i = 0; i < 10; i++)
{
currValue += analogRead(pHSen);
delay(100);
}
senValue = (currValue / 10);
//Serial.println(senValue); //uncomment this to do calibration
float m = (-3.0 / (ad4 - ad7));
//Serial.println(m);
float c = 7 - (m * ad7);
//Serial.println(c);
float a = ((m * senValue) + c);
//Serial.print("PH = "); //uncomment this to do calibration
//Serial.println(a); //uncomment this to do calibration
pH = a;
delay(500);
Blynk.virtualWrite(V3, pH);
}
//obtain dissolved oxygen in water
void getDO() {
adcVoltage = uint32_t(vRef) * analogRead(doSen) / adcRes;
dO = readDO(adcVoltage, uint8_t(temp));
Blynk.virtualWrite(V4, dO); // <-------- the connection to Blynk app keeps restarting when I uncomment this line
}
//alert if temperature exceeds a certain limit
void tempAlarm() {
unsigned long tempTime = millis();
if (temp > 30) {
if (tempTime - tempStartTime >= 60000 && tempTrig == 1) {
Blynk.notify(String("TempNow: ") + String(temp) + String(" C"));
tempStartTime = tempTime;
}
else if (tempTrig == 0) {
Blynk.email("email@example.com", "Temp Alert", String("TempRec: ") + temp + String("°C"));
//PORTD &= ~(1 << PORTD7);
tempTrig = 1;
}
}
else {
if (tempTrig == 1) {
//PORTD |= (1 << PORTD7);
tempTrig = 0;
}
}
}
//alert if pH exceeds a certain limit
void pHAlarm() {
unsigned long pHTime = millis();
if (pH > 7 || pH < 6) {
if (pHTime - pHStartTime >= 30000 && pHTrig == 1) {
Blynk.notify(String("pHNow: ") + String(pH));
pHStartTime = pHTime;
}
else if (pHTrig == 0) {
Blynk.email("email@example.com", "pH Alert", String("pHRec: ") + pH);
pHTrig = 1;
}
}
else {
if (pHTrig == 1) {
pHTrig = 0;
}
}
}
void doAlarm() {
//will implement later
}
//produce siren
void alarmSound() {
unsigned long alarmTime = millis();
if (tempTrig == 1 || pHTrig == 1) {
tone(spkPin, 880);
}
else {
noTone(spkPin);
}
}
void setup() {
//obtaining reference time to replace delay() function
tempStartTime = millis();
pHStartTime = millis();
Serial.begin(9600); // begin serial monitor, 9600 is recommended for ESP8266 shield setup
delay(10);
EspSerial.begin(ESP8266_BAUD); // Set ESP8266 baud rate
delay(10);
Blynk.begin(auth, wifi, ssid, pass); // start Blynk
tempObj.begin(); // start DS18B20
DDRD |= (1 << DDD7); // set digital pin 7 as OUTPUT (relayPin)
PORTD |= (1 << PORTD7); // set digital pin 7 OUTPUT as HIGH (this will turn off relay)
//BlynkTimer part to send data to Blynk app within fixed periods (if the app disconnects frequently, try tuning the timeout or interval)
timer.setTimeout(100, []() {
timer.setInterval(5000L, getTemp);
});
timer.setTimeout(200, []() {
timer.setInterval(5000L, getTdsEc);
});
timer.setTimeout(300, []() {
timer.setInterval(5000L, getTurbidity);
});
timer.setTimeout(400, []() {
timer.setInterval(5000L, getpH);
});
timer.setTimeout(500, []() {
timer.setInterval(10000L, getDO);
});
timer.setTimeout(600, []() {
timer.setInterval(6000L, tempAlarm);
});
timer.setTimeout(700, []() {
timer.setInterval(6000L, pHAlarm);
});
timer.setTimeout(800, []() {
timer.setInterval(10000L, alarmSound);
});
//intro (tells user that the device is up and running)
for (int i = 0; i < 3; i++) {
tone(spkPin, 1046.50, 10);
delay(100);
}
}
void loop() {
// ONLY THESE 2 LINES OF CODE CAN BE HERE, REFRAIN FROM ADDING MORE CODE IN LOOP TO PREVENT DISCONNECTION ISSUES
Blynk.run();
timer.run();
}
This is the Serial output (that is all it shows, no more prints even after an hour):
I am not sure if this has something to do with the dissolved oxygen code (because I tried replacing the value of dO variable in Blynk.virtualWrite(V4, dO);
with a fixed value and the Blynk app can respond correctly.)
I also stumbled across the pinout diagram of ESP32 and realized that it has a lot of analog pins, unlike standalone ESP8266 (because I may add more analog Sensors in the future). I may have to switch to ESP32 but I have already wasted 2 weeks soldering the circuit on a prototype board (thanks to breadboard’s loose connections that messed up my ESP-01) and finding the perfect wire management (which is still not pretty but not too bad).
Is this how far I can go with Arduino with ESP8266 shield setup or I just don’t know how to code IoT projects properly?
Many thanks.