Smart Self-Cleaning Urinal System Using Photocatalysis

Team: Hygiene Hackers

Inspiration

Our inspiration came from observing poorly maintained public sanitation facilities during our field visits. Despite substantial investments in sanitation infrastructure, unhygienic public toilets, foul odour, irregular maintenance, and open urination remain challenges in many communities.

Women and girls are particularly affected when public toilets are dirty, unsafe, or unusable. These conditions can compromise their dignity, privacy, comfort, and access to basic sanitation. When public facilities fail to meet people's needs, some avoid using them, while open urination continues to affect public spaces and community hygiene.

India has invested heavily in sanitation through initiatives such as the Swachh Bharat Mission. However, constructing sanitation infrastructure is only part of the solution; facilities must also remain clean, functional, and accessible.

We wanted to address this gap by combining photocatalysis, automation, and the Internet of Things (IoT) to develop an affordable and sustainable solution for better public urinal hygiene.

What It Does

Our Smart Self-Cleaning Urinal System combines titanium dioxide (TiO₂) photocatalysis with sensor-based automation and IoT monitoring.

Photocatalytic cleaning: A TiO₂ coating activated by UV-A light is designed to help break down organic contaminants on treated surfaces, potentially reducing residue and foul odour.

UV-based disinfection: A proposed UV-C component aims to support microbial disinfection, subject to safety controls and experimental validation.

Touchless flushing: Sensors detect user presence and enable automatic flushing, reducing the need for physical contact.

Smart water management: A water-flow sensor monitors consumption, while additional sensors support water-level monitoring and leakage detection.

IoT monitoring: An ESP32 microcontroller sends system data to a cloud dashboard, supporting remote monitoring and maintenance alerts.

Voice reminders: Audio prompts encourage appropriate hygiene practices.

By bringing these technologies together, our system aims to reduce dependence on frequent manual cleaning, improve water management, and support better-maintained public sanitation facilities.

How We Built It

