// C++ code
/* from wokwi docs
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
void setup() {
// Init
lcd.init();
*/
//# include <Adafruit_LiquidCrystal.h>
# include <LiquidCrystal_I2C.h>
# define I2C_ADDR 0x27
# define LCD_COLUMNS 20
# define LCD_LINES 4
int balance = 0;
int waterCost = 5;
int foamCost = 5;
// Pin and Button for coins, replacement for the coin slot
int coinPin_1 = 2;
int coinPin_5 = 3;
int coinPin_10 = 4;
// Pin and Button for water and foam function
int waterPin = 5;
int foamPin = 6;
// Pin for relay
int relayPin = 9;
// Event flag for water and foam feature
bool isWatering = false;
bool isFoaming = false;
bool hasWaterTime = false;
bool hasFoamTime = false;
// Variables for toggle
int waterButtonState = 0;
int prevWaterButtonState = 0;
unsigned long toggleTime = 0;
unsigned long debounce = 200UL;
// Millis() variables
unsigned long currentWaterMillis;
unsigned long currentFoamMillis;
unsigned long startWaterMillis;
unsigned long startFoamMillis;
const unsigned long second = 1000UL;
const unsigned long minute = second * 60;
const unsigned long waterTime = second * 20; //... = minute * 2; life too short
const unsigned long foamTime = second * 13; //... = minute;
unsigned long waterTimeLeft = waterTime;
unsigned long foamTimeLeft = foamTime;
//Adafruit_LiquidCrystal lcd(0);
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
void setup()
{
// Serial
Serial.begin(115200);
Serial.println("\nJello Whirled!\n");
//Intialize the LCD
lcd.init();
//Set the pin of coinButtons
pinMode(coinPin_1, INPUT_PULLUP);
pinMode(coinPin_5, INPUT_PULLUP);
pinMode(coinPin_10, INPUT_PULLUP);
// Set the pin of water and foam button
pinMode(waterPin, INPUT_PULLUP);
pinMode(foamPin, INPUT_PULLUP);
// Set the pin of relay
pinMode(relayPin, OUTPUT);
}
# define PRESST LOW
# define NOTPRESST HIGH
void loop()
{
// Read and add inserted coin
balance = AddCoinTo(balance);
// Balance constraint
if(balance < 5)
{
if(!hasWaterTime)
{
DisplayInsert();
DisplayBalance(balance);
}
if(digitalRead(waterPin) == PRESST || digitalRead(foamPin) == PRESST)
{
Serial.println("WTF LCD");
// clear the display
lcd.clear();
lcd.home();
lcd.print(" INSUFF BALANCE ");
}
}
else if(balance >= 5)
{
if(digitalRead(waterPin) == PRESST && !hasWaterTime)
{
// clear the display
lcd.clear();
balance -= waterCost;
startWaterMillis = millis();
isWatering = true;
hasWaterTime = true;
Serial.println(F("WATER IS RUNNING"));
Serial.print(F("BALANCE: P"));
Serial.println(balance);
}
if(!hasWaterTime)
{
DisplayPress();
DisplayBalance(balance);
}
}
PumpWater();
if(digitalRead(waterPin) == PRESST && hasWaterTime)
{
TogglePumpWater();
}
}
int AddCoinTo(int bal)
{
if(digitalRead(coinPin_1) == PRESST)
{
bal += 1;
Serial.print(F("BALANCE: P"));
Serial.println(bal);
}
if(digitalRead(coinPin_5) == PRESST)
{
bal += 5;
Serial.print(F("BALANCE: P"));
Serial.println(bal);
}
if(digitalRead(coinPin_10) == PRESST)
{
bal += 10;
Serial.print(F("BALANCE: P"));
Serial.println(bal);
}
return bal;
}
void DisplayBalance(int bal)
{
lcd.setCursor(0, 1);
lcd.print(" BALANCE: P");
lcd.print(bal);
}
void DisplayInsert()
{
lcd.home();
lcd.print("INSERT:P1,P5,P10");
}
void DisplayPress()
{
lcd.home();
lcd.print(" PRESS A BUTTON ");
}
void PumpWater()
{
currentWaterMillis = millis();
long displayWaterTime;
if(isWatering)
{
unsigned long elapsedWaterTime = currentWaterMillis - startWaterMillis;
if(elapsedWaterTime > waterTimeLeft)
{
if(digitalRead(relayPin) == 1)
{
digitalWrite(relayPin, 0);
}
displayWaterTime = 0;
isWatering = false;
hasWaterTime = false;
}
else if(elapsedWaterTime <= waterTimeLeft)
{
if(digitalRead(relayPin) == 0)
{
digitalWrite(relayPin, 1);
}
displayWaterTime = waterTimeLeft - elapsedWaterTime;
}
}
else if(!isWatering)
{
if(digitalRead(relayPin) == 1)
{
digitalWrite(relayPin, 0);
}
if(hasWaterTime)
{
displayWaterTime = waterTimeLeft;
}
}
// Display Time
if(hasWaterTime)
{
int countdown_minute = ((displayWaterTime / 1000) / 60) % 60;
int countdown_sec = (displayWaterTime / 1000) % 60;
lcd.home();
lcd.print("WTR");
if(countdown_minute < 10)
{
lcd.print(" ");
}
lcd.print(countdown_minute);
lcd.print(":");
if(countdown_sec < 10)
{
lcd.print("0");
}
lcd.print(countdown_sec);
}
// Reset the waterTimeLeft after the countdown is finished
if(displayWaterTime == 0)
{
waterTimeLeft = waterTime;
}
}
// Play/Pause toggle of the water time countdown:
void TogglePumpWater()
{
isWatering = !isWatering;
if(isWatering)
{
startWaterMillis = millis();
Serial.println(F("toggled: WATER IS RUNNING"));
}
else if(!isWatering)
{
waterTimeLeft -= (millis() - startWaterMillis);
Serial.println(F("toggled: WATER HAS STOPPED"));
}
}
COIN 1
WATER
FOAM
RELAY
COIN 5
COIN 10