/********* Pleasedontcode.com **********

	Pleasedontcode thanks you for automatic code generation! Enjoy your code!

	- Terms and Conditions:
	You have a non-exclusive, revocable, worldwide, royalty-free license
	for personal and commercial use. Attribution is optional; modifications
	are allowed, but you're responsible for code maintenance. We're not
	liable for any loss or damage. For full terms,
	please visit pleasedontcode.com/termsandconditions.

	- Project: **Charging System**
	- Source Code NOT compiled for: Arduino Uno
	- Source Code created on: 2024-11-06 01:12:07

********* Pleasedontcode.com **********/

/****** SYSTEM REQUIREMENTS *****/
/****** SYSTEM REQUIREMENT 1 *****/
	/* charging station */
/****** END SYSTEM REQUIREMENTS *****/

/* START CODE */

/****** DEFINITION OF LIBRARIES *****/
#include <Wire.h> // Added for I2C communication
#include <LiquidCrystal_I2C.h> // Library for I2C LCD

/****** FUNCTION PROTOTYPES *****/
void setup(void);
void loop(void);

/****** DEFINITION OF LIBRARIES CLASS INSTANCES*****/
LiquidCrystal_I2C lcd(0x27, 20, 4); // Set the I2C address of the LCD

// Pin definitions
const int relayPins[4] = {2, 3, 4, 5}; // Relay pins
const int buttonPins[4] = {6, 7, 8, 9}; // Button pins
const int buzzerPin = 10; // Buzzer pin
const int coinSlotPin = 11; // Coin slot pin

// Timing variables
unsigned long relayEndTimes[4] = {0, 0, 0, 0}; // End time for each relay
const int chargeTimePerCoin = 120; // 2 minutes per coin in seconds
#define Relay_On(b) digitalWrite(relayPins[b], LOW)
#define RelayOff(b) digitalWrite(relayPins[b], HIGH)

void setup(void)
{
	// put your setup code here, to run once:
	lcd.init(); // Initialize the LCD
	lcd.backlight(); // Turn on the backlight

	// Set relay and button pins as output/input
	for (int i = 0; i < 4; i++) {
		digitalWrite(relayPins[i], HIGH); // Ensure relays are off
		pinMode(relayPins[i], OUTPUT);
		pinMode(buttonPins[i], INPUT_PULLUP); // Buttons are active LOW
	}
	pinMode(buzzerPin, OUTPUT);
	pinMode(coinSlotPin, INPUT_PULLUP); // Use internal pull-up resistor

	// Display initial message on the LCD
	lcd.setCursor(0, 0);
	lcd.print("E-Piso Charger");
	lcd.setCursor(0, 1);
	lcd.print("2 mins/PHP    C: 0");
	lcd.setCursor(0, 2);
	lcd.print("1|00:00 2|00:00");
	lcd.setCursor(0, 3);
	lcd.print("3|00:00 4|00:00");
}

void loop(void)
{
	// put your main code here, to run repeatedly:
	const uint32_t tausend = 1000UL;
	static uint32_t CoinDelay = 0;
	static int coinsInserted = 0;
	static uint32_t lastUpdateTime = 0;

	// Check for coin insertion
	if (digitalRead(coinSlotPin) == LOW)
		if (millis() - CoinDelay >= 300) { // Confirm coin detection
			coinsInserted++;
			lcd.setCursor(17, 1);
			lcd.print(coinsInserted > 99 ? 99 : coinsInserted);
			tone(buzzerPin, tausend, 100); // Beep the buzzer
			CoinDelay = millis();
		}

	for (int i = 0; i < 4; i++) {
		// Check buttons for starting charging
		if (coinsInserted > 0 && digitalRead(buttonPins[i]) == LOW) {
			Relay_On(i); // Turn on the relay
			if (!relayEndTimes[i]) relayEndTimes[i] = millis();
			relayEndTimes[i] += tausend * coinsInserted * chargeTimePerCoin; // Set the end time for the relay based on the number of coins inserted
			coinsInserted = 0; // Reset the coin count after starting the charging
			lcd.setCursor(17, 1);
			lcd.print("0 ");
		}
		// Update relay timing
		if (relayEndTimes[i] > 0)
			if (millis() >= relayEndTimes[i]) {
				RelayOff(i); // Turn off the relay
				relayEndTimes[i] = 0; // Reset the relay end time
			}
	}

	// Only update the LCD every second
	if (millis() - lastUpdateTime >= tausend) {
		char buffer[6];
		// Update only if values have changed
		for (uint8_t i = 0; i < 4; i++) {
			uint16_t remainingTime = relayEndTimes[i] > 0 ? (relayEndTimes[i] - millis()) / tausend : 0;
			uint8_t row = i < 2 ? 2 : 3;
			uint8_t col = i % 2 == 0 ? 2 : 10;
			lcd.setCursor(col, row);
			sprintf(buffer, "%02u:%02u", remainingTime / 60, remainingTime % 60);
			lcd.print(buffer);
		}
		lastUpdateTime += tausend;
	}
}

/* END CODE */