#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // Initialize 20x4 LCD
#define buzzer 45
// configure keypad (from LAB03)
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] = {22, 24, 26, 28} ;
const byte colPins[COLS] = {30, 32, 34, 36} ;
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int animationStep = -2000; // Initial animation step with larger waves
unsigned long startTime;
const unsigned long animationDuration = 5000; // Duration of animation in milliseconds
bool menuDisplayed = false; // Track if the menu is currently displayed or not
bool animationRunning = true; // Flag to control animation running
void animationSetup() {
for (int i = 0; i < 8; i++) {
byte charLine[8];
for (int j = 0; j < 8; j++) {
if (j > i) charLine[7 - j] = B00000;
else charLine[7 - j] = B11111;
}
lcd.createChar(i, charLine);
}
}
void setup() {
//Initialize buzzer
pinMode(buzzer, OUTPUT);
Serial.begin(9600);
lcd.init();
lcd.backlight();
animationSetup();
startTime = millis(); // Record the start time
// Display the text centered
String text1 = "Welcome to Flow Rate";
String text2 = "Control System";
int length1 = text1.length();
int length2 = text2.length();
int startPosition1 = (20 - length1) / 2; // Calculate starting column position to center the first line
int startPosition2 = (20 - length2) / 2; // Calculate starting column position to center the second line
lcd.setCursor(startPosition1, 0); // Set cursor to the first row, starting from calculated position
lcd.print(text1);
lcd.setCursor(startPosition2, 1); // Set cursor to the second row, starting from calculated position
lcd.print(text2);
}
void displayMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("A: Continuous");
lcd.setCursor(0, 1);
lcd.print("B: Rotary Adj.");
lcd.setCursor(0, 2);
lcd.print("C: Automatic");
lcd.setCursor(0, 3);
lcd.print("D: Save mode & Start");
menuDisplayed = true;
}
void stopAnimation() {
animationRunning = false;
}
void animation3() {
if (!animationRunning) return; // If animation not running, exit
byte character[2];
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - startTime;
if (elapsedTime >= animationDuration) {
// Stop the animation after 5 seconds
animationRunning = false;
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("Flow Rate");
lcd.setCursor(3, 1);
lcd.print("Control System");
lcd.setCursor(1, 2);
lcd.print("Press '*' to Start");
lcd.setCursor(3, 3);
lcd.print("and Select Mode");
return;
}
for (int column = 0; column < 20; column++) {
// Adjusted coefficients for smooth wave animation
int actualValue = cos(animationStep * (0.1 + column * 0.01)) * 4 + 9;
if (actualValue == 13) {
character[0] = byte(255);
character[1] = byte(255);
}
else if (actualValue > 9) {
character[0] = byte(actualValue - 10);
character[1] = byte(255);
}
else if (actualValue == 9) {
character[0] = byte(32);
character[1] = byte(255);
}
else if (actualValue == 8) {
character[0] = byte(32);
character[1] = byte(255);
}
else if (actualValue == 0) {
character[0] = byte(32);
character[1] = byte(32);
}
else {
character[0] = byte(32);
character[1] = byte(actualValue - 1);
}
lcd.setCursor(19 - column, 2); // Adjust cursor position for 20x4 LCD (starting from row 3)
lcd.write(character[0]);
lcd.setCursor(19 - column, 3); // Adjust cursor position for 20x4 LCD (starting from row 4)
lcd.write(character[1]);
}
animationStep++;
}
void loop() {
animation3();
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
stopAnimation(); // Stop the animation
}
}
}
}