Final Project

Summary

My final project consists on manufacturing a residential low-cost water leak detector. This idea is presented taking into account the waste of this resource due to failure of sanitary installations, connection pipes or simply due to a poorly closed water pipe. Until now, the design includes a water tank that would continuously recirculated the water thanks to a small submersible electric pump. There will be a water pipe that simulates the main network from which a facility is supplied (like a house or a building) and another small parallel network that will work only in the early morning hours.

In addition, it is contemplated to use 2 solenoid valves that will allow the gates to be closed or opened in the time range of 2 to 3am. During this period of time, the first valve will close and the second will open so that the liquid enters through the parallel network and passes through a highly precise hall-type flow sensor. After this hour, the valves are reversed, opening the first and closing the second, so that the water flows in its normal network.

The idea of operating the flow sensor only from 2 to 3am is proposed because during that time there is no regular water consumption, and what the sensor senses will correspond to a liquid leak. In addition, operating the sensor for one hour prolongs its useful life. The cost of implementing this system in a home network is around $100. In the next weeks, I will detail the materials I will need, calculating the exact cost. Finally, I will work with Iot by sending the information of the sensor to the cloud and creating alarms indicating if there is a water leak in a residence.


Process

This is a gantt chart indicating all the steps of my final project.


The list of materials are the following:

- 1 12v-electropump (it must drive a low flow rate, this will simulate a water leak).

- 2 12v-solenoid valves.

- 3 MOSFET (metal–oxide–semiconductor field-effect transistor) min 1.5A. With this I will be able to regulate the water flow with PWM and the opening or closing pulse of the valves. I will also need tin filament for soldering, resistors, LED diode, header pins, cables.

- 1 hall type flow sensor.

- 1 LED screen to show the flow variable.

- 5 linear meters of 1/2" transparent hoses.

- 6 1/2" hose to device adapters (will be tested by printing them and checking for leaks at the connections).

- 1 Seeed Studio XIAO ESP32C3 IoT mini development board.

- 0.25 square meters of acrylic to make the tank.

-Copper clad laminates for the manufacture of electronic boards.

Continuing with the progress of the project, I have managed to design, manufacture and program a first version of the board by testing the components necessary for the final design. I already managed to obtain all the necessary components, and the final design of the board and its subsequent manufacturing and programming would be missing.


The processor I am using is a seeeduino ESP32-C3 that will allow me to use IoT to connect to a Wi-Fi signal and send my sensed variables to create alarms.


For this first stage, I have managed to make the 12v electric pump work and regulate the flow delivered, simulating a water leak. Likewise, I have managed to read the readings of a flow sensor and send them to the Arduino IDE serial monitor. The 12v are delivered by a separate source and it energizes a pin header so that the actuators are powered from there.

It is important to mention that the seeeduino ESP32-C3 works with 5v and does not deliver the 12v that these 3 components require, therefore I will be using a MOSFET for its control.


However, I will need to make another board where I can also control the opening and closing of the solenoid valves. For this, I will add 2 more MOSFETs to the analog pins of the seeeduino ESP32C-2. In this test, my board only has one MOSFET which I used to test the two solenoids as well as the electropump.

The video below shows the correct operation using the MOSFET of the current board. You have to be a little careful to hear the sound of the solenoid coil energizing


I will also add a voltage regulator from my supply that is 12 volts to 5 volts for the seeeduino, since it will not be connected to the computer when it is running and therefore will not be energized. This board does not has a 12v-5v regulator as I dont need it right now.


The flow sensor that I am using at the moment does not have the minimum sensitivity that I need, so I have purchased another much more sensitive sensor that allows me to measure 5 liters/hour or 0.08 liters/minute according to its datasheet. With this sensor, I will be able to take lower flow readings that simulate a water leak in a residence.






Mid may update

As of this date, I have a little more than 3 weeks to prepare my presentation of my final project. In line with the progress of the weekly assignments, I have managed to make good progress with my final project as it is shown below.

PCB design and manufacturing

