The "Smart Water Dispenser" is a system that dispenses a specific volume of water automatically. It works by measuring the water flow rate using a flow sensor and stopping the water flow once the desired volume is reached. Users can access the dispenser by using a smart card that is programmed with their personal information, such as their name, account balance, and water usage history.
Project Sketching
I designed a Smart Water Dispenser casing by Laser Cutter. I also designed an embedded system connected to a RFID Module,LCD Screen, Flow Sensor, Three input Buttons,Obstacle Sensor and Solenoid valve wich will used for measuring the water flow rate using a flow sensor and stopping the water flow once the desired volume is reached
4. What materials and components were used?
1. Microcontroller (ESP-wrom-32): Microcontroller which will be used to control the flow of water.
2. Water flow sensor (YF-S201): A flow sensor can be used to measure the amount of water flowing through the dispenser.
3. Smart card reader: A card reader can be used to read information from the smart card.
4. Solenoid valve: A solenoid valve can be used to control the flow of water.
5. LCD screen (20X4): An LCD screen can be used to display the amount of water dispensed and other information.
6. Power supply: A power supply can be used to power the microcontroller and other components.
7. Button: providing an input interface for users to select the desired dispensing option.
8. RFID Card:RFID card can be used to grant access or authorize specific users to dispense water and loading money
9. Voltage Regulator IC: A voltage regulator IC is used to regulate and stabilize the voltage (3V)level in a circuit.
10. MOSFET: It is a type of transistor that can control the flow of current in a circuit. MOSFETs are often used as switches
11. Button_Switch: Is a mechanical switch that is activated by pressing a button.
12. Resistors: They are used to control the amount of current or voltage in a circuit, to limit current flow, and to provide specific resistance values.
13. Capacitors: Capacitors store electrical energy in an electric field and release it when needed.
14. LED_SMD: LEDs are commonly used as visual indicators in electronic circuits
15. Connectors: Connectors are mechanical devices used to join or disconnect electrical circuits.
16. Buzzer: It is commonly used to generate audible alerts or notifications in electronic systems
17. Acrylic: Acrylic Will be used for the enclosure or casing of the dispenser.
18. Copper PCB: A Copper PCB (Printed Circuit Board) is a board made of insulating material with a layer of copper
19. Obstacle avoidance sensor: is designed to detect an obstacle or the difference in reflective services
5.Where did they come from?
I got all the electronic components and material used in my project from FabLabRwanda
6.How much did they cost?
Table Example
No
ITEM NAMES
SPECIFICATIONS
QUANTITY
UNIT PRICE(Rwf)
TOTAL PRICE(Rwf)
1.
Microcontroller
ESP-wrom-32
1
15000
15000
2.
Water flow sensor
YF-S201
1
8000
8000
3.
Solenoid valve
G1/2 AC 220V
1
13800
13800
4.
RFID Reader Module
13.56Mhz
1
7000
7000
5.
RFID Card
125Khz
3
1000
3000
6.
MOSFET
IRFZ44N
1
1000
1000
7.
Voltage Regulator
5V AMS1117
1
500
500
8.
LCD Display
20×4
1
11000
11000
9.
Copper PCB
single side 7x10cm
1
2000
2000
10.
Jumper Wires and others
Male,Female
1
6000
6000
11.
Acrylic
40x40x3
1
80000
80000
12.
Power Supply
HLK-5M12 12V 5W
1
10000
10000
13.
Water pipe
Small
3
1000
3000
14.
Capacitors
Small
3
1000
3000
15.
LED
Small
3
1000
3000
16.
Button_Switch
Small
3
1000
3000
17.
Buzzer
5V
1
500
500
18.
Voltage Regulator IC
3V
1
500
500
19.
Obstacle avoidance sensor
Infrared
1
2500
2500
TOTAL
N/A
29
154,800
162,800
7.What parts and systems were made?
My system was made by using the differents skills and knowldge we got from fabacademy
a. Computer-aided design
2D & 3D Design
b.Computer-controlled cutting
lasercutter
c. Embedded programming
ESP-wrom-32
d.Electronics design and production
CircuitDesign, PCB Milling and Soldaling compomnents
e.Input Devices
RFID system and Buttonsand Water flow sensor
f.Output Devices
LCD Display, and Solenoid valve, Buzzer
8.What processes were used?
a. Designing the Smart Water Dispenser case
By using skills I gain from Computer-aided design (2D and 3D Design) I designed the smart Water Dispenser case which will hold all system. the below Image shows the process we used.
This is Back side
This is Right side
This is Left side
This is Button side
This is Top side
This is Front side
This is Water Dispenser case after assembling all parts
b. Cutting with lasercutter and Engraving Machine
By using skills I gain from Computer-controlled cutting (Laser Cutter) I Cutted the smart Water Dispenser case which will hold all system. the below Image shows the process we used.
This is Water Dispenser case after Cutting on lasercutter
After assembling all parts
c. Designing and 3D Printing the RFID Card Holder and Obstacle avoidance sensor
The following Image shows the RFID Card Holder and Obstacle avoidance sensor
The following Image shows the RFID Card Holder and Obstacle avoidance sensor printed by 3D Printer
The following images shows after inserting the RFID Card Holder and Obstacle avoidance sensor
d. Circuit and PCB Design
By using skills I gain from Electronics design and production (CircuitDesign, PCB Milling and Soldaling compomnents) I designed the smart Water Dispenser Board which will hold all compomnents of the system. the below Image shows the process we used.
I started by designing, Milling, soldering PCB
Here is Schematic
Here is PCB Design
Here is PCB Design in 3D
Here is we started generate G-Codes for Milling with Roland SRM 20
Here is PCB after Milling
Here I started soldiring compomnents on PCB
Here after soldiring compomnents
Inside of the case
Outside of the Case
e. Embedded programming,Input Devices,Output Devices Embedded Networking and Communications and Interface Application Programming
By using skills I gain from Embedded programming,Input Devices,Output Devices Embedded Networking and Communications and Interface Application Programming (2D and 3D Design) I designed the smart Water Dispenser case which will hold all system. the below Image shows the process we used.
We started by designing Flow Chat Diagram
The following Image shows when I started testing and debug my system compomnents
The Microcontroller now can read, the Obstacle avoidance sensor, RFID Card and check the balance
The following Images shows when we start assembling all parts of Smart Water Despenser (Case and Electronics )
#include
#include
#include
#include
#define RST_PIN 15 // Configurable, see typical pin layout above
#define SS_PIN 5 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
MFRC522::MIFARE_Key key;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
uint32_t CardBalance = 0;
uint32_t Cost=1;
uint32_t total_cost=0;
String Card="";
uint32_t consumed_volume=0;
uint32_t Card_Balance=0;
int cardsensor= 17;
int progress=0;
int valve=13;
const unsigned long period = 1000;
int incrementbutton=2;
int decrementbutton=4;
int confirmbutton=14;
int button_state1=0;
int button_state2=0;
int button_state3=0;
int cardstate=0;
float volume=0.0;
uint32_t unit_cost=1;
#define FLOWSENSOR 27
FlowMeter Meter = FlowMeter(27);
/**
* Initialize.
*/
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
lcd.init();
lcd.backlight();
mfrc522.PCD_Init(); // Init MFRC522 card
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
pinMode(incrementbutton,INPUT_PULLUP);
pinMode(decrementbutton,INPUT_PULLUP);
pinMode(confirmbutton,INPUT_PULLUP);
pinMode(valve,OUTPUT);
Serial.println(F("insert your card"));
pinMode(cardsensor, INPUT);
attachInterrupt(digitalPinToInterrupt(cardsensor),cardpresent,CHANGE); // function for creating external interrupts at pin2 on Rising (LOW to HIGH vice versa)
request_Card();
}
/**
* Main loop.
*/
void loop() {
Meter.tick(period);
while(cardstate==0)
{
mfrc522.PCD_StopCrypto1();
Card="";
total_cost=0;
Meter.setTotalVolume(0.0f);
CardBalance=0;
cardstate = 4;
detachInterrupt(FLOWSENSOR);
}
while(cardstate==1)
{
Serial.print(" Card present = ");
checkcardinfo();
Card_info_screen();
delay(3000);
if(CardBalance>=unit_cost){
Serial.print(" Card Stored ");
Serial.print(" balance= ");
Serial.print(CardBalance);
progress=1;
while(progress==1){
confirm_Volume();
}
total_cost= unit_cost * volume;
if(total_cost < CardBalance){
charge();
attachInterrupt(FLOWSENSOR, MeterISR, RISING);
open_valve();
lcd.clear();
cardstate=2;
}
else {
close_valve();
recharge_card_screen();
}
} else {
close_valve();
recharge_card_screen();
}
}
while(cardstate==2)
{
if(consumed_volume>=total_cost){
close_valve();
}
else{
fetching();
}
}
}
void screen(){
lcd.setCursor(3,0);
lcd.print("CARD: " +String(Card));
lcd.setCursor(1,1);
lcd.print("Balance: " +String(CardBalance));
Serial.println ("screeen printint"+String(Card)+"Balance: " +String(CardBalance));
}
void MeterISR() {
// let our flow meter count the pulses
Meter.count();
consumed_volume = (Meter.getTotalVolume())*100;
}
void charge(){
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent())
return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;
byte sector = 1;
byte valueBlockB = 6;
byte trailerBlock = 7;
MFRC522::StatusCode status;
byte buffer[18];
byte size = sizeof(buffer);
int32_t value;
// Authenticate using key A
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
byte trailerBuffer[] = {
255, 255, 255, 255, 255, 255, // Keep default key A
0, 0, 0,
0,
255, 255, 255, 255, 255, 255}; // Keep default key B
mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);
status = mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Check if it matches the desired access pattern already;
// because if it does, we don't need to write it again...
if ( buffer[6] != trailerBuffer[6]
|| buffer[7] != trailerBuffer[7]
|| buffer[8] != trailerBuffer[8]) {
// They don't match (yet), so write it to the PICC
Serial.println(F("Writing new sector trailer..."));
status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
}
// Authenticate using key B
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Decrement(valueBlockB, total_cost);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Decrement() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Transfer(valueBlockB);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Transfer() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Show the new value of valueBlockB
status = mfrc522.MIFARE_GetValue(valueBlockB, &value);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("mifare_GetValue() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
Serial.println();
mfrc522.PCD_StopCrypto1();
}
////////////////////////////////////////////////////////////////////////////////////
/* checking new card information and storing them */
///////////////////////////////////////////////////////////////////////////////////////
void checkcardinfo(){
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent())
return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;
// Show some details of the PICC (that is: the tag/card)
Serial.print(F("Card UID:"));
// dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
Card="";
for (byte i = 0; i < mfrc522.uid.size; i++)
{
Card+=String(mfrc522.uid.uidByte[i],HEX);
Card.toUpperCase();
}
Serial.println ("new card = "+String(Card));
screen();
// In this sample we use the second sector,
// that is: sector #1, covering block #4 up to and including block #7
byte sector = 1;
byte valueBlockB = 6;
byte trailerBlock = 7;
MFRC522::StatusCode status;
byte buffer[18];
byte size = sizeof(buffer);
int32_t value;
// Authenticate using key A
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
byte trailerBuffer[] = {
255, 255, 255, 255, 255, 255, // Keep default key A
0, 0, 0,
0,
255, 255, 255, 255, 255, 255}; // Keep default key B
mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);
status = mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Check if it matches the desired access pattern already;
// because if it does, we don't need to write it again...
if ( buffer[6] != trailerBuffer[6]
|| buffer[7] != trailerBuffer[7]
|| buffer[8] != trailerBuffer[8]) {
// They don't match (yet), so write it to the PICC
Serial.println(F("Writing new sector trailer..."));
status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
}
// Authenticate using key B
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Show the new value of valueBlockB
status = mfrc522.MIFARE_GetValue(valueBlockB, &value);
CardBalance=value;
if (status != MFRC522::STATUS_OK) {
Serial.print(F("mifare_GetValue() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
Serial.println();
mfrc522.PCD_StopCrypto1();
}
////////////////////////////////////////////////////////////////////////////////////
/* checking if card is present or absent */
///////////////////////////////////////////////////////////////////////////////////////
void cardpresent()
{
if(digitalRead(cardsensor) == LOW){
cardstate =1;
}
else{
close_valve();
cardstate =0;
}
}
////////////////////////////////////////////////////////////////////////////////////
/* Confirming volume */
///////////////////////////////////////////////////////////////////////////////////////
void confirm_Volume()
{
volume_screen();
if((digitalRead(incrementbutton)== LOW) && button_state1==0){
Serial.println("incrementbutton pressed");
volume=volume+1;
button_state1=1;
}
else if(digitalRead(incrementbutton)== HIGH){
button_state1=0;
}
else if((digitalRead(decrementbutton)== LOW) && button_state2==0 && volume >=0.0 ){
Serial.println("decrementbutton pressed");
volume=volume-1;
button_state2=1;
}
else if(digitalRead(decrementbutton)== HIGH){
button_state2=0;
}
if(digitalRead(confirmbutton)== LOW)
{
progress=0;
}
}
void request_Card()
{
lcd.clear();
lcd.setCursor(3,1);
lcd.print("insert your");
lcd.setCursor(7,2);
lcd.print("CARD");
}
void Card_info_screen()
{
lcd.clear();
lcd.setCursor(3,1);
lcd.print("CARD= " +String(Card));
lcd.setCursor(1,2);
lcd.print("Balance= "+ String(CardBalance));
}
void volume_screen()
{
lcd.setCursor(3,1);
lcd.print("CARD= " +String(Card));
lcd.setCursor(1,2);
lcd.print("Requsting: "+ String(volume)+"L");
}
void recharge_card_screen()
{
lcd.clear();
lcd.setCursor(3,1);
lcd.print("INSUFIENT balance");
lcd.setCursor(1,2);
lcd.print("please Recharge");
}
void fetching()
{
lcd.setCursor(2,0);
lcd.print("CARD: "+String(Card));
lcd.setCursor(1,1);
lcd.print("Requested: "+ String(volume)+"L");
lcd.print("Volume: "+ String(consumed_volume)+"L");
lcd.setCursor(2,2);
lcd.print("balance: "+ String(CardBalance)+ "Rwf");
}
void button_screen()
{
lcd.clear();
lcd.setCursor(3,1);
lcd.print("volume= "+ String(volume));
}
void open_valve(){
digitalWrite(valve, HIGH);
}
void close_valve(){
digitalWrite(valve, LOW);
}
9.What questions were answered?
This project Smart Water Dispenser will applied in different sector and plays the important role of providing clean water on affordable cost.
Applications of Smart Water Dispenser:
1. Offices and Workplaces: This Smart Water dispenser can be used in office settings to promote hydration among employees, track water consumption, and encourage sustainable practices.
2. Educational Institutions: Schools, colleges, and universities can install smart water dispensers to provide clean water to students and faculty while raising awareness about water conservation.
3. Public Spaces: Smart water dispensers can be placed in public parks, shopping malls, airports, and other communal areas to offer convenient access to clean drinking water for the general public on affordable cost
4. Healthcare Facilities: Smart water dispensers can be installed in hospitals, clinics, and nursing homes to ensure a clean and safe water supply for patients, staff, and visitors.
10.How the system works (Smart Water Dispenser)
To use the system you follow the following steps:
1st. Power on the system :
When you turn on the system with 12V and by using Voltage Regulators 5v and 3.3V for powering the least of parts of the system. When we start the system the LCD will display a message Insert your CARD2nd. Insert the card and the system checks card balance :
If the balance is not sufficient the system display a message Insufficiant Balance please recharge
Once the balance is greater or equal to 100 (the cost of one litter of water) the system diplay Requesting Volume of water in(Volume)
By using 3 buttons you will set the volume of water you will request, (Button for increasing volume, Button for dencreasing and other for confirming the volume you want to request)
After confirm 4 Litters of water we will display the below message, the system will go to rechack if the available balance will be equivalent to requested volume.
Final results of how the system works
The video shows how the system works
If you want to learn about my Designs, kindly click here