We developed an electronic prototype around an ESP32 microcontroller, integrating sensors (NH3, DHT11, two channel driver, a solenoid valve, and supporting components.

A time-of-flight distance sensor detects user presence, while a water-flow sensor measures water consumption. An ammonia sensor monitors an indicator associated with unpleasant odour, and additional sensors support environmental and water-level monitoring. The ESP32 processes sensor readings and controls the connected components.

We programmed the system using the Arduino IDE and integrated IoT functionality with a cloud dashboard to display operational parameters and alerts.

For the photocatalytic component, we applied a TiO₂ coating to a ceramic tile and conducted a preliminary experiment using a coffee stain. This helped us explore the potential of photocatalytic self-cleaning. However, the test was preliminary and does not yet establish the coating's effectiveness on an actual urinal.

Our project brings together electronics, programming, and material science to explore a solution that could potentially be retrofitted into existing public urinals.

Challenges We Ran Into

One of our biggest challenges was integrating multiple sensors and electronic components into a single working system. Reliable sensor readings, automated flushing, water-flow measurement, and cloud connectivity required careful integration and testing.

Another challenge was translating the scientific concept of photocatalysis into a practical sanitation application. Although our ceramic-tile experiment allowed us to explore the coating's potential, further testing is needed to measure cleaning efficiency and determine its durability on actual urinal surfaces.

We also had to consider affordability, energy consumption, water efficiency, and maintenance requirements. Since the system is intended for public facilities, the UV components must include suitable shielding and safety interlocks to prevent harmful exposure.

These challenges taught us that an innovative idea must be supported by careful engineering, safety considerations, and evidence from real-world testing.

Accomplishments We're Proud Of

We are proud to have developed a prototype that combines photocatalysis, IoT technology, and automated sanitation to address a persistent public hygiene problem. Our project is addressing the following USDs: SDG 6: Clean Water and Sanitation. SDG 3: Good Health and Well-Being. SDG 11: Sustainable Cities and Communities. SDG 9: Industry, Innovation and Infrastructure SDG 12: Responsible Consumption and Production

Our accomplishments include:

Developing an ESP32-based prototype with sensor-driven automation.

Integrating water-flow monitoring and cloud-based system monitoring.

Exploring TiO₂ photocatalysis through preliminary testing on a coated ceramic tile.

Designing a modular concept with potential for retrofitting existing urinals.

Presenting our innovation through student research and innovation platforms.

Applying engineering and material science to a real community sanitation challenge.

Above all, we are proud that our project began with a problem affecting everyday life. Rather than focusing only on building sanitation facilities, we wanted to explore how technology could help keep them cleaner, functional, and easier to maintain.

What We Learned

This project taught us that innovation involves much more than developing an idea. It requires understanding community needs, researching scientific principles, building prototypes, integrating hardware and software, testing assumptions, and learning from limitations.

We explored how photocatalysis may help break down organic contaminants, how sensors and microcontrollers can automate sanitation processes, and how IoT systems can support remote monitoring.

We also learned the importance of distinguishing between intended benefits and experimentally demonstrated results. Our initial coating test helped us investigate feasibility, but further research is required to establish photocatalytic efficiency, antimicrobial performance, coating durability, and actual water savings.

Most importantly, we learned that sanitation is not just an infrastructure problem. It is also a matter of dignity, accessibility, sustainability, and accountability. Technology can contribute to addressing these challenges when it is designed around people's needs and validated through practical testing.

Sustainable Development Goals (SDGs)

Our project primarily supports SDG 6: Clean Water and Sanitation by exploring photocatalytic cleaning, touchless flushing, and smart water monitoring to improve public urinal hygiene.

It also contributes to:

SDG 11 — Sustainable Cities and Communities: By addressing poor public sanitation and exploring ways to maintain cleaner public facilities.

SDG 3 — Good Health and Well-Being: By aiming to improve hygiene and investigating UV-based microbial disinfection.

SDG 9 — Industry, Innovation and Infrastructure: By integrating photocatalysis, sensors, automation, and IoT technology into a sanitation solution.

Our broader mission also connects with SDG 5 — Gender Equality, recognizing how inadequate public sanitation affects women and girls, and SDG 12 — Responsible Consumption and Production, through our focus on water monitoring and potentially reducing dependence on frequent chemical cleaning.

These connections reflect our project's intended contributions; further testing and field trials are needed to verify its real-world impact.

What's Next?

Our next goal is to transform our prototype into a reliable, most affordable, and field-tested sanitation solution.

Our future plans include:

Photocatalytic validation: Test TiO₂ coatings on actual urinal surfaces and evaluate cleaning performance and durability.

Disinfection testing: Conduct controlled microbial tests and validate UV-C safety measures.

Water-efficiency studies: Compare water consumption with conventional urinals under similar conditions.

Smarter monitoring: Improve our cloud dashboard and explore AI-assisted maintenance alerts and usage analytics.

Cost optimization: Refine component selection and design to reduce manufacturing and installation costs.

Field trials: Collaborate with municipal bodies, schools, colleges, and public facility operators to evaluate real-world performance.

Scalable deployment: Explore retrofitting existing urinals and installing the system in railway stations, bus terminals, educational institutions, hospitals, shopping centres, and other public facilities.

In the long term, we envision a sustainable sanitation system that supports better-maintained public facilities, reduces unnecessary resource consumption, and helps create cleaner, more accessible public spaces for everyone.

Our ambition is not merely to build a smart urinal, but to help bridge the gap between sanitation infrastructure and the outcomes people actually experience.

Our motto: “Hack the Filth — Heal the World.”

Built With

  • arduino
  • dfplayer
  • dht11
  • esp32
  • nh3sensor
  • solenoid
  • speaker
  • tof
  • uvlight
Share this project:

Updates

posted an update —

If any further details are required, kindly let me know.

I started this project about one and a half year ago, since then we have been adding some improved features. We integrated with Blynk IoT Cloud Plat form. /* Smart Photocatalytic Urinal – FINAL COMPLETE VERSION

  • Beautified UI (Fonts & Background)
  • Same Layout, Same Logic */ #define BLYNK_PRINT Serial

define BLYNK_TEMPLATE_ID "TMPL38cF3weDR"

define BLYNK_TEMPLATE_NAME "Smart Urinal NH3"

define BLYNK_AUTH_TOKEN "wB4D3rfMonXp6Kz6EfBePjbQ32xf-c2k"

include

include

include

include

include

include "DHT.h"

include

include

include

HardwareSerial dfSerial(2); DFRobotDFPlayerMini dfPlayer;

// ---------- BLYNK TIMING ---------- unsigned long lastBlynkMillis = 0; const unsigned long blynkInterval = 1000; // 1 second

/* -------- WATER LEVEL SENSOR (HC-SR04) -------- */

define WATER_TRIG_PIN 26

define WATER_ECHO_PIN 33

define TANK_DEPTH_CM 30

long waterDistance = 0; unsigned long lastWaterMillis = 0; int waterPercent = 0; // Tank level in %

/* -------- ANNOUNCEMENT CONTROL -------- */ unsigned long personEnterMillis = 0; bool announcementPlayed = false; const unsigned long ANNOUNCE_DELAY = 1000;

/* ---------------- HARDWARE ---------------- */ Adafruit_VL53L1X lox;

const int UVLED = 4; const int solenoidPin = 27; const int GLED = 19; const int announceTrigger = 25; const int DHTPIN = 5; const int NH3_PIN = 35;

/* -------- WATER FLOW SENSOR -------- */ const int FLOW_PIN = 34; volatile unsigned long flowPulses = 0; float flowRate = 0.0; float totalWater = 0.0;

unsigned long lastFlowMillis = 0; unsigned long flowStartMillis = 0; bool waterFlowing = false; bool leakageAlert = false; bool poor_hygieneAlertSent = false; // POOR Hygiene Alert Flag bool lowWaterAlertSent = false; // Low Water Alert Flag

const float PULSES_PER_LITER = 1000.0; const unsigned long LEAK_TIME = 30000;

/* -------- STATIC IP CONFIG -------- */ IPAddress local_IP(10,234,90,100); IPAddress gateway(10,234,90,76); IPAddress subnet(255,255,255,0); IPAddress primaryDNS(10,234,90,76); IPAddress secondaryDNS(8,8,8,8);

/* ---------------- WIFI ---------------- / const char ssid = "BHUPEN"; const char* password = "Mithra@2010";

/* ---------------- SERVERS ---------------- */ WebServer httpServer(80); WebSocketsServer webSocket(81);

/* ---------------- DHT ---------------- */

define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE); float lastTemp = NAN, lastHum = NAN; unsigned long lastDHTMillis = 0; const unsigned long dhtInterval = 5000;