The first thing I started to design and then manufacture was the electronic board. I had previously mentioned that I should make another board that includes 3 MOSFETs: one for the electric pump and the other two for the solenoid valves.

To manufacture this board I followed the same steps as the first board, which were documented in week 9.

First I start with the design of the PCB in the fusion 360 software using the electronic design module, starting with the schematic to design and enter all the components that I will need.

In addition to the MOSFETs, I have now incorporated a voltage regulator from 12v to 5v so that the board can be powered with my external 12v source and also power the seeeduino with 5v. My design also includes a schottky diode in line with the 5v so that when I upload the code to my seeeduino it does not overheat the voltage regulator, and also protects the seeeduino from burning out.

Next I arrange the tracks and see what is the most efficient way to join them.

For this I used a manual rout of 24mill.

Below is a short video of what a track looks like with that thickness mentioned.

After that, I design the outline of the board. I decided to use a drop shape for the outline.

Next, I used Flatcam software for generate the NC codes of the 3 files: tracks, outline and thru hole for the male seeeduino pins.

Then I use the Roland machine to manufacture the PCB from the 3 NC files delivered by flatcam software: tracks, outline and thru hole for the male seeeduino pins.

Next, I solder all the components SMD and male pins to the seeeduino.

While I was soldering, I performed continuity tests with a multimeter to ensure that there was continuity of current in the copper tracks and components.

Finally, this is the result along with the cables connected to the other components of the project



2d and 3d design

My final project includes designs in 2D as well as 3D. First, I started by laying out the entire base to hold the flow sensor, hoses, and solenoid valves.

For this design, I had to first measure the sensor connections to join them to the hose system, as well as the solenoid valves. work with 0.2mm less than the measurements of my devices so that they can be held and pressed into the support.

Also, I consider a system of spaces in the support so that the cables can be hidden.

It was not necessary to make the base robust or consider high filling because the weight it was going to support was not decisive.

This is the base ready to attach the sensor and the two solenoid valves.

Finally, in order to attach the electronic board, I had to make another design that can be attached to this one. This design includes using an OLED screen as well.

I also made the design of the base in the Fusion 360 software. Then, I used the Enroute software to generate the g-code and finished by cutting a piece in the drop shape. For this, I used the Multicam-3000 machine.

I used a 3mm of diameter mill for this operation.

The software delivers the G-code and I put that code into the multicam-3000 machine.

Thermoforming

I made the water tank with a thermoforming process of acrylic.

The process of thermoforming acrylic involves heating an acrylic sheet until it becomes malleable and then molding it into the desired shape. Here is a general overview of the process I made:

Material Preparation: An acrylic sheet of the 4mm of thickness is selected for the project.

Heating: The acrylic sheet is heated to its thermoforming temperature, typically between 150°C and 170°C (300°F and 340°F). This was made with a heat gun.

Molding: Once the sheet is hot and pliable, it is placed over and I gave it the shape I wanted.

Cooling: The molded sheet is allowed to cool maintain the desired shape. Cooling should be gradual to prevent warping or internal stresses in the material.

Final part

Finally, I made the programming code under the following logic: At 3:00 am the solenoid valve that is in the main pipe will close and will cause the fluid to go through the auxiliary pipe, opening the second solenoid valve that is below. This state will last 15 minutes, a proven time and sufficient to detect if there is a fluid, meaning that there is an abnormal consumption in that pipe. The idea of this is to prolong the life of the flow sensor.

I will also be working with the Blynk app connected via Wi-Fi to the seeeduino ESP32-C3. The sensor will be sending information to the app through the seeeduino, and also vice versa to be able to control the solenoid valves. I learned to work with this app in the week 14: interface and application programming.

The operating times will be programmed from the app Blynk. At first I thought of using an RTC (Real Time Clock) module which, as its name says, allows programming with a real-time clock. However, after studying the benefits of the seeeduino ESP32-C3's Wi-Fi connectivity and knowing the potential of the Blynk app, I decided to choose to work with this one.

