#include "LiquidCrystal_I2C.h"
#include "Classes.h"
#include "Servo.h"
// This section is responsible for the connection of the hardware of the circuit
LiquidCrystal_I2C lcd(0x27, 16, 2); // Create an instance of LiquidCrystal_I2C for the LCD
VendingMachine vendingMachine; // Create an instance of VendingMachine
Servo servo; // Create an instance of Servo for controlling the servo motor
unsigned long previousTime = 0; // Variable to store the previous time for interrupt handling
volatile int potentiometerValue = -1; // Volatile variable to store the potentiometer value
int main(void) {
init();
initialize();
while (true) {
cycle();
}
}
// Initialize the hardware and setup
void initialize() {
lcd.init(); // Initialize the LCD display
lcd.backlight(); // Turn on the LCD backlight
Serial.begin(9600); // Initialize the serial communication
setupPinChangeInterrupt(); // Setup pin change interrupt for button input
setupADC(); // Setup ADC for potentiometer input
servo.attach(3); // Attach the servo motor to pin 3
servo.write(0); // Set the initial position of the servo to 0 degrees
setupSwitches(); // Setup switches as inputs with internal pull-up resistors
setupLED(); // Setup the LED pin as output
}
// Perform a single cycle of the vending machine operation
void cycle() {
vendingMachine.printToDisplay(lcd); // Update the display
vendingMachine.handleInputs(); // Handle user inputs
}
// Setup pin change interrupt for handling button input
void setupPinChangeInterrupt() {
PCICR |= (1 << PCIE0); // Enable pin change interrupt for PCINT7:0
PCMSK0 |= (1 << PCINT0); // Enable pin change interrupt for PCINT0 (button input)
}
// Setup ADC for reading the potentiometer input
void setupADC() {
ADCSRA |= (1 << ADEN) | (1 << ADIE); // Enable ADC and ADC interrupt
ADMUX = 0; // Use ADC0 as the analog input channel
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescaler to 128
ADCSRA |= (1 << ADSC); // Start the first ADC conversion
}
// Setup switches as inputs with internal pull-up resistors
void setupSwitches() {
DDRB &= ~(0b00111100); // Set switches as input
PORTB |= (0b00111100); // Enable internal pull-up resistors for switches
}
// Setup LED pin as output
void setupLED() {
DDRD |= (1 << DDD4); // Set LED pin as output
}
// Interrupt Service Routine for pin change interrupt
ISR(PCINT0_vect) {
unsigned long currentTime = millis();
if (currentTime - previousTime > 500) {
vendingMachine.handleInterrupt(); // Handle the button interrupt
previousTime = currentTime;
}
}
// Interrupt Service Routine for ADC conversion complete interrupt
ISR(ADC_vect) {
potentiometerValue = ADC; // Read the ADC value
ADCSRA |= (1 << ADSC); // Start the next ADC conversion
}
// This section is responsible for handling the timer timeout
// Interrupt Service Routine for Timer2 compare match A interrupt
ISR(TIMER2_COMPA_vect) {
vendingMachine.onTimeout(); // Handle the timer timeout
}