#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// Define I2C LCD address
#define LCD_I2C_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
#define NUM_ITEMS 5
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] =
{
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 5, 4, 3, 2 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 9, 8, 7, 6 }; // Pins connected to R1, R2, R3, R4
int item_days[NUM_ITEMS] = {0, 0, 0, 0, 0}; // Day counter for each item
const char* item_names[NUM_ITEMS] = {"Milk", "Eggs", "Cheese", "Yogurt", "Vegetables"};
int item_expiry_days[NUM_ITEMS] = {3, 5, 7, 4, 6}; // Expiry days for each item
bool items[NUM_ITEMS] = {false, false, false, false, false};
int item_no;
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, LCD_COLUMNS, LCD_LINES);
enum State
{
WAITING,
DELETE_PENDING,
DISPLAY_PENDING
};
State current_state = WAITING;
unsigned long previousMillis = 0; // Stores the last time the counter was updated
const long interval = 6000; // Simulate one day in milliseconds (for testing)
void setup()
{
_delay_ms(250);
// Init
lcd.init();
lcd.backlight();
// Set LED and buzzer pins as output
DDRB |= (1 << PB2); // Green LED on pin 10
DDRB |= (1 << PB3); // Red LED on pin 11
DDRB |= (1 << PB4); // Buzzer on pin 12
// Set button pin as input
DDRB &= ~(1 << PB5); // Pin 13 as input
lcd.clear();
}
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
increment_days();
}
check_items();
check_leds();
}
void check_items()
{
char key = keypad.getKey();
switch (current_state)
{
case WAITING:
if (key == '*')
{
current_state = DELETE_PENDING;
}
else if (key == '#')
{
current_state = DISPLAY_PENDING;
}
else if (key >= '1' && key <= '5')
{
item_no = key - '1';
add_item(item_no);
}
break;
case DELETE_PENDING:
if (key >= '1' && key <= '5')
{
item_no = key - '1';
delete_item(item_no);
current_state = WAITING;
}
else if (key != NO_KEY)
{
current_state = WAITING; // Reset state if any other key is pressed
}
break;
case DISPLAY_PENDING:
if (key >= '1' && key <= '5')
{
item_no = key - '1';
display_days(item_no);
current_state = WAITING;
}
else if (key != NO_KEY)
{
current_state = WAITING; // Reset state if any other key is pressed
}
break;
}
}
void add_item(int item_no)
{
item_days[item_no] = 0; // Reset days counter for the item
items[item_no] = true; // Mark item as added
lcd.setCursor(0, 0);
lcd.print(item_names[item_no]);
lcd.setCursor(0, 1);
if (item_no == 1 || item_no == 4)
{
lcd.print("are added!");
} else {
lcd.print("is added!");
}
_delay_ms(1000);
lcd.clear();
}
void delete_item(int item_no)
{
items[item_no] = false; // Mark item as deleted
lcd.setCursor(0, 0);
lcd.print(item_names[item_no]);
lcd.setCursor(0, 1);
if (item_no == 1 || item_no == 4)
{
lcd.print("are deleted!");
} else {
lcd.print("is deleted!");
}
item_days[item_no] = 0; // Reset days counter
_delay_ms(1000);
lcd.clear();
}
void display_days(int item_no)
{
lcd.setCursor(0, 0);
lcd.print(item_names[item_no]);
lcd.setCursor(0, 1);
lcd.print("Days: ");
lcd.print(item_days[item_no]);
_delay_ms(1000);
lcd.clear();
}
void increment_days()
{
for (int i = 0; i < NUM_ITEMS; i++)
{
if (items[i]) // Only increment days for items that have been added
{
item_days[i]++;
}
}
}
void check_leds()
{
// Check if the button is pressed
if (PINB & (1 << PB5)) // Assuming the button pulls the pin high when pressed
{
bool item_expired = false;
lcd.clear();
for (int i = 0; i < NUM_ITEMS; i++)
{
if (items[i] && item_days[i] >= item_expiry_days[i]) // Use the custom expiration period
{
item_expired = true;
// Turn on red LED
PORTB |= (1 << PB3);
// Turn on buzzer
PORTB |= (1 << PB4);
lcd.setCursor(0, 0);
lcd.print(item_names[i]);
lcd.setCursor(0, 1);
lcd.print("is expired!");
_delay_ms(2000);
lcd.clear();
}
}
if (item_expired == true)
{
// Turn off green LED
PORTB &= ~(1 << PB2); // Check if the green led is on and make it off
}
else
{
// Turn on green LED
PORTB |= (1 << PB2);
lcd.setCursor(0, 0);
lcd.print("All items are");
lcd.setCursor(0, 1);
lcd.print("fine!");
_delay_ms(2000);
lcd.clear();
// Turn off red LED
PORTB &= ~(1 << PB3);
// Turn off buzzer
PORTB &= ~(1 << PB4);
}
}
else
{
// Turn off both LEDs and buzzer if the button is not pressed
PORTB &= ~(1 << PB2);
PORTB &= ~(1 << PB3);
PORTB &= ~(1 << PB4);
lcd.clear();
}
}