/* ---------------- HYGIENE ---------------- */ int nh3Raw = 0; int hygieneIndex = 0; String hygieneLevel = "UNKNOWN";

/* ---------------- CONFIG ---------------- */ unsigned long flushDuration = 6000; int distanceActivate = 70; int countThreshold = 3;

/* ---------------- LOGIC ---------------- */ int distanceCm = 1000, stableDistance = 1000; int count = 0; long userCount = 0;

bool solenoidState = false; bool uvState = false; bool userPresent = false;

/* ---------------- TIMING ---------------- */ unsigned long lastCountMillis = 0; unsigned long flushStartMillis = 0; unsigned long lastBroadcastMillis = 0; const unsigned long broadcastInterval = 150;

/* -------- FLOW INTERRUPT -------- */ void IRAM_ATTR flowISR(){ flowPulses++; }

/* ---------------- UV HELPER ---------------- */ void setUV(bool state){ digitalWrite(UVLED, state ? HIGH : LOW); uvState = state; }

long readWaterLevelCM() { digitalWrite(WATER_TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(WATER_TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(WATER_TRIG_PIN, LOW);

long duration = pulseIn(WATER_ECHO_PIN, HIGH, 30000); // 30ms timeout if (duration == 0) return TANK_DEPTH_CM;

long distance = duration * 0.0343 / 2; return constrain(distance, 0, TANK_DEPTH_CM); }

void updateWaterLevel() {

// Distance from sensor to water surface static int lastDist = TANK_DEPTH_CM; int d = readWaterLevelCM(); waterDistance = (lastDist * 3 + d) / 4; lastDist = waterDistance;

// Actual water height inside tank int waterHeight = TANK_DEPTH_CM - waterDistance; waterHeight = constrain(waterHeight, 0, TANK_DEPTH_CM);

// Convert to percentage (0–100) waterPercent = map(waterHeight, 0, TANK_DEPTH_CM, 0, 100);

// Debug Serial.print("Tank Level: "); Serial.print(waterPercent); Serial.println(" %"); }

void sendToBlynk() {

Blynk.virtualWrite(V1, distanceCm); Blynk.virtualWrite(V2, userCount); Blynk.virtualWrite(V3, lastTemp); Blynk.virtualWrite(V4, lastHum); Blynk.virtualWrite(V5, flowRate); Blynk.virtualWrite(V6, totalWater); Blynk.virtualWrite(V7, hygieneIndex); Blynk.virtualWrite(V8, hygieneLevel); Blynk.virtualWrite(V9, leakageAlert ? 1 : 0); Blynk.virtualWrite(V10, waterPercent); // Tank % only

// -------------------------------------------------- // Poor Hygiene ALERT EVENT (hygieneIndex > 250) // -------------------------------------------------- if (hygieneIndex > 250 && !poor_hygieneAlertSent) {

Blynk.logEvent("poor_hygiene", 
  "ALERT: HYGIENE INDEX crossed 250!- Urgent Cleaning is required. Current Hygiene Index: " + String(hygieeIndex));

poor_hygieneAlertSent = true;

}

// Reset alert when AQI normal if (hygieneIndex <= 100) { poor_hygieneAlertSent = false; }

// -------------------------------------------------- // lowWaterAlertSent ALERT EVENT (waterPercent < 20) // -------------------------------------------------- if (waterPercent < 20 && !lowWaterAlertSent) {

Blynk.logEvent("low_water", 
 "ALERT: Low Water level below 20%!- Urgent Water Filling to Tank is required. Current Water Tank Level: " + String(waterPercent));

lowWaterAlertSent = true;

}

// Reset alert when AQI normal if (waterPercent >= 20) { lowWaterAlertSent = false; } }

BLYNK_WRITE(V0) { if (param.asInt()) { digitalWrite(solenoidPin, LOW); solenoidState = true; flushStartMillis = millis(); } }

/* ---------------- WEB PAGE (BEAUTIFIED) ---------------- */ const char webpage[] PROGMEM = R"rawliteral( <!DOCTYPE html> Smart Urinal Dashboard

--   |   -- body{ font-family:'Segoe UI',Roboto,Arial,sans-serif; background:#f5f7fa; color:#1f2937; text-align:center; } h3{ margin:14px 0; letter-spacing:0.6px; color:#0f766e; font-size:2em; } h4{ margin:14px 0; letter-spacing:0.6px; color:#0f766e; font-size:1.5em; } table{ border-collapse:separate; border-spacing:0; margin:10px auto; width:95%; max-width:1150px; background:#ffffff; box-shadow:0 8px 24px rgba(0,0,0,0.08); border-radius:10px; overflow:hidden; } th,td{ padding:8px 10px; font-size:18px;// font size in the table padding:8px;border:1px solid #cbd5e1; //added for cell borders } th{ background:#e6f4f1; color:#065f46; font-weight:600; border-bottom:2px solid #b2dfdb; } tr:not(:first-child) td{ border-bottom:1px solid #e5e7eb; } .label{ text-align:left; color:#374151; } .value{ text-align:center; font-weight:600; color:#111827; } .alert{ color:#dc2626; font-weight:700; } #flushBox{ width:90px; height:130px; border:2px solid #0f766e; border-radius:8px; margin:12px auto; display:none; overflow:hidden; } .water{ width:100%; height:100%; background:linear-gradient(180deg,#99d9f2,#38bdf8,#0284c7); animation:flow 0.6s linear infinite; } @keyframes flow{ 0%{transform:translateY(-100%)} 100%{transform:translateY(100%)} } input{ width:70px; padding:4px; border:1px solid #94a3b8; border-radius:4px; } button{ padding:6px 14px; border:none; background:#0f766e; color:white; border-radius:6px; font-weight:600; cursor:pointer; } .excellent { color: #16a34a; /* Green */ font-weight: 700; } .acceptable { color: #2563eb; /* Blue */ font-weight: 700; } .poor { color: #f59e0b; /* Orange */ font-weight: 700; } .unhygienic { color: #dc2626; /* Red */ font-weight: 700; } .leak-ok { color: #16a34a; /* Green */ font-weight: 700; } .leak-bad { color: #dc2626; /* Red */ font-weight: 700; } .tank-good { color: #16a34a; /* Green */ font-weight: 700; } .tank-mid { color: #2563eb; /* Blue */ font-weight: 700; } .tank-low { color: #dc2626; /* Red */ font-weight: 700; } button:hover{background:#115e59}

SMART SELF-CLEANING URINAL SYSTEM using PHOTOCATALYSIS

for Public Hygiene & Sustainable Sanitation

Presence & Usage System Control Environment & Hygiene Water Monitoring
Distance (cm)-- Activation Distance-- Temperature (°C)-- Flow Rate (L/min)--
Live Count (Sec)-- Flush Duration (Sec)-- Humidity (%)-- Total Water Used (L)--
Count Threshold (Sec)-- Ultraviolet (UV) Light-- Hygiene Index-- Leakage AlertNO LEAKAGE
Total Users-- Solenoid Valve (Flush)-- Hygiene Level-- Tank Level--

⚙ Control Settings

Activation Distance Threshold Count Flush Duration (in Sec.) Apply function updateDateTime() { const now = new Date(); const dateStr = now.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' }); const timeStr = now.toLocaleTimeString(); document.getElementById("date").textContent = dateStr; document.getElementById("time").textContent = timeStr; } setInterval(updateDateTime, 1000); updateDateTime(); // initial call const ws=new WebSocket('ws://'+location.hostname+':81/'); ws.onmessage=e=>{ const d=JSON.parse(e.data); distance.textContent=d.distance; count.textContent=d.count; countTh.textContent=d.countThreshold; users.textContent=d.users; actDist.textContent=d.distanceActivate; flushDur.textContent=d.flushDuration; uv.textContent=d.uv; solenoid.textContent=d.solenoid; temp.textContent=d.temp??"--"; hum.textContent=d.hum??"--"; hIndex.textContent=d.hygieneIndex; hygiene.textContent = d.hygiene; hygiene.className = "value"; // reset styling if (d.hygiene === "Excellent") { hygiene.classList.add("excellent"); } else if (d.hygiene === "Acceptable") { hygiene.classList.add("acceptable"); } else if (d.hygiene === "POOR") { hygiene.classList.add("poor"); } else if (d.hygiene === "UNHYGIENIC") { hygiene.classList.add("unhygienic"); } flow.textContent=d.flowRate; water.textContent=d.totalWater; waterLevel.textContent = d.waterPercent + " %"; waterLevel.className = "value"; // reset first if (d.waterLevel === "FULL") { waterLevel.classList.add("tank-good"); } else if (d.waterLevel === "HALF") { waterLevel.classList.add("tank-mid"); } else if (d.waterLevel === "LOW" || d.waterLevel === "NO WATER") { waterLevel.classList.add("tank-low"); } leak.textContent = d.leakageAlert ? "⚠ LEAK" : "NO LEAKAGE"; leak.className = "value"; // reset if (d.leakageAlert) { leak.classList.add("leak-bad"); } else { leak.classList.add("leak-ok"); } flushBox.style.display=(d.solenoid==="ON")?"block":"none"; };

)rawliteral";

/* ---------------- HTTP ---------------- */ void handleRoot(){ httpServer.send_P(200,"text/html",webpage); }

void handleSet(){ if(httpServer.hasArg("distance")) distanceActivate=httpServer.arg("distance").toInt(); if(httpServer.hasArg("countth")) countThreshold=httpServer.arg("countth").toInt(); if(httpServer.hasArg("flush")) flushDuration=httpServer.arg("flush").toInt()*1000UL; httpServer.sendHeader("Location","/"); httpServer.send(303); }

/* ---------------- HYGIENE ---------------- */ void updateHygieneLevel(){ nh3Raw=analogRead(NH3_PIN); hygieneIndex=map(nh3Raw,0,4095,0,500); if(hygieneIndex<50) hygieneLevel="Excellent"; else if(hygieneIndex<120) hygieneLevel="Acceptable"; else if(hygieneIndex<250) hygieneLevel="POOR"; else hygieneLevel="UNHYGIENIC"; }

/* ---------------- BROADCAST ---------------- */ void broadcastState(){ String j = "{"; j += "\"distance\":" + String(distanceCm) + ","; j += "\"count\":" + String(count) + ","; j += "\"countThreshold\":" + String(countThreshold) + ","; j += "\"users\":" + String(userCount) + ","; j += "\"distanceActivate\":" + String(distanceActivate) + ","; j += "\"flushDuration\":" + String(flushDuration / 1000) + ","; j += "\"uv\":\"" + String(uvState ? "ON" : "OFF") + "\","; j += "\"solenoid\":\"" + String(solenoidState ? "ON" : "OFF") + "\","; j += "\"temp\":" + (isnan(lastTemp) ? String("null") : String(lastTemp)) + ","; j += "\"hum\":" + (isnan(lastHum) ? String("null") : String(lastHum)) + ","; j += "\"hygieneIndex\":" + String(hygieneIndex) + ","; j += "\"hygiene\":\"" + hygieneLevel + "\","; j += "\"flowRate\":" + String(flowRate, 2) + ","; j += "\"totalWater\":" + String(totalWater, 2) + ","; j += "\"leakageAlert\":" + String(leakageAlert ? "true" : "false") + ","; j += "\"waterPercent\":" + String(waterPercent) + ","; j += "\"waterDistance\":" + String(waterDistance); j += "}";

webSocket.broadcastTXT(j); }

/* ---------------- SETUP ---------------- */ void setup(){ Serial.begin(115200); Wire.begin(); pinMode(UVLED,OUTPUT); pinMode(GLED,OUTPUT); pinMode(solenoidPin,OUTPUT); pinMode(announceTrigger,OUTPUT);

pinMode(NH3_PIN,INPUT); pinMode(FLOW_PIN,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(FLOW_PIN), flowISR, RISING);

pinMode(WATER_TRIG_PIN, OUTPUT); pinMode(WATER_ECHO_PIN, INPUT); // GPIO33 → no INPUT_PULLUP

digitalWrite(solenoidPin,HIGH); digitalWrite(announceTrigger,HIGH); dfSerial.begin(9600, SERIAL_8N1, 16, 17);

delay(1000); // IMPORTANT (DFPlayer boot time)

if (!dfPlayer.begin(dfSerial)) { Serial.println(" DFPlayer NOT detected!"); } else { Serial.println(" DFPlayer READY!"); dfPlayer.volume(30);

delay(500); dfPlayer.play(2); // TEST SOUND ON STARTUP }

dht.begin(); lox.begin(); lox.startRanging();

WiFi.config(local_IP,gateway,subnet,primaryDNS); WiFi.begin(ssid,password); while(WiFi.status()!=WL_CONNECTED) delay(300);

Blynk.config(BLYNK_AUTH_TOKEN); Blynk.connect(); Blynk.config(BLYNK_AUTH_TOKEN); Blynk.connect();

httpServer.on("/",handleRoot); httpServer.on("/set",handleSet); httpServer.begin(); webSocket.begin(); }

/* ---------------- LOOP ---------------- */ void loop(){

Blynk.run();

httpServer.handleClient(); webSocket.loop(); unsigned long now=millis();

if (millis() - lastBlynkMillis >= blynkInterval) { lastBlynkMillis = millis(); sendToBlynk(); }

if(lox.dataReady()){ int rawDist=lox.distance()/10; if(rawDist>0 && rawDist<300){ stableDistance=(stableDistance*3+rawDist)/4; distanceCm=stableDistance; } else distanceCm=1000; lox.clearInterrupt(); }

bool personNow=(distanceCm>=5 && distanceCm<=distanceActivate);

if (millis() - lastWaterMillis >= 3000) { // every 3 seconds Water Level Sensing updateWaterLevel(); lastWaterMillis = millis(); }

if(personNow){ if(!userPresent){ userPresent=true; personEnterMillis=now; announcementPlayed=false; } // -------- FINAL ANNOUNCEMENT FIX -------- if (!announcementPlayed && (now - personEnterMillis > ANNOUNCE_DELAY)) { Serial.println(" Playing announcement"); // DEBUG dfPlayer.play(1); // plays 0001.mp3 announcementPlayed = true; } if(now-lastCountMillis>=2000){ lastCountMillis=now; count++; } digitalWrite(GLED,HIGH); } else { userPresent=false; announcementPlayed=false; personEnterMillis=0; lastCountMillis=now; digitalWrite(GLED,LOW); if(count>=countThreshold && !solenoidState){ digitalWrite(solenoidPin,LOW); solenoidState=true; flushStartMillis=now; userCount++; } count=0; }

if(solenoidState||personNow) setUV(false); else setUV(true);

if(solenoidState && now-flushStartMillis>=flushDuration){ digitalWrite(solenoidPin,HIGH); solenoidState=false; }

if(now-lastFlowMillis>=1000){ noInterrupts(); unsigned long pulses=flowPulses; flowPulses=0; interrupts(); flowRate=(pulses/PULSES_PER_LITER)*60.0; totalWater+=(pulses/PULSES_PER_LITER); if(flowRate>0.05){ if(!waterFlowing){ waterFlowing=true; flowStartMillis=now; } if(now-flowStartMillis>=LEAK_TIME) leakageAlert=true; } else { waterFlowing=false; leakageAlert=false; } lastFlowMillis=now; }

if(now-lastDHTMillis>=dhtInterval){ lastDHTMillis=now; float t=dht.readTemperature(); float h=dht.readHumidity(); if(!isnan(t)&&!isnan(h)){ lastTemp=t; lastHum=h; } }

updateHygieneLevel(); Serial.print("Water Distance: "); Serial.print(waterDistance); Serial.print(" cm | Level: "); Serial.print("Tank %: "); Serial.println(waterPercent);

if(now-lastBroadcastMillis>=broadcastInterval){ lastBroadcastMillis=now; broadcastState(); } }

Log in or sign up for Devpost to join the conversation.

Submission history