Dominic F.Alex SagrisAaron Lutheran
Published

Filtered Water Dispenser

A miniature water dispenser that can be attached to a faucet head can feed the water through a filtration system.

IntermediateShowcase (no instructions)10 hours53
Filtered Water Dispenser

Things used in this project

Hardware components

Argon
Particle Argon
Could be condensed to have all sensors function on 2 argons, but this project was designed with the intent of 3 argon boards in the system.
×3
Water TDS Sensor
×1
IR receiver (generic)
×1
IR transmitter (generic)
×1
Plastic Solenoid Inlet Valve
×1

Software apps and online services

ThingSpeak API
ThingSpeak API
Particle Build Web IDE
Particle Build Web IDE

Story

Read more

Custom parts and enclosures

Spacers

Stand Legs

Schematics

Cup Sensor Schematic

Input Valve Schematic

Tank Sensors Schematic

Communication Diagram

Water Quality Graph

ThingSpeak Water Quality vs. Time plot

Code

Tank Sensors

C/C++
The Tank argon constantly uploads the current water quality to the ThingSpeak graphing integration. When the tank is not full, a message is sent to the Input Valve Argon, which then sends a confirmation back, turning on the Tank Argon's LED. After the tank fills, a message is sent to the Input Valve Argon to shut off the input. Confirmation of this completion shuts off the Tank Argon's LED. The Tank Argon also receives messages from the cup sensor, requesting a water quality check. If the quality is high enough, confirmation is sent back, allowing the output valve to open.
int FillLevelPin = A3;
int FillLevel = 0;
int FillLevelOld = 0;
int FillReq = 2000;

int PPMpin = A4;
int PPM = 0;
int PPMOld = 0;
int PPMreq = 1000;

int ValveLED = D8;

int i = 0;

String qualityLog = "";

void setup() {
    //pinMode(FillLevelPin, INPUT_PULLDOWN); // Default pin to HIGH, grounding pin to LOW
    pinMode(ValveLED, OUTPUT);
    Particle.subscribe("request-quality", checkQuality, MY_DEVICES); // When quality is requested, run checkQuality function
    Particle.subscribe("tank-full", tankFull, MY_DEVICES);
    Particle.subscribe("tank-filling", tankFilling, MY_DEVICES);
    Serial.begin(9600);
}

void loop() {
    FillLevel = analogRead(FillLevelPin);
    PPM = analogRead(PPMpin);
    if (PPM > PPMreq && PPMOld < PPMreq) {
        Particle.publish("PPMwarning"); // Notification event
    }
    if (FillLevel > FillReq && FillLevelOld < FillReq) { //When fill level drops...
        Particle.publish("request-fill"); // Request fill valve to open
        delay(1000); // Delay 1 second as to not overload publishing limit
        while (FillLevel > FillReq) { // DO NOT DO OTHER EVENTS UNITL VALVE IS OFF
            FillLevel = analogRead(FillLevelPin); // Update Fill Level inside loop
            delay(100);
        }
        Particle.publish("request-stop"); // Stop valve upon leaving while loop
    }
    Serial.printlnf("%d", FillLevel);
    FillLevelOld = FillLevel;
    PPMOld = PPM;
    delay(500);
    qualityLog = String(PPM);
    Particle.publish("Water Quality", qualityLog, PRIVATE);
}

void checkQuality(const char *event, const char *data) { // Function
    if (PPM < PPMreq) { // If PPM is low enough...
        Particle.publish("quality-confirmed"); // Send back confirmation
    }
    delay(500);
}
void tankFull(const char *event, const char *data) { // Function
    digitalWrite(ValveLED, LOW);
}
void tankFilling(const char *event, const char *data) { // Function
    digitalWrite(ValveLED, HIGH);
}

Cup Sensor

C/C++
This code controls the IR sensor to detect when a cup is placed in front of the outlet. When the receiver detects a sufficiently low distance, it submits a request to the PPM sensor to confirm a high enough water quality in the tank. When confirmation is received, the valve is opened.
int ValvePin = D3;
int IRPin = A4;
int IR = 0;
int IROld = 0;
int Filtered = 1500;
int FilterConst = 0;
int Cutoff = 600;

void setup() {
    pinMode(IRPin, INPUT_PULLDOWN); // Initialize Sensor Pin
    pinMode(ValvePin, OUTPUT); // Initialize Valve Pin
    digitalWrite(ValvePin, LOW); //  Turn Valve Off
    Particle.subscribe("quality-confirmed", openValve, MY_DEVICES); // When confirmation is recieved, run openValve function
}
void loop() {
    IR = analogRead(IRPin);
    Filtered = ((Filtered*FilterConst)+IR)/(FilterConst+1);
    if (Filtered > Cutoff && IROld < Cutoff){ // When cup is detected...
        Particle.publish("request-quality", PRIVATE); // Request water quality
    } else if (Filtered < Cutoff && IROld > Cutoff) { // When cup is moved...
        digitalWrite(ValvePin, LOW); // Close valve
    }
    delay(100);
    IROld = Filtered;
}

void openValve(const char *event, const char *data) { // Function
    digitalWrite(ValvePin, HIGH); // Opens Valve
}

Input Valve

C/C++
The input valve argon waits for a fill request to be published. When a request is published, confirmation is sent back and the valve is turned on. The argon responds similarly to stop requests.
int InputValvePin = D0;

void setup() {
    pinMode(InputValvePin, OUTPUT);
    Particle.subscribe("request-stop", stopValve, MY_DEVICES);
    Particle.subscribe("request-fill", startValve, MY_DEVICES);
}

void loop() {
}

void stopValve(const char *event, const char *data) { // Function
    digitalWrite(InputValvePin, LOW);
    Particle.publish("tank-full");
}
void startValve(const char *event, const char *data) { // Function
    digitalWrite(InputValvePin, HIGH);
    Particle.publish("tank-filling");
}

Credits

Dominic F.

Dominic F.

1 project • 2 followers
Alex Sagris

Alex Sagris

1 project • 2 followers
3171
Aaron Lutheran

Aaron Lutheran

1 project • 1 follower

Comments

Add projectSign up / Login