// Libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <EEPROM.h>
// Initialize the LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x32 for a 16 chars and 2 line display
// Define servo pins
#define SERVO_PIN_1 9
#define SERVO_PIN_2 10
#define SERVO_PIN_3 11
// Create an array to hold servo objects
Servo servo[3];
// Define other pins
#define coinSlot 2
#define buzzer 13
#define button1 4
#define button2 7
#define button3 8
#define changePricesButton 12 // New button for transitioning to phase 2
char lcdBuffer[16];
char prefix[] = "Bal: Php";
volatile int pulse = 0; // Make pulse volatile for use in ISR
char ZZ[] = ".00";
int phase = 1;
int previousPulse = 0; // Variable to store previous pulse value
// Define variant prices
int prices[] = {5, 8, 10}; // Changed from const to allow modification
const int buttons[] = {button1, button2, button3};
const int servoPin[] = {SERVO_PIN_1, SERVO_PIN_2, SERVO_PIN_3};
// Function prototypes
void setup();
void loop();
void insertcoinpage(); // prints "insert coin" on Row 1
void startlcd(); // initializes LCD i2c
void printCredits(); //print updated credits
void dispenseVariant(int index); // dispensing function for all products
void transitionToPhase1(); // Go to phase 1
void transitionToPhase2(); // Go to phase 2
void Buzz(); // buzz for "n" milliseconds
void BuzzLow(); // buzz low for "n" milliseconds
void changePrices(); //Directs to change prices Mode or Admin mode
void savePricesToEEPROM(); // save prices to eeprom, this is used inside the change proces function
void loadPricesFromEEPROM(); //Load saved prices from eeprom
void coinISR(); // ISR function (Interrupt Service Routine, this function is executed once interrupt button is pressed)
// Setup, initialize everything here
void setup()
{
startlcd();
pinMode(coinSlot, INPUT);
pinMode(changePricesButton, INPUT_PULLUP);
for (int i = 0; i < 3; i++) {
pinMode(buttons[i], INPUT_PULLUP);
}
// Attach and set initial position of servos to 0 degrees using a loop
for (int i = 0; i < 3; i++) {
servo[i].attach(servoPin[i]);
servo[i].write(0); // Set initial position to 0 degrees
}
int prices[] = {5, 8, 10}; // REMOVE THIS AFTER FINISHING THE CODE, everytime the arduino starts, this is the defualt price, so the eeprom prices is deleted when restarted
savePricesToEEPROM(); // REMOVE THIS AFTER FINISHING THE CODE, everytime the arduino starts, this is the defualt price, so the eeprom prices is deleted when restarted
loadPricesFromEEPROM();
insertcoinpage();
// Attach interrupt to the coinSlot pin
attachInterrupt(digitalPinToInterrupt(coinSlot), coinISR, RISING); //always update credits from coin slot
}
// MAIN LOOP
void loop() {
if (phase == 1) {
printCredits(); // Always print updated credits
for (int i = 0; i < 3; i++) {
dispenseVariant(i);
}
if (digitalRead(changePricesButton) == LOW) { // Check if the change prices button is pressed
transitionToPhase2();
}
}
if (phase == 2) {
changePrices();
savePricesToEEPROM();
transitionToPhase1();
}
}
// Functions
void insertcoinpage()
{
lcd.setCursor(0, 0);
lcd.print(" ");
delay(200);
lcd.setCursor(0, 0);
lcd.print(" Insert Coins");
delay(100);
printCredits();
}
void startlcd()
{
lcd.init();
lcd.backlight();
lcd.clear();
}
void printCredits()
{
if (pulse > previousPulse) {
Buzz();
previousPulse = pulse;
}
sprintf(lcdBuffer, "%s %d%s", prefix, pulse, ZZ);
lcd.setCursor(0, 1);
lcd.print(lcdBuffer);
}
void dispenseVariant(int index)
{
if (digitalRead(buttons[index]) == LOW) {
if (pulse >= prices[index]) {
Buzz();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Dispensing");
lcd.setCursor(0, 1);
lcd.print(" Product ");
lcd.print(index + 1);
delay(500);
for (int i = 0; i < 2; i++) {
Buzz();
delay(500);
}
pulse -= prices[index];
previousPulse = pulse;
activateServo(servo[index]);
delay(500);
lcd.clear();
insertcoinpage();
printCredits();
delay(100);
for (int i = 0; i < 2; i++) {
Buzz();
delay(100);
}
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Insufficient");
lcd.setCursor(0, 1);
lcd.print(" Balance ");
for (int i = 0; i < 2; i++) { // Loop 10 times
BuzzLow();
delay(80);
}
delay(500);
lcd.clear();
insertcoinpage();
printCredits();
delay(100);
}
}
}
void transitionToPhase1()
{
lcd.clear();
phase = 1;
insertcoinpage();
}
void transitionToPhase2()
{
phase = 2;
lcd.clear();
loadPricesFromEEPROM(); // Load prices from EEPROM
}
void activateServo(Servo& servo)
{
servo.write(90); // Example position for activation
delay(500); // Time for the servo to stay in position
servo.write(0); // Return to initial position
}
void Buzz()
{
tone(buzzer, 3000); // Send 3 kHz tone to pin 9
delay(30);
noTone(buzzer); // Stop the tone
}
void BuzzLow()
{
tone(buzzer, 250); // Send 3 kHz tone to pin 9
delay(30);
noTone(buzzer); // Stop the tone
}
void changePrices()
{
lcd.clear();
delay(200);
lcd.setCursor(0, 0);
lcd.print("Please wait...");
for (int i = 0; i < 2; i++) { // Loop 10 times
Buzz();
delay(80);
}
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Entering Admin");
lcd.setCursor(0, 1);
lcd.print("Mode...");
for (int i = 0; i < 2; i++) { // Loop 10 times
Buzz();
delay(80);
}
delay(2000);
for (int i = 0; i < 3; i++) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("P");
lcd.print(i + 1);
lcd.print(" Price: ");
lcd.print(prices[i]);
Buzz();
while (true) {
if (digitalRead(button1) == LOW) {
Buzz();
prices[i] -= 1;
delay(50); // Debounce delay
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("P");
lcd.print(i + 1);
lcd.print(" Price: ");
lcd.print(prices[i]);
}
if (digitalRead(button2) == LOW) {
Buzz();
prices[i] += 1;
delay(50); // Debounce delay
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("P");
lcd.print(i + 1);
lcd.print(" Price: ");
lcd.print(prices[i]);
}
if (digitalRead(button3) == LOW) {
Buzz();
delay(500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Saving price...");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Prices saved");
delay(500);
lcd.clear();
for (int i = 0; i < 2; i++) { // Loop 10 times
Buzz();
delay(80);
}
break;
}
}
}
}
void savePricesToEEPROM()
{
for (int i = 0; i < 3; i++) {
EEPROM.write(i, prices[i]);
}
}
void loadPricesFromEEPROM()
{
for (int i = 0; i < 3; i++) {
prices[i] = EEPROM.read(i);
}
}
// ISR to increment pulse
void coinISR()
{
pulse += 1;
delayMicroseconds(30000);
}