Here you go. It is rather a large program... Hopefully the formatting stays correct. yes I also know that there are various serial commands that are currently in the code that Ive been using to double check for debugging etc
/*
Soda-Pop Dispenser Machine V 1.3
By:
Geoffrey Andreychuk
July 15th, 2022
*/
// Including additional required libraries:
#include <LiquidCrystal_I2C.h>
#include <EncoderButton.h>
#include <Wire.h>
EncoderButton eb1(2, 3, 4); // Declaring the Rotary Encoder & Button along with the Assigned Pins used Encoder+button: EncoderButton(byte encoderPin1, byte encoderPin2, byte switchPin);
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 20 chars and 4 line display
int ButtonPin = 33;
int ButtonState = High
int DrinkPointer = 0; // a variable to point to the current position in the Drink List
int TotalNumDrink = 10; // variable to hold the value of Drink Options
int DrinkSelection = -1; // variable to point to the users selected drink option to make the drink
bool IsClicked = false; // to see if a selection has been made
int Increment; // variable to hold a + for CW and - for a CCW turn of Rotary Encoder
unsigned long IdleTime = 25000; // a timer fuction to be used to clear any selected options and return program to main selection screen
unsigned long EventInterval = 5000;
unsigned long PreviousTime = 0;
unsigned long CurrentTime;
char *DrinkChoices[] = {"Dr. Pepper", "Grape Crush", "Orange Crush", "Cream Soda", "Iced Tea", "Coke", "Diet Coke", "Root Beer", "Sprite", "Soda Water"};
//Pump A
#define enA 5
#define in1 22
//Pump B
#define enB 6
#define in2 23
//Pump C
#define enC 7
#define in3 24
//Pump D
#define enD 8
#define in4 25
//Pump E
#define enE 9
#define in5 26
//Pump F
#define enF 10
#define in6 27
//Pump G
#define enG 11
#define in7 28
//Pump H
#define enH 12
#define in8 29
//Relays to control Solenoid Valves 1-3
#define Sol1 30
#define Sol2 31
#define Sol3 32
//Set all pump and Solenoid pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(enC, OUTPUT);
pinMode(enD, OUTPUT);
pinMode(enE, OUTPUT);
pinMode(enF, OUTPUT);
pinMode(enG, OUTPUT);
pinMode(enH, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(in5, OUTPUT);
pinMode(in6, OUTPUT);
pinMode(in7, OUTPUT);
pinMode(in8, OUTPUT);
pinMode(Sol1, OUTPUT);
pinMode(Sol2, OUTPUT);
pinMode(Sol3, OUTPUT);
pinMode(ButtonPin, INPUT_PULLUP)
void setup()
{
Serial.begin(9600);
lcd.init(); // initialize the display
lcd.backlight();
IdleMenu();
//Link the event(s) to your function
eb1.setClickHandler(onEb1Clicked);
eb1.setEncoderHandler(onEb1Encoder);
}
void IdleMenu() // Prints the idle screen message to the display
{
lcd.clear();
lcd.setCursor(0, 0); // Sets the cursor to column 4, line 0, since counting begins with row 0
lcd.print("Drink Selection Menu");
// set the cursor to line 1 which is the second row
lcd.setCursor(2, 1);
lcd.print("Rotate Knob Left"); // print to the second line
lcd.setCursor(2, 2);
lcd.print("or Right & Press"); // print to the fourth line
lcd.setCursor(0, 3);
lcd.print("to make Selection!!");
}
void SelectionMenu()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("<-----------------");
lcd.setCursor(3, 1);
lcd.print(DrinkChoices[DrinkPointer]);
lcd.setCursor(3, 2);
lcd.print("---------------->");
lcd.setCursor(0, 3);
lcd.print("Press knob to Select");
};
//A function to handle the 'encoder' event
void onEb1Encoder(EncoderButton& eb)
{
Serial.print("eb1 incremented by: ");
Serial.println(eb.increment());
Serial.print("eb1 position is: ");
Serial.println(eb.position());
Serial.println("Increment is: ");
Serial.println(Increment);
Serial.println("DrinkPointer position: ");
Serial.println(DrinkPointer);
}
void UpdatePointer()
{
Increment = (eb1.position());
Serial.println("----------------");
Serial.println("Position is: ");
Serial.println(eb1.position());
eb1.resetPosition();
DrinkPointer = DrinkPointer + Increment;
Serial.println("DrinkPointer position: ");
Serial.println(DrinkPointer);
if (DrinkPointer = (TotalNumDrink - 1))
{
DrinkPointer = 0;
return;
}
if (DrinkPointer = 0)
{
DrinkPointer = (TotalNumDrink - 1);
return;
}
}
void PlaceGlass() // Function to tell the user which side to place glass
{
// cleans up the screen before letting user know where to put glass
Serial.print("Is Clicked: ");
Serial.println(IsClicked);
Serial.print("Drink Selection is: ")
Serial.println(DrinkChoices[DrinkSelection]);
lcd.clear();
lcd.setCursor(0, 0);
lcd.println("Place Glass");
lcd.setCursor(5, 1);
if (DrinkSelection <= 0 && DrinkSelection < 6)
{
lcd.println("Right ------->");
}
If (DrinkSelection >= 6 && DrinkSelection < 10)
{
lcd.println("<-------- Left");
}
lcd.setCursor(2,2);
lcd.println("Press & Hold Button");
lcd.setCursor(1,3);
lcd.println("to dispense Pop");
}
void Dispense(int PWM, int Pump, int Solenoid)
{
ButtonState = digitalRead(ButtonPin);
while (ButtonState == Low) {
analogWrite(PWM,255); // turn on pwm control for pump
digitalWrite(Pump,HIGH); // turn on pump
digitalWrite(Solenoid,HIGH); // turn on Solenoid
ButtonState = digitalRead(ButtonPin);
}
void loop()
{
eb1.update();
CurrentTime = millis();
if ((CurrentTime - PreviousTime) >= IdleTime)
{
IdleMenu();
PreviousTime = CurrentTime;
}
if ((CurrentTime - PreviousTime >= EventInterval) && (eb1.position() != 0))
{
SelectionMenu();
UpdatePointer();
PreviousTime = CurrentTime;
};
if ((eb1.isPressed()) == true) && ((IsClicked) == false)
{
IsClicked = true; // to ensure selection is held till timout value is reached then reset
DrinkSelection = DrinkPointer; // to ensure that the selected drink is not changed till either drink is poured or idle timer timeout is reached
PlaceGlass();
switch (DrinkSelection)
{
case 0: // Selection Dr. Pepper
PWM = enA;
Pump = inA;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
case 1: // Selection Grape Crush
PWM = enB
Pump = inB;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
case 2: // Selection Orange Crush
PWM = enC;
Pump = inC;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
case 3: // Selection Cream Soda
PWM = enD;
Pump = inD;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
Case 4: // Selection Iced Tea
PWM = 0
Pump = 0;
Solenoid = soL3;
Dispense(PWM, Pump, Solenoid)
break;
case 5: // Selection Soda Water
PWM = 0;
Pump = 0;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
case 6: // Selection Coke
PWM = enE;
Pump = inE;
Solenoid = sol2;
Dispense(PWM, Pump, Solenoid)
break;
case 7: // Selection Diet Coke
PWM = enF;
Pump = inF;
Solenoid = sol2;
Dispense(PWM, Pump, Solenoid)
break;
case 8: // Selection Sprite
PWM = enG;
Pump = inG;
Solenoid = sol2;
Dispense(PWM, Pump, Solenoid)
break;
case 9: // Selection Root Beer
PWM = enH;
Pump = inH;
Solenoid = sol1;
Dispense(PWM, Pump, Solenoid)
break;
}
/*To ensure that nothing is accidently dispensed till a new drink selection is made by the next user and return the system back to an idle state */
IsClicked = false;
DrinkSelection = -1
PWM = 0;
Pump = 0;
aSolinoid = 0;
};
};