Tap Alert!

In late 2020 I started the development of a device named Tap Alert! The idea for the product was that it would be able to attach to standardized fixtures and fittings on the end of a tap, and when it detects that water has been running for over a user-definable amount of time, it alerts the user to this, it achieves this by Beeping, Flashing and Sending notifications to a Users Phone. The original target audience for the device was Blind and Visually impaired users, although through the development process I found a secondary market of people looking to save money on expensive water bills. I developed this project as part of my A-Level Product Design Course.

After doing a lot of research into different areas such as Ergonomics and required Electronics, I came up with Six Original first Concepts.

From my original Six first concept drawings, I created 4 further developments, after thoroughly bulking out the concepts I settled on one. This was the first “Building Block” that I based my final product off of.

Once I was happy with the final design I started work on developing the final design- I did research into electronics and Microcontrollers, eventually settling on using an ESP8622-E12F as the main Microprocessor for this device, this allowed me to create a Webserver that I could then use to send Push Notifications to a users Device.

I also did research into how I could make sense the presence of water, I looked into flow metres and other similar devices, eventually settling on using a moisture sensor, normally used to detect the presence of moisture in Plant Pots. However, with some clever code, I could make it detect the presence of Water. So I started developing my final design. It took a few iterations but when I was done I was finally left with this:

With this model, I was able to use FDM 3D printing technology to produce a final part, which I was able to use to assemble the device together.

Once I finished the final assembly I flashed the custom firmware that I wrote using C++ and Compiled and using the Arduino IDE. And I was finally complete with this product.


/*Importing Notification and Wifi Libaries*/
#include Pushsafer.h
#include ESP8266WiFi.h
#include WiFiClient.h
#include WiFiManager.h

WiFiServer server(80);

int currentState = 0; // Sets the Current State to 1 if analog Read threshold met.
int lastState = 0;   // Saves the Previous State to refer to later.
int numberOfActivations = 0; // Used to track total number of activations
unsigned long timeStart = 0;  // Used for debugging
unsigned long runTime; // Used to compare if time between activation is less than 5000
unsigned long timeSinceStart = 0;
unsigned long finalTime = 5000;
unsigned long timeSinceLastActivation = 1000;



//Defining Console Messages
String runTimeTxtIn = "Time Since Timer Last Timer Start - Millis: ";
String runTimeTxtOut;
String analogValueTxtIn = "Analog Value: ";
String analogValueTxtOut;
String currentStateTxtIn = "Check State: ";
String currentStateTxtOut;
String millisTxtIn = "Millis(): ";
String millisTxtOut;
String timerStartTxtIn = "Timer Start: ";
String timerStartTxtOut;
String timeSinceStartTxtIn = "Time Since Start: ";
String timeSinceStartTxtOut;
String numberOfActivationsTxtInPart1 = "Youve left the Tap Running ";
String numberOfActivationsTxtInPart2 = " Times this week";
String numberOfActivationsTxtOut;

 /*Important to make Serial Monitor work*/
#include 
SoftwareSerial GPIO4(2);

int sensorPin = A0; /*Moisture Sensor Poin*/
int sensorValue;  /*Moisture Sensor Output Value*/
int limit = 1000;   /*Defines the Threshold for device to activate*/
const int ledPin = 2;  /*Defines the LED Pin*/

// Pushsafer private or alias key
#define PushsaferKey "YXNrdZ9YDdwn4HMXtT9m"

/*WiFiClientSecure client;*/
WiFiClient client;
Pushsafer pushsafer(PushsaferKey, client);

void setup() {
 Serial.begin(9600);
 pinMode(ledPin, OUTPUT);

 WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP

//WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wm;

bool res;
res = wm.autoConnect("TapDetector",""); // password protected ap

if(!res) {
    Serial.println("Failed to connect");
    // ESP.restart();
    } 
else {
    //if you get here you have connected to the WiFi    
    Serial.println("Wifi Connected: ");
}



  // Set WiFi to station mode and disconnect from an AP if it was Previously
//  // connected
//  WiFi.mode(WIFI_STA);
//  WiFi.disconnect();
//  delay(100);
//
//  // Attempt to connect to Wifi network:
//  Serial.print("Connecting Wifi: ");
//  Serial.println(ssid);
//  WiFi.begin(ssid, password);
//
//  while (WiFi.status() != WL_CONNECTED) {
//    Serial.print(".");
//    delay(500);
//}

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  pushsafer.debug = true;
}