The code was written in the Arduino IDE, and using the following libraries:

#include //This line includes the WiFi library for the ESP32. It provides the functions needed to connect the ESP32 to a WiFi network.

#include //This line includes the WiFiClient library, which allows the ESP32 to create a client that can connect to a specified internet IP address and port.

#include //This line includes the Blynk library for the ESP32. Blynk is the app that allows you to build mobile and web applications for the Internet of Things (IoT). This library simplifies the process of connecting the ESP32 to the Blynk app.

#include //This line includes the FlowSensor library, which is used to interface with flow sensors. These sensors measure the rate of fluid flow of water.

#include //This line includes the Wire library, which is used for I2C communication. I2C is a communication protocol that allows multiple devices (like sensors and displays) to communicate with the ESP32 using just two wires. I used because I have an OLED display for the status and information of the variables of my project.

#include //This line includes the Adafruit GFX library, which provides a common graphics library for various displays. It includes functions for drawing shapes, text, and images on the display.

#include //This line includes the Adafruit SSD1306 library, which is specifically for controlling SSD1306-based OLED displays. It provides functions to interface with the display.

Program code

#define BLYNK_TEMPLATE_ID "TMPL2L1JAtM3R" // Define the Blynk template ID

#define BLYNK_TEMPLATE_NAME "ESP32 FINAL PROJECT" // Define the Blynk template name

#define BLYNK_AUTH_TOKEN "vbwqd0jSgHx8SR12pEOhHkTO03UNKGyk" // Define the Blynk authentication token

#define BLYNK_PRINT Serial // Enable Serial output for debugging

#include // Include the WiFi library for ESP32

#include // Include the WiFi client library

#include // Include the Blynk library for ESP32

#include // Include the flow sensor library

#include // Include the I2C communication library

#include // Include the Adafruit GFX library for graphics

#include // Include the Adafruit SSD1306 library for OLED display

// My WiFi credentials

char ssid[] = "Depa703"; // SSID where I made my project

char pass[] = "borgono10000"; // Password of the wifi network

// Flow sensor setup

FlowSensor Sensor(150, 8); // Create a flow sensor object with specific parameters, Pulses is 150 as the manufacturer say, port 8 of Seeeduino ESP32-C3

unsigned long lastCheck = 0; // Variable to keep track of the last check time

const int solenoidPinUP = 4; // Pin connected to the UP solenoid valve

const int solenoidPinUNDER = 2; // Pin connected to the UNDER solenoid valve

const int mosfetPinPump = 3; // Pin connected to the MOSFET for the pump

// OLED display setup

#define SCREEN_WIDTH 128 // Define the width of the OLED display

#define SCREEN_HEIGHT 64 // Define the height of the OLED display

#define OLED_RESET -1 // Define the OLED reset pin (not used here)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Create an OLED display object

// System states

enum SystemState {

NORMAL_FLOW,

ALERT,

DISPLAY_FLOW_RATE,

DISPLAY_COST

};

SystemState currentState = NORMAL_FLOW; // Set the initial system state to NORMAL_FLOW

unsigned long stateStartTime = 0; // Variable to store the state start time

unsigned long stateDuration = 0; // Variable to store the state duration

// Variables to control the solenoids and the pump from Blynk

bool solenoidUPState = false; // Initial state of the UP solenoid valve

bool solenoidUNDERState = false; // Initial state of the UNDER solenoid valve

bool pumpState = true; // Turn on the pump by default

void count() {

Sensor.count(); // Increment the flow sensor counter

}

void setup() {

// Debug console

Serial.begin(115200); // Initialize the Serial communication at 115200 baud rate

// Connect to Blynk

Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); // Connect to Blynk using the authentication token and WiFi credentials

// Initialize the flow sensor Sensor.begin(count); // Initialize the flow sensor with the count function

// Set the pins as outputs and activate them

pinMode(solenoidPinUP, OUTPUT); // Set the UP solenoid pin as an output

pinMode(solenoidPinUNDER, OUTPUT); // Set the UNDER solenoid pin as an output

