#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
int pinRedLED = 5;
int pinGreenLED = 13;
int pinFlowSensor = 0;
int pinButton = 4;
int pinUssTrig = 3;
int pinUssEcho = 2;
int pinRelayPump = 1;
bool objectDetected = false;
bool buttonPressed = false;
bool isHot = false;
bool isPumpRunning = false;
int step = 0;
double volume = 0.0;
// time
unsigned long startMillis;
// CONSTANTS
const float BETA = 3950; // should match the Beta Coefficient of the thermistor
const double flowRate = 0.1; // L/s
const double stopThreshold = 0.1; // L/s
const double hotTemperature = 40;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// setup LCD
lcd.begin(16, 2);
// setup LED
pinMode(pinGreenLED, OUTPUT);
pinMode(pinRedLED, OUTPUT);
// setup button
pinMode(pinButton, INPUT);
// setup ultrasonic sensor (HC-SR04)
pinMode(pinUssTrig, OUTPUT);
pinMode(pinUssEcho, INPUT);
// setup pump relay
pinMode(pinRelayPump, OUTPUT);
// finish setup
// set idle screen
updateDisplay("idle");
// set step to 1
step = 1;
}
int getDistance() {
// Start a new measurement:
digitalWrite(pinUssTrig, HIGH);
delayMicroseconds(10);
digitalWrite(pinUssTrig, LOW);
// Read the result:
int duration = pulseIn(pinUssEcho, HIGH);
int distance = duration / 58;
// Serial.print("Distance in CM: ");
// Serial.println(distance);
return distance;
}
double getTemperature() {
// NTC Temperature Sensor
int analogValue = analogRead(A0);
double celsius = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
return celsius;
}
void setPump(bool state) {
if(state) {
digitalWrite(pinRelayPump, HIGH);
} else {
digitalWrite(pinRelayPump, LOW);
}
isPumpRunning = state;
}
void updateVolume() {
double newVolume = volume + ((millis() - startMillis) / 1000.0 * flowRate);
volume = newVolume;
}
void updateDisplay(String state) {
// clear display
lcd.clear();
if(state == "idle") {
lcd.print("Place container");
}
if(state == "detected") {
lcd.print("Press Start");
}
if(state == "dispensing") {
lcd.print("Dispensing...");
}
if(state == "done") {
lcd.print("Done!");
}
// Warning
if(state == "hot") {
lcd.print("STOP! Water too hot!");
}
}
void updateSerial() {
Serial.print(volume);
Serial.print(",");
Serial.println(getTemperature());
}
void loop() {
// put your main code here, to run repeatedly:
// if on step 4, return to step 1
if(step == 4) {
step = 1;
updateDisplay("idle");
}
// check if water is too hot
if(!isHot && getTemperature() > hotTemperature) {
// if temperature is too hot
isHot = true;
step = 1;
digitalWrite(pinRedLED, HIGH);
digitalWrite(pinGreenLED, LOW);
updateDisplay("hot");
} else if(isHot && getTemperature() < hotTemperature) {
// if temperature is normal
isHot = false;
digitalWrite(pinRedLED, LOW);
updateDisplay("idle");
}
// Step 1: detect container
objectDetected = getDistance() < 10 && !isHot; // Don't scan if temperature is hot
if(objectDetected && step < 2) {
step = 2;
digitalWrite(pinGreenLED, HIGH);
updateDisplay("detected");
} else if(!objectDetected && !isHot && step > 1) {
step = 1;
digitalWrite(pinGreenLED, LOW);
updateDisplay("idle");
}
// Step 2: wait for button press
buttonPressed = digitalRead(pinButton);
if(step == 2 && buttonPressed) {
step = 3;
}
// Step 3: start dispensing water and measure water volume
if(step == 3) {
if(!isPumpRunning) {
setPump(true);
startMillis = millis();
updateDisplay("dispensing");
}
updateVolume();
// Step 4: stop dispensing when volume is above threshold
if(volume >= stopThreshold / 1000) {
setPump(false);
step = 4;
volume = 0;
updateDisplay("done");
}
}
updateSerial();
if(step == 1)
delay(1000);
else if(step == 4)
delay(3000);
}