#include <Wire.h>
#include <Button2.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
#define COIN_PULSE_PIN 2 //pin2 or pin3 only if uno,nano,pro mini //connect to universal coin acceptor
#define BUZZER_PIN 13 //connect to buzzer
#define RELAY_PIN 3 //connect to relay input
#define RELAY_PIN2 5 //connect to relay input shampoo
#define SECONDS_PER_PISO 36
#define SECONDS_PER_PISO_SHAMPOO 2
#define SHAMPOO_PIN 7
#define PAUSE_PIN 6
#define WASH_PIN 4
/////////////////////////////////////////////////////////////////
Button2 shampooButton, washButton, pauseButton;
/////////////////////////////////////////////////////////////////
volatile unsigned long timer1, timer2, soundTimer;
//variables to keep track of the timing of recent interrupts
unsigned long pulse_time = 0;
unsigned long last_pulse_time = 0;
volatile unsigned int pulseCount;
volatile bool pulseFlag;
int seconds, minutes;
bool activateFlag;
long currentTotalSeconds;
bool firstTime;
byte screen, previousScreen, soundType;
byte balance;
void timerIsr() { // this are interrupt service //countdown timers
//routine to turn provide a count down timer
//this will decrement every 1 millisecond
if (timer1)
timer1-- ; // Only decrement if non-zero !!!!!!!!!!!!
if (timer2)
timer2-- ;
if (soundTimer)
soundTimer-- ;
}
ISR(TIMER1_COMPA_vect) {
timerIsr();
}
void setup() {
cli();//stop interrupts
//set timer1 interrupt at 1khz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for
OCR1A = 250;
// turn on CTC mode
TCCR1B |= (1 << WGM12);
//64 prescaler//this is just because wokwi will not lag very much on high prescaler
TCCR1B |= (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
Serial.begin(115200);
pinMode(COIN_PULSE_PIN, INPUT_PULLUP);
pinMode(RELAY_PIN, OUTPUT);
pinMode(RELAY_PIN2, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
//digitalWrite(BUZZER_PIN,HIGH);
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.clear();
attachInterrupt(digitalPinToInterrupt(COIN_PULSE_PIN), pulseHandler, FALLING);
washButton.begin(WASH_PIN, 0, false);
pauseButton.begin(PAUSE_PIN, 0, false);
shampooButton.begin(SHAMPOO_PIN, 0, false);
washButton.setClickHandler(washButtonHandler);
pauseButton.setClickHandler(pauseButtonHandler);
shampooButton.setClickHandler(shampooButtonHandler);
soundType = 7;
}
///////////////////////////////
void loop() {
washButton.loop();
pauseButton.loop();
shampooButton.loop();
// put your main code here, to run repeatedly:
if (pulseFlag) {
pulseFlag = 0;
// Serial.println("o yeah");
balance++;
if (screen == 3 || screen == 6) { //if pause screen or wash screen
currentTotalSeconds += (pulseCount * SECONDS_PER_PISO);
pulseCount = 0;
}
if (screen == 7 || screen == 8) {//if pause screen or shampoo screen
currentTotalSeconds += (pulseCount * SECONDS_PER_PISO_SHAMPOO);
pulseCount = 0;
}
//convert seconds to minute:seconds
minutes = currentTotalSeconds / 60;
seconds = currentTotalSeconds % 60; //get the remainder
if (screen == 1 || screen == 4) { //insert coin screen
screen = 2;// balance screen
}
soundType = 1;
}
if (screen != previousScreen) { //when screen is changed, clear it
lcd.clear();
}
previousScreen = screen;
if (!timer1) { //update every second
timer1 = 1000; // inside this if,will fire every this no. of milliseconds
switch (screen)
{
case 4:
lcd.setCursor(0, 0);
lcd.print(F("--Done Pumping--"));
if (!timer2) {
screen = 5;
screen = 1; //go back to home
}
break;
// case 5:
// lcd.setCursor(0, 0);
// lcd.print("Thank you !");
// if (!timer2) {
// screen = 1;//goback
// }
// break;
case 0:
screen = 1;
break;
case 1://home
lcd.setCursor(0, 0);
lcd.print(" INSERT COINS!");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(F("Select a Button"));
lcd.setCursor(0, 1);
lcd.print(F("Bal. Php "));
lcd.print(balance);
break;
case 6: //if paused ang wash
lcd.setCursor(0, 0);
lcd.print("Pumping Paused! ");
digitalWrite(RELAY_PIN, LOW);
lcd.setCursor(5, 1);
if (minutes < 10) {
lcd.print('0');
}
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) {
lcd.print('0'); //zero place holder if less than 10
}
lcd.print(seconds);
break;
case 8: //if paused ang shampoo
lcd.setCursor(0, 0);
lcd.print("Pumping Paused! ");
digitalWrite(RELAY_PIN2, LOW);
lcd.setCursor(5, 1);
if (minutes < 10) {
lcd.print('0');
}
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) {
lcd.print('0'); //zero place holder if less than 10
}
lcd.print(seconds);
break;
case 3:
lcd.setCursor(0, 0);
lcd.print("Pumping Water...");
lcd.setCursor(0, 1);
lcd.print("Time: ");
seconds--;
if (seconds < 0) {
seconds = 59;
if (minutes > 0) minutes--;
}
currentTotalSeconds--;
digitalWrite(RELAY_PIN, HIGH);
lcd.setCursor(5, 1);
if (minutes < 10) {
lcd.print('0');
}
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) {
lcd.print('0'); //zero place holder if less than 10
}
lcd.print(seconds);
Serial.print(F("pesos left:"));
Serial.println(currentTotalSeconds / 60);
if (currentTotalSeconds == 0) { //if finish na
digitalWrite(BUZZER_PIN, LOW); //off ALL
digitalWrite(RELAY_PIN, LOW);
activateFlag = 0;
currentTotalSeconds = 0;
seconds = 0;
minutes = 0;
screen = 4; timer2 = 1300;
balance = 0;
}
break;
case 7:
lcd.setCursor(0, 0);
lcd.print("Pumping Shampoo...");
lcd.setCursor(0, 1);
lcd.print("Time: ");
if (!firstTime) {//so that it will start the count down on exact time
seconds--;
if (seconds < 0) {
seconds = 59;
if (minutes > 0) minutes--;
}
currentTotalSeconds--;
}
digitalWrite(RELAY_PIN2, HIGH);
lcd.setCursor(5, 1);
if (minutes < 10) {
lcd.print('0');
}
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) {
lcd.print('0'); //zero place holder if less than 10
}
lcd.print(seconds);
Serial.print(F("pesos left:"));
Serial.println(currentTotalSeconds / 60);
if (currentTotalSeconds == 0) {
digitalWrite(BUZZER_PIN, LOW); //off ALL
digitalWrite(RELAY_PIN2, LOW);
activateFlag = 0;
currentTotalSeconds = 0;
seconds = 0;
minutes = 0;
screen = 4; timer2 = 1300;
balance = 0;
}
// if (currentTotalSeconds < 61 && currentTotalSeconds>0) {//buzzer activate
// digitalWrite(BUZZER_PIN, !digitalRead(BUZZER_PIN));
// }
break;
}
}
soundEffect();
}
void pulseHandler() {
pulse_time = millis();
if (pulse_time - last_pulse_time > 40) // debounce, to avoid glitches
{
pulseCount++;
pulseFlag = true;
last_pulse_time = pulse_time;
}
}
void washButtonHandler(Button2 & btn) {
switch (btn.getType()) {
case single_click:
if (screen == 2) {
screen = 3;
balance = 0;
soundType = 7;
currentTotalSeconds += (pulseCount * SECONDS_PER_PISO) + 1;
//add 1 compensate during first time and continuation delay
minutes = currentTotalSeconds / 60;
seconds = currentTotalSeconds % 60; //get the remainder
// seconds++;
pulseCount = 0;
}
else if (screen == 6) {
screen = 3;
soundType = 7;
}
// Serial.println("yeah");
break;
}
}
void pauseButtonHandler(Button2 & btn) {
switch (btn.getType()) {
case single_click:
if (screen == 3 ) {
screen = 6; //pause screen
soundType = 3;
}
else if (screen == 7) {
screen = 8; //pause screen
soundType = 3;
}
break;
}
}
void shampooButtonHandler(Button2 & btn) {
switch (btn.getType()) {
case single_click:
if (screen == 2) {
balance = 0;
screen = 7;
soundType = 7;
currentTotalSeconds += (pulseCount * SECONDS_PER_PISO_SHAMPOO) + 1; //calculate
//add 1 compensate during first time and continuation delay
minutes = currentTotalSeconds / 60;
seconds = currentTotalSeconds % 60; //get the remainder
pulseCount = 0;
}
else if (screen == 8) {
screen = 7; //shampoo screen
soundType = 7; //startSOund
}
break;
}
}
void soundEffect() { //from super mario
switch (soundType) {
case 1:
soundTimer = 100;
soundType = 2;
break;
case 2: // coin sound
tone(BUZZER_PIN, 494 * 2, 80);
if (!soundTimer) {
tone(BUZZER_PIN, 660 * 2, 200);
soundType = 0;
}
break;
case 3: // pausesound//ayaw kol ...hahaha
soundTimer = 100;
tone(BUZZER_PIN, 660 * 2, 80);
soundType = 4;
break;
case 4:
if (!soundTimer) {
tone(BUZZER_PIN, 525 * 2, 80);
soundType = 5;
soundTimer = 100;
}
break;
case 5:
if (!soundTimer) {
soundTimer = 100;
tone(BUZZER_PIN, 660 * 2, 80);
soundType = 6;
}
break;
case 6:
if (!soundTimer) {
//soundTimer = 50;
tone(BUZZER_PIN, 525 * 2, 300);
soundType = 0;
}
break;
case 7: // starting
soundTimer = 100;
tone(BUZZER_PIN, 329 * 2, 80);
soundType = 8;
break;
case 8:
if (!soundTimer) {
soundTimer = 100;
tone(BUZZER_PIN, 390 * 2, 80);
soundType = 9;
}
break;
case 9:
if (!soundTimer) {
soundTimer = 100;
tone(BUZZER_PIN, 587 * 2, 80);
soundType = 10;
}
break;
case 10:
if (!soundTimer) {
soundTimer = 100;
tone(BUZZER_PIN, 528 * 2, 80);
soundType = 11;
}
break;
case 11:
if (!soundTimer) {
soundTimer = 100;
tone(BUZZER_PIN, 590 * 2, 80);
soundType = 12;
}
break;
case 12:
if (!soundTimer) {
tone(BUZZER_PIN, 788 * 2, 200);
soundType = 0;
}
break;
}
}
//329 390 587 528 590 788