pinMode(mosfetPinPump, OUTPUT); // Set the MOSFET pump pin as an output

// Turn on the pump at the start

digitalWrite(mosfetPinPump, HIGH); // Turn on the pump by setting the pin HIGH

// Initialize the OLED display

if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Initialize the display with I2C address 0x3C

Serial.println(F("SSD1306 allocation failed")); // Print an error message if the display initialization fails

for (;;); // Enter an infinite loop if the initialization fails

}

display.display(); // Display the initial buffer

delay(2000); // Small delay for the display initialization

display.clearDisplay(); // Clear the display buffer

display.setTextSize(2); // Set the text size for the display

display.setTextColor(SSD1306_WHITE); // Set the text color for the display

Serial.println(F("OLED display initialized successfully")); // Print a success message for the display initialization

// Set the initial state

currentState = NORMAL_FLOW; // Set the initial state to NORMAL_FLOW

stateStartTime = millis(); // Record the current time as the state start time

stateDuration = 10000; // Set the duration for NORMAL_FLOW state to 10 seconds

// Ensure the solenoids and pump are in the correct state at the start

digitalWrite(solenoidPinUP, solenoidUPState); // Set the UP solenoid state

digitalWrite(solenoidPinUNDER, solenoidUNDERState); // Set the UNDER solenoid state

digitalWrite(mosfetPinPump, pumpState); // Set the pump state

}

// Blynk functions to handle the solenoid and pump switches BLYNK_WRITE(V0) {

solenoidUPState = param.asInt(); // Get the value from the Blynk app for the UP solenoid

digitalWrite(solenoidPinUP, solenoidUPState); // Set the UP solenoid state

Blynk.virtualWrite(V0, solenoidUPState); // Update the switch state in the Blynk dashboard

}

BLYNK_WRITE(V2) {

solenoidUNDERState = param.asInt(); // Get the value from the Blynk app for the UNDER solenoid

digitalWrite(solenoidPinUNDER, solenoidUNDERState); // Set the UNDER solenoid state

Blynk.virtualWrite(V2, solenoidUNDERState); // Update the switch state in the Blynk dashboard

}

BLYNK_WRITE(V3) {

pumpState = param.asInt(); // Get the value from the Blynk app for the pump

digitalWrite(mosfetPinPump, pumpState); // Set the pump state

Blynk.virtualWrite(V3, pumpState); // Update the switch state in the Blynk dashboard

}

