#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Encoder.h> // Include the Rotary Encoder library
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // Initialize 16x2 LCD
#define buzzer 3
#define motorDriver 4
#define sensor 2
byte sensorInt = 0;
volatile long pulse;
unsigned long lastTime;
float volume;
float desiredFlowRate = 4.5; // Default desired flow rate
float desiredVolume = 0.0; // Variable to store the desired volume set by the user
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}};
const byte rowPins[ROWS] = {13, 12, 11, 10};
const byte colPins[COLS] = {9, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
unsigned long startTime;
bool menuDisplayed = false; // Track if the menu is currently displayed or not
char selectedMode = ' '; // Default selected mode is none
bool flowDetectionRunning = false; // Flag to indicate if flow detection is running
void setup()
{
pinMode(buzzer, OUTPUT);
pinMode(sensor, INPUT);
pinMode(motorDriver, OUTPUT);
lcd.init();
lcd.backlight();
startTime = millis(); // Record the start time
//Liters per Minute
pulse=0;
attachInterrupt(sensorInt, increase, FALLING);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kontrol Aliran");
lcd.setCursor(0, 1);
lcd.print("Tekan * ");
}
void displayMenu()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tekan B ");
lcd.setCursor(0, 1);
lcd.print("Untuk Melanjutkan");
menuDisplayed = true;
}
void loop() {
char key = keypad.getKey(); // Get the key pressed
if (key != NO_KEY) {
tone(buzzer, 1300, 50); // Play tone for keypress
if (key == '*') { // If asterisk (*) key is pressed
if (!menuDisplayed) { // If menu is not already displayed
displayMenu(); // Display the menu
}
} else if (key == '#') { // If '#' key is pressed
} else if (menuDisplayed) { // If menu is displayed
if (key >= 'A' && key <= 'B' && selectedMode == ' ') { // If a valid mode key is pressed and no mode is currently running
selectedMode = key;
switch (selectedMode) {
case 'B':
modeC(); // Enter Mode C
break;
}
} else if (selectedMode != ' ') {
}
}
}
}
void displayModeC(float actualVolume)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Point:");
lcd.setCursor(0, 1);
lcd.print("Actual: ");
lcd.print(actualVolume, 1);
lcd.print(" mL");
}
void modeC()
{
displayModeC(0.0);
float setVolume = getSetVolume();
if (flowDetectionRunning)
{
detectFlow(setVolume);
}
}
float getSetVolume() {
// Get the desired volume from the user using the keypad
// This function should wait until the user presses '*' to confirm the input
float volume = 0.0;
bool volumeEntered = false;
while (!volumeEntered) {
char key = keypad.getKey();
if (key >= '0' && key <= '9') {
volume = volume * 10 + (key - '0');
lcd.setCursor(10, 0);
lcd.print(volume);
} else if (key == '*') {
volumeEntered = true;
flowDetectionRunning = true; // Set flow detection flag
}
}
return volume;
}
void detectFlow(float setVolume) {
unsigned long lastTime = 0;
unsigned long interval = 1000; // Interval for flow rate calculation (in milliseconds)
unsigned long totalPulses = 0;
float totalVolume = 0.0;
lcd.setCursor(8, 1);
lcd.print(" "); // Clear previous value
while (true) {
unsigned long currentTime = millis();
if (currentTime - lastTime >= interval)
{
detachInterrupt(sensorInt);
float flowRate = (pulse - totalPulses) * 60.0 / (interval * 7.5); // Assuming 7.5 pulses per liter
totalPulses = pulse;
lastTime = currentTime;
totalVolume += flowRate / 1000.0; // Convert flow rate from L/min to L/s, then accumulate
lcd.setCursor(8, 1);
lcd.print(totalVolume, 1); // Print actual accumulated volume with 1 decimal place
lcd.print(" mL");
// Check if accumulated volume meets or exceeds set volume
if (totalVolume >= setVolume) { //Jika volume yang di terima melebihi volume set point maka pompa berhenti
analogWrite(motorDriver, 0); // Stop the pump
flowDetectionRunning = false; // Reset flow detection flag
menuDisplayed = false; // Return to mode selection
break;
}
pulse=0;
attachInterrupt(sensorInt, increase, FALLING);
}
}
}
void increase()
{
pulse++;
}