//#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL2cb74LMBb"
#define BLYNK_TEMPLATE_NAME "Volume do Sabao"
#define BLYNK_AUTH_TOKEN "1vneYb2R9eMRjDmY2_RPLPcbQiFJVa43"
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
//Set Water Level Distance in CM
int emptyTankDistance = 70 ; //Distance when tank is empty
int fullTankDistance = 30 ; //Distance when tank is full
int emptyTankDistance_2 = 70 ; //Distance when tank is empty
int fullTankDistance_2 = 30 ; //Distance when tank is full
//Set trigger value in percentage
int triggerPer = 10 ; //alarm will start when water level drop below triggerPer
int triggerPer_2 = 10 ; //alarm will start when water level drop below triggerPer
//definicao do pino do sensor e de interrupcao
const int INTERRUPCAO_SENSOR = 0; //interrupt = 0 equivale ao pino digital 2
const int PINO_SENSOR = 4;
unsigned long contador = 0; //definicao da variavel de contagem de voltas
const float FATOR_CALIBRACAO = 4.5; //definicao do fator de calibracao para conversao do valor lido
//definicao das variaveis de fluxo e volume
float fluxo = 0;
float volume = 0;
float volume_total = 0;
//definicao da variavel de intervalo de tempo
unsigned long tempo_antes = 0;
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <AceButton.h>
using namespace ace_button;
// Define connections to sensor
#define TRIGPIN 27 //D27
#define ECHOPIN 26 //D26
#define TRIGPIN_2 33 //D33
#define ECHOPIN_2 25 //D25
#define wifiLed 2 //D2
#define ButtonPin1 12 //D12
#define BuzzerPin 13 //D13
#define GreenLed 14 //D14
#define Relay1 23 //D23
#define Relay2 19 //D19
#define Relay3 18 //D18
#define Relay4 5 //D5
BLYNK_WRITE(V4){
int RELE = param.asInt();
// Liga e desliga o rele
if(RELE == 1){
digitalWrite(Relay1, HIGH);
delay(3000);
digitalWrite(Relay1, LOW);
}
}
BLYNK_WRITE(V5){
int RELE = param.asInt();
// Liga e desliga o rele
if(RELE == 1){
digitalWrite(Relay2, HIGH);
delay(3000);
digitalWrite(Relay2, LOW);
}
}
BLYNK_WRITE(V6){
int RELE = param.asInt();
// Liga e desliga o rele
if(RELE == 1){
digitalWrite(Relay3, HIGH);
delay(3000);
digitalWrite(Relay3, LOW);
}
}
BLYNK_WRITE(V7){
int RELE = param.asInt();
// Liga e desliga o rele
if(RELE == 1){
digitalWrite(Relay4, HIGH);
delay(3000);
digitalWrite(Relay4, LOW);
}
}
//Change the virtual pins according the rooms
#define VPIN_BUTTON_1 V1
#define VPIN_BUTTON_2 V2
#define VPIN_BUTTON_3 V3
#define VPIN_BUTTON_4 V4
#define VPIN_BUTTON_5 V5
#define VPIN_BUTTON_6 V6
#define VPIN_BUTTON_7 V7
#define VPIN_BUTTON_8 V8
#define VPIN_BUTTON_9 V9
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
float duration;
float duration_2;
float distance;
float distance_2;
int waterLevelPer;
int waterLevelPer_2;
bool toggleBuzzer = HIGH; //Define to remember the toggle state
char auth[] = BLYNK_AUTH_TOKEN;
ButtonConfig config1;
AceButton button1(&config1);
void handleEvent1(AceButton*, uint8_t, uint8_t);
BlynkTimer timer;
void checkBlynkStatus() { // called every 3 seconds by SimpleTimer
bool isconnected = Blynk.connected();
if (isconnected == false) {
//Serial.println("Blynk Not Connected");
digitalWrite(wifiLed, LOW);
}
if (isconnected == true) {
digitalWrite(wifiLed, HIGH);
//Serial.println("Blynk Connected");
}
}
BLYNK_CONNECTED() {
Blynk.syncVirtual(VPIN_BUTTON_1);
Blynk.syncVirtual(VPIN_BUTTON_2);
Blynk.syncVirtual(VPIN_BUTTON_3);
Blynk.syncVirtual(VPIN_BUTTON_4);
Blynk.syncVirtual(VPIN_BUTTON_5);
Blynk.syncVirtual(VPIN_BUTTON_6);
Blynk.syncVirtual(VPIN_BUTTON_7);
Blynk.syncVirtual(VPIN_BUTTON_8);
Blynk.syncVirtual(VPIN_BUTTON_9);
}
void displayData(int value){
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0,0);
display.print("Sabao: ");
display.setTextSize(4);
display.setCursor(30,32);
display.print(value);
display.print("%");
display.display();
delay(500);
}
void oledData (int valor){
oled.clearDisplay();
oled.setTextSize(2);
oled.setCursor(0,0);
oled.print("Amaciante: ");
oled.setTextSize(4);
oled.setCursor(30,32);
oled.print(valor);
oled.print("%");
oled.display();
delay(500);
}
void measureDistance(){
// Set the trigger pin LOW for 2uS
digitalWrite(TRIGPIN, LOW);
delayMicroseconds(2);
// Set the trigger pin HIGH for 20us to send pulse
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(20);
// Return the trigger pin to LOW
digitalWrite(TRIGPIN, LOW);
// Measure the width of the incoming pulse
duration = pulseIn(ECHOPIN, HIGH);
// Determine distance from duration
// Use 343 metres per second as speed of sound
// Divide by 1000 as we want millimeters
distance = ((duration / 2) * 0.343)/10;
if (distance > (fullTankDistance - 10) && distance < emptyTankDistance ){
waterLevelPer = map((int)distance ,emptyTankDistance, fullTankDistance, 0, 100);
displayData(waterLevelPer);
Blynk.virtualWrite(VPIN_BUTTON_1, waterLevelPer);
Blynk.virtualWrite(VPIN_BUTTON_2, (String(distance) + " cm"));
Blynk.virtualWrite(VPIN_BUTTON_3, (String("Clicar somente uma vez em cada maquina.")));
if (waterLevelPer < triggerPer){
digitalWrite(GreenLed, HIGH);
if (toggleBuzzer == HIGH){
digitalWrite(BuzzerPin, HIGH);
}
}
if (distance < fullTankDistance){
digitalWrite(GreenLed, LOW);
if (toggleBuzzer == HIGH){
digitalWrite(BuzzerPin, HIGH);
}
}
if (distance > (fullTankDistance + 5) && waterLevelPer > (triggerPer + 5)){
toggleBuzzer = HIGH;
digitalWrite(BuzzerPin, LOW);
}
}
// Delay before repeating measurement
//delay(100);
}
void measureDistance_2(){
// Set the trigger pin LOW for 2uS
digitalWrite(TRIGPIN_2, LOW);
delayMicroseconds(2);
// Set the trigger pin HIGH for 20us to send pulse
digitalWrite(TRIGPIN_2, HIGH);
delayMicroseconds(20);
// Return the trigger pin to LOW
digitalWrite(TRIGPIN_2, LOW);
// Measure the width of the incoming pulse
duration_2 = pulseIn(ECHOPIN_2, HIGH);
// Determine distance from duration
// Use 343 metres per second as speed of sound
// Divide by 1000 as we want millimeters
distance_2 = ((duration_2 / 2) * 0.343)/10;
if (distance_2 > (fullTankDistance_2 - 10) && distance_2 < emptyTankDistance_2 ){
waterLevelPer_2 = map((int)distance_2 ,emptyTankDistance_2 , fullTankDistance_2, 0, 100);
oledData(waterLevelPer_2);
Blynk.virtualWrite(VPIN_BUTTON_8, waterLevelPer_2);
Blynk.virtualWrite(VPIN_BUTTON_9, (String(distance_2) + " cm"));
// Print result to serial monitor distance 1
Serial.println(millis());
Serial.print("Distance: ");
Serial.print(distance);
Serial.print(" cm \tDistance 2: ");
Serial.print(distance_2);
Serial.print(" cm");
if (waterLevelPer_2 < triggerPer_2){
digitalWrite(GreenLed, HIGH);
if (toggleBuzzer == HIGH){
digitalWrite(BuzzerPin, HIGH);
}
}
if (distance_2 < fullTankDistance_2 ){
digitalWrite(GreenLed, LOW);
if (toggleBuzzer == HIGH){
digitalWrite(BuzzerPin, HIGH);
}
}
if (distance_2 > (fullTankDistance_2 + 5) && waterLevelPer_2 > (triggerPer_2 + 5)){
toggleBuzzer = HIGH;
digitalWrite(BuzzerPin, LOW);
}
}
// Delay before repeating measurement
}
void Contagem_de_Pulsos(){//executa a contagem de pulsos uma vez por segundo
if((millis() - tempo_antes) >= 1000){
detachInterrupt(digitalPinToInterrupt(INTERRUPCAO_SENSOR));//desabilita a interrupcao para realizar a conversao do valor de pulsos
fluxo = ( ((millis() - tempo_antes)/1000) * contador) / FATOR_CALIBRACAO;//conversao do valor de pulsos para L/min
volume = fluxo / 60; //calculo do volume em L passado pelo sensor
volume_total += volume; //armazenamento do volume
//exibicao do valor de fluxo
Serial.print("\nFluxo de: ");
Serial.print(fluxo);
Serial.print(" L/min");
//exibicao do valor de volume
Serial.print("\t Volume total gasto: ");
Serial.print(volume_total);
Serial.println(" L\n");
contador = 0; //reinicializacao do contador de pulsos
tempo_antes = millis(); //atualizacao da variavel tempo_antes
}
}
void setup() {
// Set up serial monitor
Serial.begin(115200);
// Set pinmodes for sensor connections
pinMode(ECHOPIN, INPUT);
pinMode(TRIGPIN, OUTPUT);
pinMode(ECHOPIN_2, INPUT);
pinMode(TRIGPIN_2, OUTPUT);
pinMode(wifiLed, OUTPUT);
pinMode(GreenLed, OUTPUT);
pinMode(BuzzerPin, OUTPUT);
pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
pinMode(Relay4, OUTPUT);
pinMode(ButtonPin1, INPUT_PULLUP);
pinMode(PINO_SENSOR, INPUT_PULLUP);
// Configurando a interrupção externa no pino do botão
attachInterrupt(digitalPinToInterrupt(PINO_SENSOR), contador_pulso, FALLING);
digitalWrite(wifiLed, LOW);
digitalWrite(GreenLed, LOW);
digitalWrite(BuzzerPin, LOW);
config1.setEventHandler(button1Handler);
button1.init(ButtonPin1);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(500);
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
if(!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(500);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.clearDisplay();
WiFi.begin(ssid, pass);
timer.setInterval(2000L, checkBlynkStatus); // check if Blynk server is connected every 2 seconds
Blynk.config(auth);
delay(1000);
}
void loop() {
Blynk.run();//start blynk conection
timer.run(); // Initiates SimpleTimer
measureDistance();
measureDistance_2();
Contagem_de_Pulsos();
button1.check();
}
void contador_pulso() { //funcao chamada pela interrupcao para contagem de pulsos
contador++;
}
void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT1");
switch (eventType) {
case AceButton::kEventReleased:
//Serial.println("kEventReleased");
digitalWrite(BuzzerPin, LOW);
toggleBuzzer = LOW;
break;
}
}