void loop() {

Blynk.run(); // Run the Blynk main loop

unsigned long currentTime = millis(); // Get the current time

if (currentTime - stateStartTime >= stateDuration) {

// Change state if the duration has passed

switch (currentState) {

case NORMAL_FLOW:

currentState = ALERT; // Change to ALERT state

stateDuration = 2000; // Set duration for ALERT state

break;

case ALERT:

currentState = DISPLAY_FLOW_RATE; // Change to DISPLAY_FLOW_RATE state

stateDuration = 2000; // Set duration for DISPLAY_FLOW_RATE state

break;

case DISPLAY_FLOW_RATE:

currentState = DISPLAY_COST; // Change to DISPLAY_COST state

stateDuration = 2000; // Set duration for DISPLAY_COST state

break;

case DISPLAY_COST:

{

static int cycleCount = 0; // Static variable to count cycles

cycleCount++;

if (cycleCount >= 3) { // Repeat the cycle 3 times

cycleCount = 0; // Reset cycle count

currentState = NORMAL_FLOW; // Change back to NORMAL_FLOW state

stateDuration = 10000; // Set duration for NORMAL_FLOW state

} else {

currentState = ALERT; // Change back to ALERT state

stateDuration = 2000; // Set duration for ALERT state

}

break;

}

}

stateStartTime = currentTime; // Update the state start time

// Actions based on the current state

switch (currentState) {

case NORMAL_FLOW:

digitalWrite(solenoidPinUP, HIGH); // Open UP solenoid

digitalWrite(solenoidPinUNDER, LOW); // Close UNDER solenoid

display.clearDisplay(); // Clear the display

display.setCursor((SCREEN_WIDTH - 12 * 6) / 2, (SCREEN_HEIGHT - 16) / 2); // Center text

display.println("NORMAL"); // Display NORMAL

display.setCursor((SCREEN_WIDTH - 4 * 6) / 2, (SCREEN_HEIGHT - 16) / 2 + 16); // Center text

display.println("FLOW"); // Display FLOW

display.display(); // Update the display

Serial.println("State: NORMAL_FLOW"); // Print state to Serial

break;

case ALERT:

digitalWrite(solenoidPinUP, LOW); // Close UP solenoid

digitalWrite(solenoidPinUNDER, HIGH); // Open UNDER solenoid

display.clearDisplay(); // Clear the display

display.setCursor((SCREEN_WIDTH - 5 * 6) / 2, 0); // Center text

display.println("ALERT"); // Display ALERT

display.setCursor((SCREEN_WIDTH - 5 * 6) / 2, 24); // Center text

display.println("ALERT"); // Display ALERT

display.setCursor((SCREEN_WIDTH - 5 * 6) / 2, 48); // Center text

display.println("ALERT"); // Display ALERT

display.display(); // Update the display

Serial.println("State: ALERT"); // Print state to Serial

break;

case DISPLAY_FLOW_RATE:

{

Sensor.read(); // Read the flow sensor

float flowRate = Sensor.getFlowRate_m(); // Get the flow rate in L/min

Blynk.virtualWrite(V1, flowRate); // Update the flow rate in the Blynk app

display.clearDisplay(); // Clear the display

display.setCursor(0, 0); // Set cursor position

display.println("Flow Rate:"); // Display Flow Rate label

display.print(flowRate); // Display the flow rate

display.println(" L/min"); // Display units

display.display(); // Update the display

Serial.print("Flow Rate: "); // Print flow rate to Serial

Serial.print(flowRate); // Print the flow rate value

Serial.println(" L/min"); // Print units to Serial

break;

}

case DISPLAY_COST:

{

Sensor.read(); // Read the flow sensor

float flowRate = Sensor.getFlowRate_m(); // Get the flow rate in L/min

float monthlyCost = flowRate * 60 * 24 * 30 * 0.005 / 4; // Calculate the monthly cost

display.clearDisplay(); // Clear the display

display.setCursor(0, 0); // Set cursor position

display.println("Cost/Month"); // Display Cost/Month label

display.setCursor(0, 32); // Set cursor position

display.print("$"); // Display currency symbol

display.println(monthlyCost); // Display the monthly cost

display.display(); // Update the display

Serial.print("Cost/Month: $"); // Print monthly cost to Serial

Serial.println(monthlyCost); // Print the cost value to Serial

break;

}

}

}

// Update the state of the solenoids and pump in the Blynk dashboard

Blynk.virtualWrite(V0, digitalRead(solenoidPinUP)); // Update UP solenoid state

Blynk.virtualWrite(V2, digitalRead(solenoidPinUNDER)); // Update UNDER solenoid state

Blynk.virtualWrite(V3, digitalRead(mosfetPinPump)); // Update pump state

}

Wifi integration via Blynk platform

This is the final part of my project, and where with the information I receive through my seeeduino ESP32-C3 I can make decisions on the Blynk platform. Here you configure the alarms and the operating timing of the solenoid valves at the time they have to open or close.

First I had to create the working interface with my solenoids and sensor reading

Then I programed the alarms with the condition that if the sensor detects any water flow, it will send the alert to the user's cell phone.

These are the alerts that are reflected on the OLED screen, depending on each case.






Project Slide


Project video

Files:

Traces png
Outline png
Drills png
Drills for flatcam
Tracks for flatcam
Outline for flatcam
Drills NC code for Roland
Drills NC code for Roland
Outline NC code for Roland
Acrylic top cover stl
Base stl
Final project stl
Final project code IDE arduino