// ATmega32 - Offline Airplane Boarding System
// No defines, all register names as-is, no libraries used
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
// List of valid 3-digit boarding IDs
char valid_ids[][4] = {"100", "101", "102", "103", "104", "200", "201", "202",
"203", "204"};
int total_boarded = 0; // Counter for total people boarded
int flight_crew[5] = {0, 0, 0, 0, 0}; // Flags to track crew members (IDs 00-
04)
// ---------------------------- LCD Functions (4-bit mode on PORTC)
----------------------------
// Send a command to LCD we will send the command 4 bit at a time (nibbles)
void lcd_cmd(unsigned char cmd) { //this functions sends commands to the lcd like
clear display etc
PORTC = (PORTC & 0x0F) | (cmd & 0xF0); // Send higher nibble by masking lower
nibble
PORTC &= ~(1 << 0); // RS = 0 (command mode) rests register select pin to 0
telling the lcd we are sending commands not data
PORTC |= (1 << 1); // EN = 1 sets enable pin to 1 this tells the lcd to
process the command/data
_delay_ms(1); //ensures the lcd has enough time to process the data
PORTC &= ~(1 << 1); // EN = 0 sets the en pin to 0,tells lcd to finish the
command cycle
_delay_ms(2); //gives lcd time to process the command
PORTC = (PORTC & 0x0F) | (cmd << 4); // Send lower nibble
PORTC |= (1 << 1);//enables the en pin to 1,tells lcd to process command
_delay_ms(1);//gives time for lcd
PORTC &= ~(1 << 1); //enables en pin to 0,tells lcd to finish the command
_delay_ms(2); //gives time for the lcd to process
}
// Display a single character
void lcd_char(unsigned char data) {//this function sends data to the lcd(characters
)
PORTC = (PORTC & 0x0F) | (data & 0xF0); // Send higher nibble
PORTC |= (1 << 0); // RS = 1 (data mode) //sets rs into 1 indicating were
sending character data not a command
PORTC |= (1 << 1); // EN = 1 , this sets the enable pin to 1 to make the lcd
process the data
_delay_ms(1); // gives enough time for the lcd to process
PORTC &= ~(1 << 1); // EN = 0 this sets the enable pin to 0 tells the lcd to
complete the processing
_delay_ms(2); //gives enough time for lcd to process the data
PORTC = (PORTC & 0x0F) | (data << 4); // Send lower nibble
PORTC |= (1 << 1); //sets enable pin to 1 tells lcd to process the data
_delay_ms(1);//gives enough time for lcd to process data
PORTC &= ~(1 << 1); //sets enable pin to 0 ,tells lcd to complete the operation
_delay_ms(2); //gives enough time for lcd to process
}
// Initialize LCD
void lcd_init() { //function used to Initialize the lcd prior anything
DDRC = 0xFF; // Set PORTC as output because we will display so its output
_delay_ms(20);//gives enough time for lcd to process
lcd_cmd(0x02); // 4-bit mode this sets the lcd to 4 bit mode
lcd_cmd(0x28); // 2 lines, 5x8 matrix
lcd_cmd(0x0C); // Display on, cursor off for a cleaner look we turned off the
visible cursor
lcd_cmd(0x06); // Increment cursor to the right
lcd_cmd(0x01); // Clear display
_delay_ms(2); //giving enough time for the lcd to process
}
// Display a string
void lcd_str(char *str) {
while (*str) {
lcd_char(*str++);
}
}
// Clear LCD screen
void lcd_clear() {
lcd_cmd(0x01);
_delay_ms(2);
}
// Set cursor to specific row and column
void lcd_set_cursor(unsigned char row, unsigned char col) {
lcd_cmd(0x80 + row * 0x40 + col);
}
// ---------------------------- Keypad Functions (PORTD)
----------------------------
char keypad[4][3] = {{'1','2','3'},{'4','5','6'},{'7','8','9'},{'*','0','#'}};
// Set rows as output, columns as input
void keypad_init() {
DDRD = 0xF0;
PORTD = 0xFF;
}
// Scan keypad and return pressed key
char get_key() {
for (int row = 0; row < 4; row++) {
DDRD = 0xF0;
PORTD = ~(1 << (row + 4));
_delay_ms(5);
for (int col = 0; col < 3; col++) {
if (!(PIND & (1 << col))) {
while (!(PIND & (1 << col)));
return keypad[row][col];
}
}
}
return 0;
}
// Read 3-digit ID from keypad
void get_id(char *buffer) {
int i = 0;
char key;
while (i < 3) {
key = get_key();
if (key >= '0' && key <= '9') {
buffer[i++] = key;
lcd_char(key); // Show digit on LCD
}
}
buffer[3] = '\0'; // Null-terminate string
}
// ---------------------------- PWM for Servo (Timer0, PB3)
----------------------------
// Setup PWM
void pwm_init() {
DDRB |= (1 << 3); // Set PB3 (OC0) as output
TCCR0 |= (1 << WGM00) | (1 << WGM01) | (1 << COM01) | (1 << CS01); // Fast PWM,
non-inverting, clk/8
}
// Open gate by setting PWM duty
void servo_open() {
OCR0 = 19; // Approx. 2ms pulse
}
// Close gate by setting PWM duty
void servo_close() {
OCR0 = 5; // Approx. 1ms pulse
}
// ---------------------------- ADC Functions ----------------------------
// Initialize ADC
void adc_init() {
ADMUX = 0x00; // Select channel 0
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, clk/8
}
// Read ADC value from given channel
unsigned int adc_read(unsigned char ch) {
ADMUX = (ADMUX & 0xF0) | ch;
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC)); // Wait for conversion
return ADC;
}
// Convert ADC value to temperature (assuming LM35)
unsigned char read_temp() {
unsigned int raw = adc_read(0);
return (raw * 500UL) / 1024;
}
// ---------------------------- Boarding Logic ----------------------------
// Check if entered ID is valid
unsigned char is_valid_id(char *id) {
for (int i = 0; i < sizeof(valid_ids)/4; i++) {
if (strcmp(id, valid_ids[i]) == 0)
return 1;
}
return 0;
}
// Mark flight crew member as onboard
void update_crew_status(char *id) {
if (id[1] == '0' && id[2] >= '0' && id[2] <= '4') {
int crew_id = id[2] - '0';
flight_crew[crew_id] = 1;
}
}
// Check if all 5 flight crew are onboard
unsigned char all_crew_present() {
for (int i = 0; i < 5; i++) {
if (!flight_crew[i]) return 0;
}
return 1;
}
// ---------------------------- Main Program ----------------------------
int main(void) {
DDRB |= (1 << 1); // Buzzer output on PB1
DDRB &= ~(1 << 0); // Safety sensor input on PB0
pwm_init();
adc_init();
lcd_init();
keypad_init();
lcd_str("Boarding System");
_delay_ms(1000);
lcd_clear();
while (1) {
char id[4];
lcd_str("Enter ID:");
lcd_set_cursor(1, 0);
get_id(id);
lcd_clear();
// Check motor temperature
if (read_temp() > 50) {
PORTB |= (1 << 1); // Activate buzzer
lcd_str("Overheat!");
_delay_ms(1000);
PORTB &= ~(1 << 1); // Turn off buzzer
lcd_clear();
continue;
}
// Check if ID is valid
if (is_valid_id(id)) {
update_crew_status(id);
total_boarded++;
lcd_str("Welcome!");
_delay_ms(1000);
lcd_clear();
// Meal selection prompt
lcd_str("1-Veg 2-Chkn");
lcd_set_cursor(1, 0);
lcd_str("3-Beef 4-Spec");
_delay_ms(1000);
char meal = get_key();
lcd_clear();
lcd_str("Meal Chosen: ");
lcd_char(meal);
_delay_ms(1000);
// Check safety sensor before opening gate
if (!(PINB & (1 << 0))) {
servo_open();
_delay_ms(2000);
servo_close();
}
} else {
lcd_str("Invalid ID");
_delay_ms(1000);
lcd_clear();
}
}
}