#define F_CPU 16000000UL
#include <avr/interrupt.h>
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <avr/eeprom.h> // EEPROM kütüphanesi
#define LCD_CTRL PORTD // We are using port D
#define LCD_EN PD2
#define LCD_RW PD1
#define LCD_RS PD0
#define buzzer_pin PD3 // Buzzer connected to PD7
long t0 = 8388609; // Boş ağırlık (tare) değeri
#define CALIBRATION_FACTOR 0.42// (reading)/(known weight)
#define HX711_DOUT PB4 // Data output pin (Digital Pin 12)
#define HX711_SCK PB5 // Clock pin (Digital Pin 13)
void lcd_command(unsigned char cmd);
void lcd_init(void);
void lcd_data(unsigned char data);
void lcdCommand(char);
void lcdData(char);
void lcd_print(unsigned char *str);
void lcd_gotoxy(unsigned char x, unsigned char y);
void keypadScan(void);
void save_to_eeprom(uint8_t address, char data);
char read_from_eeprom(uint8_t address);
int eeprom_address = 0; // EEPROM adresi için başlangıç değeri
typedef struct {
const char name[15];
int calories;
const char recipe[20]; // Yemek örneği eklendi
} Product;
typedef struct {
const char name[15];
Product products[5];
} Category;
const Category categories[] = {
{"Fruits", {
{"Peach", 59, "Peach Smoothie"},
{"Grape", 62, "Grape Salad"},
{"Strawberry", 53, "Strawberry Parfait"},
{"Pomegranate", 83, "Chicken Salad"},
{"Olive", 115, "Olive Tapenade"}
}},
{"Meat-Dairy", {
{"Ribeye", 402, "Grill-Ribeye Steak"},
{"Beef", 679, "Beef Stew"},
{"Fillet", 170, "Grilled Fillet "},
{"Mince", 250, "Beef Mince Pasta"},
{"Ostrich", 206, "Ostrich Burger"}
}},
{"Vegetables", {
{"Tomato", 22, "Tomato Soup"},
{"Potato", 77, "Mashed Potatoes"},
{"Carrot", 41, "Carrot Cake"},
{"Lettuce", 5, "Lettuce Wrap"},
{"Spinach", 23, "Spinach Salad"}
}},
{"Grains", {
{"Rice", 130, "Vegetable Fried Rice"},
{"Bread", 79, "Avocado Toast"},
{"Pasta", 131, "Spaghetti Carbonara"},
{"Oatmeal", 68, "Oatmeal Bowl"},
{"Quinoa", 120, "Quinoa Salad"}
}},
{"Seafood", {
{"Salmon", 208, "Grilled Salmon"},
{"Tuna", 132, "Tuna Sandwich"},
{"Shrimp", 99, "Shrimp Scampi"},
{"Cod", 82, "Baked Cod"},
{"Crab", 97, "Crab Cakes"}
}},
{"Desserts", {
{"Cake", 260, "Chocolate Cake"},
{"Ice Cream", 207, "Vanilla Ice Cream"},
{"Cookies", 502, "Chocolate Cookies"},
{"Pudding", 140, "Banana Pudding"},
{"Donut", 195, "Glazed Donut"}
}},
{"Beverages", {
{"Water", 0, "Lemon Water"},
{"Tea", 2, "Green Tea"},
{"Coffee", 2, "Black Coffee"},
{"Juice", 112, "Orange Juice"},
{"Milk", 103, "Strawberry Milkshake"}
}},
{"Snacks", {
{"Chips", 152, "Potato Chips"},
{"Popcorn", 106, "Butter Popcorn"},
{"Nuts", 607, "Mixed Nuts"},
{"Pretzels", 195, "Soft Pretzels"},
{"Crackers", 129, "Cheese Crackers"}
}},
{"Condiments", {
{"Ketchup", 112, "Ketchup Meatballs"},
{"Mustard", 66, "Honey Mustard Chicken"},
{"Mayo", 94, "Chicken Salad Sandwich"},
{"Soy Sauce", 9, "Teriyaki Stir-Fry"},
{"BBQ Sauce", 70, "BBQ Chicken Wings"}
}}
};
int main() {
DDRD = 0xFF; // Setting DDRD to output // setting for port D
lcd_init(); // initialization of LCD function
_delay_ms(30);
init_hx711();
buzzer_init();
lcd_init(); // Initialize the LCD
lcd_gotoxy(1, 1);
lcd_print("Categories"); // Print the text
for (int i = 0; i < 9; i++) {
lcd_gotoxy(1, 2);
lcd_print((unsigned char*)categories[i].name); // Display category name
lcd_print(" ");
}
lcdCommand(0x01); // Clear LCD
lcd_gotoxy(1, 1); // Go to the location 1,1 of lcd
lcd_print("Choose a category"); // Print the text
lcd_gotoxy(1, 2); // Go to the location 1,2 of lcd
// Keypad initialization
DDRB = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
DDRC = (0 << 0) | (0 << 1) | (0 << 2) | (0 << 3);
PORTB = (0 << 0) | (0 << 1) | (0 << 2) | (0 << 3);
PORTC = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
while (1) {
keypadScan();
};
return 0;
}
void keypadScan() {
// Store value for column
uint8_t keyPressCodeC = PINC;
DDRC ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
DDRB ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
PORTC ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
PORTB ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
_delay_ms(5);
// Store value for row
int temp = PINB;
uint8_t keyPressCodeR = temp << 4;
// Add value for column and row
uint8_t keyPressCode = keyPressCodeC | keyPressCodeR;
// Comparison and resultant action
char key = '\0'; // Basılan tuşu saklamak için değişken
// Column one
if (keyPressCode == 0b11101110) {
key = '1';
} else if (keyPressCode == 0b11011110) {
key = '4';
} else if (keyPressCode == 0b10111110) {
key = '7';
} else if (keyPressCode == 0b01111110) {
key = '*';
}
// Column two
else if (keyPressCode == 0b11101101) {
key = '2';
} else if (keyPressCode == 0b11011101) {
key = '5';
} else if (keyPressCode == 0b10111101) {
key = '8';
} else if (keyPressCode == 0b01111101) {
key = '0';
}
// Column three
else if (keyPressCode == 0b11101011) {
key = '3';
} else if (keyPressCode == 0b11011011) {
key = '6';
} else if (keyPressCode == 0b10111011) {
key = '9';
} else if (keyPressCode == 0b01111011) {
key = '#';
}
if (key != '\0') { // Eğer geçerli bir tuş basılmışsa
lcd_print(&key); // Tuşu LCD'ye yazdır
save_to_eeprom(eeprom_address++, key); // Tuşu EEPROM'a kaydet ve adresi artır
if (key >= '1' && key <= '9') {
int category = key - '1';
lcdCommand(0x01); // Clear LCD
//lcd_print(" "); // Clear the display
_delay_ms(1); // Increase delay time
lcd_gotoxy(1, 1);
lcd_print((unsigned char*)categories[category].name); // Display category name
for (int i = 0; i < 5; i++) {
lcd_gotoxy(1, 2); // Each product will be displayed on a new line
lcd_print(categories[category].products[i].name);
lcd_print(" - ");
char calories[10];
itoa(categories[category].products[i].calories, calories, 10);
lcd_print(calories);
lcd_gotoxy(1, 3); // Each product will be displayed on a new line
const char* recipe = categories[category].products[i].recipe;
lcd_print(recipe);
lcd_gotoxy(1, 2); // Clear the line for next product
lcd_print(" ");
lcd_gotoxy(1, 3); // Clear the line for next product
lcd_print(" ");
}
lcd_print("Choose a product"); // Print the text
// Wait for user to press a key for product selection
char selectedProductKey = '\0';
while (selectedProductKey == '\0') {
_delay_ms(100); // Small delay for debounce
selectedProductKey = keypadScanForProductSelection();
}
if (selectedProductKey >= '1' && selectedProductKey <= '5') {
int productIndex = selectedProductKey - '1';
lcdCommand(0x01); // Clear LCD
// lcd_print(" "); // Clear the display
_delay_ms(1);
lcd_gotoxy(1, 3); // Clear the line for next product
lcd_print(categories[category].products[productIndex].name); // Display selected product name
float weight = get_weight();
float weight1 = get_weight();
float weight2 = get_weight()/1000;
char weight_str2[20];
dtostrf(weight2, 6, 2, weight_str2); // Ağırlığı string'e dönüştür
lcd_gotoxy(1, 1);
lcd_print("Weight: ");
lcd_print(weight_str2);
// Calculate and display calories
int totalCalories = weight2 * categories[category].products[productIndex].calories*10;
char calories_str[20];
itoa(totalCalories, calories_str, 10);
lcd_gotoxy(1, 2);
lcd_print("Calorie: ");
lcd_print(calories_str);
if (totalCalories > 1000) { // Check if calories exceed 1000
lcd_gotoxy(1, 4);
lcd_print("UNHEALTHY");
buzzer_on(); // Turn on the buzzer
}
}
}
}
}
char keypadScanForProductSelection() {
// Store value for column
uint8_t keyPressCodeC = PINC;
DDRC ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
DDRB ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
PORTC ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
PORTB ^= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
_delay_ms(5);
// Store value for row
int temp = PINB;
uint8_t keyPressCodeR = temp << 4;
// Add value for column and row
uint8_t keyPressCode = keyPressCodeC | keyPressCodeR;
// Comparison and resultant action
char key = '\0'; // Basılan tuşu saklamak için değişken
// Column one
if (keyPressCode == 0b11101110) {
key = '1';
} else if (keyPressCode == 0b11011110) {
key = '4';
} else if (keyPressCode == 0b10111110) {
key = '7';
} else if (keyPressCode == 0b01111110) {
key = '*';
}
// Column two
else if (keyPressCode == 0b11101101) {
key = '2';
} else if (keyPressCode == 0b11011101) {
key = '5';
} else if (keyPressCode == 0b10111101) {
key = '8';
} else if (keyPressCode == 0b01111101) {
key = '0';
}
// Column three
else if (keyPressCode == 0b11101011) {
key = '3';
} else if (keyPressCode == 0b11011011) {
key = '6';
} else if (keyPressCode == 0b10111011) {
key = '9';
} else if (keyPressCode == 0b01111011) {
key = '#';
}
return key;
}
void buzzer_init(void) {
DDRD |= (1 << buzzer_pin); // Set buzzer pin as output
}
void buzzer_on(void) {
PORTD |= (1 << buzzer_pin); // Turn on the buzzer
}
void buzzer_off(void) {
PORTD &= ~(1 << buzzer_pin); // Turn off the buzzer
}
void init_hx711(void) {
DDRB |= (1 << HX711_SCK); // SCK as output
DDRB &= ~(1 << HX711_DOUT); // DOUT as input
}
long read_hx711(void) {
long count = 0;
DDRB |= (1 << HX711_SCK); // Set SCK as output
DDRB &= ~(1 << HX711_DOUT); // Set DOUT as input
// Wait for DOUT to go low
while (PINB & (1 << HX711_DOUT));
for (int i = 0; i < 24; i++) {
PORTB |= (1 << HX711_SCK); // SCK high
_delay_us(1);
count = count << 1;
PORTB &= ~(1 << HX711_SCK); // SCK low
_delay_us(1);
if (PINB & (1 << HX711_DOUT)) {
count++;
}
}
// Set the gain for the next reading
PORTB |= (1 << HX711_SCK); // SCK high
_delay_us(1);
count ^= 0x800000; // Toggle MSB
PORTB &= ~(1 << HX711_SCK); // SCK low
_delay_us(1);
return count;
}
float get_weight(void) {
long raw_value = read_hx711();
float weight = (raw_value - t0) / CALIBRATION_FACTOR;
return weight;
}
void save_to_eeprom(uint8_t address, char data) {
eeprom_update_byte((uint8_t*)address, data);
}
char read_from_eeprom(uint8_t address) {
return eeprom_read_byte((const uint8_t*)address);
}
void lcd_gotoxy(unsigned char x, unsigned char y) {
unsigned char firstCharAdr[] = {0x80, 0xC0, 0x94, 0xD4};
lcdCommand(firstCharAdr[y - 1] + x - 1);
_delay_ms(0.1);
}
void lcd_init(void) {
lcdCommand(0x02); // To initialize LCD in 4-bit mode.
_delay_ms(1);
lcdCommand(0x28); // To initialize LCD in 2 lines, 5X7 dots and 4bit mode.
_delay_ms(1);
lcdCommand(0x01); // Clear LCD
_delay_ms(1);
lcdCommand(0x0E); // Turn on cursor ON
_delay_ms(1);
lcdCommand(0x80); // —8 go to first line and –0 is for 0th position
_delay_ms(1);
return;
}
void lcdCommand(char cmd_value) {
char cmd_value1;
cmd_value1 = cmd_value & 0xF0; // Mask lower nibble
lcd_command(cmd_value1); // Send to LCD
cmd_value1 = ((cmd_value << 4) & 0xF0); // Shift 4-bit and mask
lcd_command(cmd_value1); // Send to LCD
}
void lcdData(char data_value) {
char data_value1;
data_value1 = data_value & 0xF0; // Mask lower nibble
lcd_data(data_value1); // because PD4-PD7 pins are used.
data_value1 = ((data_value << 4) & 0xF0); // Shift 4-bit and mask
lcd_data(data_value1); // Send to LCD
}
void lcd_command(unsigned char cmd) {
LCD_CTRL = cmd;
LCD_CTRL &= ~(1 << LCD_RS); // RS = 0 for command
LCD_CTRL &= ~(1 << LCD_RW); // RW = 0 for write
LCD_CTRL |= (1 << LCD_EN); // EN = 1 for High to Low pulse
_delay_ms(1);
LCD_CTRL &= ~(1 << LCD_EN); // EN = 0 for High to Low pulse
_delay_ms(40);
return;
}
void lcd_data(unsigned char data) {
LCD_CTRL = data;
LCD_CTRL |= (1 << LCD_RS); // RS = 1 for data
LCD_CTRL &= ~(1 << LCD_RW); // RW = 0 for write
LCD_CTRL |= (1 << LCD_EN); // EN = 1 for High to Low pulse
_delay_ms(1);
LCD_CTRL &= ~(1 << LCD_EN); // EN = 0 for High to Low Pulse
_delay_ms(40);
return;
}
void lcd_print(unsigned char *str) {
int i = 0;
while (str[i] != '\0') { // loop will go on till the NULL character in the string
lcdData(str[i]); // sending data on LCD byte by byte
i++;
}
return;
}