void loop() {

  //Structure of PushSafer Notifications
  struct PushSaferInput input;
  input.message = "Quick! Go turn it off!";
  input.title = "Youve left your Tap Running!";
  input.sound = "41";
  input.vibration = "";
  input.icon = "149";
  input.iconcolor = "#FFCCCC";
  input.priority = "1";
  input.device = "a";
  input.url = "https://louishitchcockdesign.wordpress.com/";
  input.urlTitle = "";
  input.picture = "";
  input.picture2 = "";
  input.picture3 = "";
  input.time2live = "";
  input.retry = "";
  input.expire = "";
  input.answer = "";

sensorValue = analogRead(sensorPin); // Reads the value of the Sensor between 1024 - 0
analogValueTxtOut = analogValueTxtIn + sensorValue;   // Formats text to be output in Console
Serial.println(analogValueTxtOut);  //Writes the Analog Value in Console
 
if (sensorValue = finalTime) {    // Checks to see if 'timeSinceStart' is more than or equal to 'finalTime' (5000ms)
  Serial.println("Activated (First Activation)");  // Prints Activated in console (debugging)
  delay(50);  // waits 50ms
  currentState = 0; // resets 'currentState' to 0
  lastState = 0; // resets 'lastState' to 0
  timeSinceStart = 0; // resets 'timeSinceStart' to 0
  timeStart = 0;   // resets 'timeStart' to 0
  finalTime = finalTime;  // ((Adds 5000ms longer to required activation time for loop -- OLD))
  numberOfActivations = numberOfActivations + 1; // Used to track Total number of Activations
  timeSinceLastActivation = millis(); // Sets system running time in ms to 'timeSinceLastActivation' used to comapare and not spam the console
  numberOfActivationsTxtOut = numberOfActivationsTxtInPart1 + numberOfActivations + numberOfActivationsTxtInPart2;
//  
  Serial.println(pushsafer.sendEvent(input));  // Sends Notification
  Serial.println("Sent");    //Prints "Sent" in console.

  Serial.println("Waiting 30 Seconds");
  delay(5000);
  Serial.println("25 Seconds");
  delay(5000);
  Serial.println("20 Seconds");
  delay(5000);
  Serial.println("15 Seconds");
  delay(5000);
  Serial.println("10 Seconds");
  delay(5000);
  Serial.println("5 Seconds");
  delay(5000);
  Serial.println("Restarting");
   }
}


//if  (millis() < 604800000); {     //Sends Weekly Breakdown.         WIP
//
//  //Structure of PushSafer Notifications
//  struct PushSaferInput weekly;
//  input.message = numberOfActivationsTxtOut;
//  input.title = "";
//  input.sound = "2";
//  input.vibration = "1";
//  input.icon = "1";
//  input.iconcolor = "#FFCCCC";
//  input.priority = "1";
//  input.device = "a";
//  input.url = "";
//  input.urlTitle = "";
//  input.picture = "";
//  input.picture2 = "";
//  input.picture3 = "";
//  input.time2live = "";
//  input.retry = "";
//  input.expire = "";
//  input.answer = "";
//    Serial.println(pushsafer.sendEvent(input));  // Weekly Notification
//    Serial.println("Sent Weekly Notification");    //Prints "Sent" in console.
//}




//Debug
currentStateTxtOut = currentStateTxtIn + currentState;
Serial.println(currentStateTxtOut);

timerStartTxtOut = timerStartTxtIn + timeStart;
Serial.println(timerStartTxtOut);

timeSinceStartTxtOut = timeSinceStartTxtIn + timeSinceStart;
Serial.println(timeSinceStartTxtOut);

millisTxtOut = millisTxtIn + millis();
Serial.println(millisTxtOut);


numberOfActivationsTxtOut = numberOfActivationsTxtInPart1 + numberOfActivations + numberOfActivationsTxtInPart2;
Serial.println(numberOfActivationsTxtOut);


Serial.println("\n");   // Adds a line of spacing in console.
delay(1000);  // Waits 1 second and restarts loop
}

Overall I’m happy with my final product, if I were to re-design it for a commercial application I’d make my own Microcontroller, this would allow me to make it a lot smaller and more compact, which would help improve the overall aesthetics of the device.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s