#include <LiquidCrystal.h>
#include <stdio.h>
//LCD Pin Numbers//
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // RS, E, D4, D5, D6, D7
//Pin Numbers//
const int UpButton = 9; //Pin Up Button is connected to
const int DownButton = 8; //Pin Down Button is connected to
const int ConfirmButton = 7; //Pin Confirm Button is connected to
const int BackButton = 6; //Pin Decline Button is connected to
//Important Values//
int FeedTemperature = 190;
int BarrelTemperature = 200;
int NozzleTemperature = 200;
int AugerSpeed = 100;
String PlasticName = "Manual";
//Constants of Machine Parts//
//Incrementation for Menu//
int MenuPage = 1;
int PreviousMenuPage = 2;
//Incrementation for Plastic Selection//
int PlasticPage = 1;
int PreviousPlasticPage = 2;
//Incrementation for Manual Selection//
int ManualPage = 1;
int UpdateSpeed = 500;
/*
1 is the Main Menu
2 is the Plastic Selection
3 is the Manual Selection
4 is the Confirmation
99 is Turn off Display
*/
int ScreenType = 1;
//Debounce Functions for Possible Errors//
bool CurrentUp = LOW; //Checks if any Current is Flowing through Up Button
bool LastUp = LOW; //The state of the Up Button last time it was pressed/held
bool LastDown = LOW; //The state of the Down Button last time it was pressed/held
bool CurrentDown = LOW; //Checks if any Current is Flowing through Down Button
bool CurrentConfirm = LOW; //Checks if any Current is Flwoing through Confirm Button
bool LastConfirm = LOW; //The state of the Confirm Button last time it was pressed/held
bool LastBack = LOW; //The state of the Back Button last time it was pressed/held
bool CurrentBack = LOW; //Checks if any Current is Flowing through Back Button
//Custom Degree Symbol//
byte Degrees[] = {
B00110,
B01001,
B01001,
B00110,
B00000,
B00000,
B00000,
B00000
};
byte SelectionStar[] = {
B00100,
B10101,
B01110,
B11111,
B01110,
B10101,
B00100,
B00000
};
//Plastic Properties//
struct PlasticProp{
String Name;
int Feed;
int Barrel;
int Nozzle;
int AugerSpeed;
};
//Plastic Property Definitions//
PlasticProp PLA = { //PLA Properties
"PLA", //PLA
100, //Feed
170, //Barrel
170, //Nozzle
10 //Auger Speed (RPM)
};
PlasticProp ABS = { //ABS Properties
"ABS", //ABS
100, //Feed
195, //Barrel
200, //Nozzle
10 //Auger Speed (RPM)
};
PlasticProp PETG = { //PETG Properties
"PETG", //PETG
100, //Feed
200, //Barrel
220, //Nozzle
10 //Auger Speed (RPM)
};
void setup() {
//Initialization of Buttons as Inputs
pinMode(UpButton, INPUT);
pinMode(DownButton, INPUT);
pinMode(ConfirmButton, INPUT);
pinMode(BackButton, INPUT);
//Initialization of LCD
lcd.begin(20, 4);
//Creating the Degree Symbol
lcd.createChar(1, Degrees);
lcd.createChar(2, SelectionStar);
lcd.home();
Serial.begin(9600);
}
//Debounce Function for Buttons//
bool DeBounce(bool Last,int Pin){
bool Current = digitalRead(Pin); //Reads the input of the button in this moment of time
if (Last != Current){ //If the current is not the same, recheck to make sure that is the case
delay(5);
Current = digitalRead(Pin);
}
return Current; //Returns the button input
}
//Registers Whether or Not the Button was pressed
bool ButtonPress(bool Last,bool Current){
return Last == LOW && Current == HIGH;
}
//Reset all Page Numbers when Changing Screens
void ResetPages(){
PlasticPage = 1;
MenuPage = 1;
ManualPage = 1;
}
//Main Menu Display//
void MenuScreen(){
lcd.noBlink(); //Disables the blink
lcd.setCursor(0,0); //Sets where to print 1st
lcd.print("Select Plastic Type"); //Prints First Option
lcd.setCursor(0, 1); //Sets where to print 2nd
lcd.print("Manual Override"); //Prints Second Option
lcd.setCursor(0, 2); //Sets where to print 3rd
lcd.print("Calibration"); //Prints Third Option
lcd.setCursor(0, 3); //Sets where to print 4th
lcd.print("Turn off"); //Prints Fourth Option
for (int ii = 0; ii <= 3;ii++){ //Increments through all 4 options
lcd.setCursor(19, ii); //Sets the cursor for each increment
lcd.write(2); //Prints the Stars for Options
}
}
//Change the Main Menu According to User Input//
int MenuSelection(){
if (ButtonPress(LastUp,CurrentUp)){ //Checks if the Up Button was Pressed
MenuPage++; //Incremements MenuPage by 1 if it is pressed
if (MenuPage > 4){ //However, MenuPage cannot go past 4
MenuPage = 4; //If the MenuPage is greater then 4, reset it back to 4
}
else{ //If the MenuPage is able to change
lcd.clear(); //Clear the LCD to refresh
}
}
if (ButtonPress(LastDown,CurrentDown)){ //Checks if the Down Button was Pressed
MenuPage--; //Decremenets MenuPage by 1 if it is pressed
if (MenuPage < 1){ //However, MenuPage cannot go past 1
MenuPage = 1; //If the MenuPage is less than 1, reset it back to 1
}
else{ //If the MenuPage is able to change
lcd.clear(); //Clear the LCD to refresh
}
}
switch(MenuPage){ //Enables the blinking cursor on selected option
case 1:{ //On the first option
lcd.setCursor(19,0); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the Selection Star
}break;
case 2:{ //On the seconds option
lcd.setCursor(19,1); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the SelectionStar
}break;
case 3:{ //On the third option
lcd.setCursor(19,2); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the SelectionStar
}break;
case 4:{ //On the fourth option
lcd.setCursor(19,3); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the SelectionStar
}break;
}
return MenuPage; //Returns the New MenuPage Number
}
//Plastic Selection Display//
void PlasticScreen(){
lcd.noBlink(); //Disables the blink
lcd.setCursor(0,0); //Sets where to print 1st line
lcd.print("Plastic Types:"); //Prints first line
lcd.setCursor(0, 1); //Sets where to print 1st option
lcd.print("PLA"); //Prints First Option
lcd.setCursor(0, 2); //Sets where to print 2nd option
lcd.print("ABS"); //Prints Second Option
lcd.setCursor(0, 3); //Sets where to print 3rd option
lcd.print("PETG"); //Prints Third Option
for (int ii = 1; ii <= 3;ii++){ //Increments through all 3 options
lcd.setCursor(19, ii); //Sets the cursor for each increment
lcd.write(2); //Prints the Stars for Options
}
}
//Plastic Selection Code//
int PlasticSelection(){
if (ButtonPress(LastUp,CurrentUp)){ //Checks if the Up Button was Pressed
PlasticPage++; //Incremements PlasticPage by 1 if it is pressed
if (PlasticPage > 3){ //However, PlasticPage cannot go past 3
PlasticPage = 3; //If the PlasticPage is greater then 3, reset it back to 3
}
else{ //If the PlasticPage is able to change
lcd.clear(); //Clear the LCD to refresh
}
}
if (ButtonPress(LastDown,CurrentDown)){ //Checks if the Down Button was Pressed
PlasticPage--; //Decremenets PlasticPage by 1 if it is pressed
if (PlasticPage < 1){ //However, PlasticPage cannot go past 1
PlasticPage = 1; //If the PlasticPage is less than 1, reset it back to 1
}
else{ //If the PlasticPage is able to change
lcd.clear(); //Clear the LCD to refresh
}
}
switch(PlasticPage){ //Enables the blinking cursor on selected option
case 1:{ //On the first option
lcd.setCursor(19,1); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the Selection Star
}break;
case 2:{ //On the second option
lcd.setCursor(19,2); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the Selection Star
}break;
case 3:{ //On the third option
lcd.setCursor(19,3); //Set Cursor ontop of Selection Star
lcd.blink(); //Blink the Selection Star
}break;
}
return PlasticPage; //Returns the New PlasticPage Number
}
//Load Proper Information for Selected Plastic//
int PlasticLoad(){
switch(PlasticPage){
case 1: { //PLA
FeedTemperature = PLA.Feed; //Change the Feed Temp
BarrelTemperature = PLA.Barrel; //Change the Barrel Temp
NozzleTemperature = PLA.Nozzle; //Change the Nozzle Temp
AugerSpeed = PLA.AugerSpeed; //Change Auger Speed
PlasticName = PLA.Name; //Change Plastic Name
}break;
case 2: {
FeedTemperature = ABS.Feed; //Change the Feed Temp
BarrelTemperature = ABS.Barrel; //Change the Barrel Temp
NozzleTemperature = ABS.Nozzle; //Change the Nozzle Temp
AugerSpeed = ABS.AugerSpeed; //Change Auger Speed
PlasticName = ABS.Name; //Change Plastic Name
}break;
case 3: {
FeedTemperature = PETG.Feed; //Change the Feed Temp
BarrelTemperature = PETG.Barrel; //Change the Barrel Temp
NozzleTemperature = PETG.Nozzle; //Change the Nozzle Temp
AugerSpeed = PETG.AugerSpeed; //Change Auger Speed
PlasticName = PETG.Name; //Change Plastic Name
}break;
}
}
//Manual Selection Display//
void ManualScreen(){
//Disables the blink
lcd.noBlink();
//Sets where to print 1st line
lcd.setCursor(0,0);
//Prints Feed: [Temp] oC
lcd.print("Feed: ");
lcd.print(FeedTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 2nd line
lcd.setCursor(0, 1);
//Prints Barrel: [Temp] oC
lcd.print("Barrel: ");
lcd.print(BarrelTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 3rd line
lcd.setCursor(0, 2);
//Prints Nozzle: [Temp] oC
lcd.print("Nozzle: ");
lcd.print(NozzleTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 4th line
lcd.setCursor(0, 3);
//Prints Feed: [Temp]oC
lcd.print("Auger: ");
lcd.print(AugerSpeed);
lcd.print(" RPM");
for (int ii = 0; ii <= 3;ii++){ //Increments through all 4 lines
lcd.setCursor(19, ii); //Sets the cursor for each increment
lcd.write(2); //Prints the Stars for Options
}
}
//Manual Selection for Temperatures//
void ManualScroll(int* Temperature){
while(ButtonPress(LastUp,CurrentUp)){ //Press and holding the up button
(*Temperature)++; //Increments Temperature up by one
if ((*Temperature) > 300){ //Prevents from Going above 300C
(*Temperature) = 300; //Resets it back to 300C
}
ManualScreen();
delay(UpdateSpeed); //Allows for some reaction time of user
CurrentUp = DeBounce(LastUp,UpButton); //Re-reads the Up Button
UpdateSpeed = UpdateSpeed - 50; //Allows Ramp-up
if (UpdateSpeed < 100){ //Maximum of 10 per second
UpdateSpeed = 100; //10 updates per second
}
}
while(ButtonPress(LastDown,CurrentDown)){ //Press and holding the down button
(*Temperature)--; //Decrements Temperature by one
if ((*Temperature) < 0){ //Prevents from Going below 0C
(*Temperature) = 0; //Resets is back to 0C
}
if ((*Temperature) == 99 || (*Temperature) == 9){ //Clears the LCD when going from 100 to 99
lcd.clear(); //Clear LCD
}
ManualScreen();
delay(UpdateSpeed); //Allows for some reaction time of user
CurrentDown = DeBounce(LastDown,DownButton); //Re-reads the Down Button
UpdateSpeed = UpdateSpeed - 50; //Allows Ramp-Up
if (UpdateSpeed < 100){ //Maximum of 10 per second
UpdateSpeed = 100; //10 updates per second
}
}
UpdateSpeed = 500; //Reset Update Speed
PlasticName = "Manual"; //Change PlasticName to Manual
}
//Manual Selection for Auger Speed//
void AugerScroll(){
while(ButtonPress(LastUp,CurrentUp)){ //Press and holding the up button
AugerSpeed++; //Increments Temperature up by one
if (AugerSpeed > 200){ //Prevents from Going above 300C
AugerSpeed = 150; //Resets it back to 300C
}
ManualScreen();
delay(UpdateSpeed); //Allows for some reaction time of user
CurrentUp = DeBounce(LastUp,UpButton); //Re-reads the Up Button
UpdateSpeed = UpdateSpeed - 50; //Allows Ramp-up
if (UpdateSpeed < 100){ //Maximum of 10 per second
UpdateSpeed = 100; //10 updates per second
}
}
while(ButtonPress(LastDown,CurrentDown)){ //Press and holding the down button
AugerSpeed--; //Decrements Temperature by one
if (AugerSpeed < 0){ //Prevents from Going below 0C
AugerSpeed = 0; //Resets is back to 0C
}
if (AugerSpeed == 99 || AugerSpeed == 9){ //Clears the LCD when going from 100 to 99
lcd.clear(); //Clear LCD
}
ManualScreen();
delay(UpdateSpeed); //Allows for some reaction time of user
CurrentDown = DeBounce(LastDown,DownButton); //Re-reads the Down Button
UpdateSpeed = UpdateSpeed - 50; //Allows Ramp-Up
if (UpdateSpeed < 100){ //Maximum of 10 per second
UpdateSpeed = 100; //10 updates per second
}
}
UpdateSpeed = 500; //Reset Update Speed
}
//Show the Temperatures before starting//
void ConfirmationScreen(){
//Disables the blink
lcd.noBlink();
//Sets where to print 1st line
lcd.setCursor(0,0);
//Prints Feed: [Temp] oC
lcd.print("F: ");
lcd.print(FeedTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 2nd line
lcd.setCursor(0, 1);
//Prints Barrel: [Temp] oC
lcd.print("B: ");
lcd.print(BarrelTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 3rd line
lcd.setCursor(0, 2);
//Prints Nozzle: [Temp] oC
lcd.print("N: ");
lcd.print(NozzleTemperature);
lcd.print(" ");
lcd.write(1);
lcd.print("C");
//Sets where to print 4th line
lcd.setCursor(0, 3);
//Prints Feed: [Temp]oC
lcd.print("A: ");
lcd.print(AugerSpeed);
lcd.print(" RPM");
//Display Confirm Option
lcd.setCursor(12,3);
lcd.print("Confirm?");
//Display what they are confirming
lcd.setCursor(14,0);
lcd.print(PlasticName);
}
void loop(){
CurrentUp = DeBounce(LastUp,UpButton); //Get the Current flowing through the Up Button
CurrentDown = DeBounce(LastDown,DownButton); //Get the Current flowing through the Down Button
CurrentConfirm = DeBounce(LastConfirm,ConfirmButton); //Get the Current flowing through the Confirm Button
CurrentBack = DeBounce(LastBack,BackButton); //Get the Current flowing through the Back Button
//When on the Main Menu
if (ScreenType == 1){
if (MenuPage != PreviousMenuPage){ //If the Page on the Main Menu was changed recently
MenuScreen(); //Update the Main Menu
PreviousMenuPage = MenuPage; //Update the Last recorded Menu Page
} //Will not refresh the screen unless a change was made
MenuPage = MenuSelection(); //Look for a update and enable blinker
}
//When on Plastic Selection
if (ScreenType == 2){
if (PlasticPage != PreviousPlasticPage){ //If the Page on the Plastic Selection was changed recently
PlasticScreen(); //Update the Plastic Selection Screen
PreviousPlasticPage = PlasticPage; //Update the Last recorded Plastic Page
}
PlasticPage = PlasticSelection(); //Look for a update and enable blinker
}
//When on Manual Selection
//Note: The buttons suck on wokwi but work on TinkerCad, even with DeBounce disabled. Just accept this I guess
if (ScreenType == 3){
if (ManualPage == 4){ //On AugerSpeed
AugerScroll(); //Look for Temeprature Updates with Up and Down Buttons
if (ButtonPress(LastConfirm,CurrentConfirm)) {ManualPage++;} //If the Confirm Button is pressed, go to next line
if (ButtonPress(LastBack,CurrentBack)) {ManualPage--;LastBack = CurrentBack;} //If the Back Button is pressed, go to next line
}
if (ManualPage == 3){ //On Nozzle Temperature
ManualScroll(&NozzleTemperature); //Look for Temeprature Updates with Up and Down Buttons
if (ButtonPress(LastConfirm,CurrentConfirm)) {ManualPage++;} //If the Confirm Button is pressed, go to next line
if (ButtonPress(LastBack,CurrentBack)) {ManualPage--;LastBack = CurrentBack;} //If the Back Button is pressed, go to next line
}
if (ManualPage == 2){ //On Barrel Temperature
ManualScroll(&BarrelTemperature); //Look for Temeprature Updates with Up and Down Buttons
if (ButtonPress(LastConfirm,CurrentConfirm)) {ManualPage++;} //If the Confirm Button is pressed, go to next line
if (ButtonPress(LastBack,CurrentBack)) {ManualPage--;LastBack = CurrentBack;} //If the Back Button is pressed, go to next line
}
if (ManualPage == 1){ //On Feed Temperature
ManualScroll(&FeedTemperature); //Look for Temeprature Updates with Up and Down Buttons
if (ButtonPress(LastConfirm,CurrentConfirm)) {ManualPage++;LastBack = CurrentBack;} //If the Confirm Button is pressed, go to next line
}
lcd.setCursor(19,ManualPage-1); //Set the Location of the Blinker
lcd.blink(); //Turn on the Blinker
}
CurrentBack = DeBounce(LastBack,BackButton); //Get the Current flowing through the Back Button
if (ScreenType == 4){ //If on the Confirmation Screen
lcd.noBlink(); //Turn off blinking
ConfirmationScreen(); //Constantly Refesh Screen
}
//If the Confirm Button is Pressed
if (ButtonPress(LastConfirm,CurrentConfirm)){
if (ScreenType == 3 && ManualPage == 4){ //If on the Manual Selection and AugerSpeed
lcd.clear(); //Clear the LCD
ScreenType = 4; //Change the ScreenType to Confirmation
ResetPages(); //Resets all Pages
ConfirmationScreen(); //Load the Confirmation Screen
}
if (ScreenType == 2){ //If on the Plastic Selection
lcd.clear(); //Clear the LCD
PlasticLoad(); //Load Proper Plastic Information
ScreenType = 4; //Change ScreenType to Confirmation
ResetPages(); //Resets all Pages
ConfirmationScreen(); //Load the Confirmation Screen
}
if (ScreenType == 1 && MenuPage == 4){ //If on the Main Menu and Selecting "Turn Off"
lcd.noDisplay(); //Turn off Display
lcd.noBlink(); //Turn off Blinking
ScreenType = 99; //Set ScreenType to arbitrary value (Needs to be changed)
}
if (ScreenType == 1 && MenuPage == 2){ //If on the Menu Screen and Selecting "Manual Override"
lcd.clear(); //Clear the LCD
ScreenType = 3; //Change the ScreenType to Manual Selection Screen
ResetPages(); //Resets all Pages
ManualScreen(); //Load the Manual Selection Screen
}
if (ScreenType == 1 && MenuPage == 1){ //If on the Menu Screen and Selecting "Select Plastic Type"
lcd.clear(); //Clear the LCD
ScreenType = 2; //Change the ScreenType to Plastic Selection Screen
ResetPages(); //Resets all Pages
PlasticScreen(); //Load the Plastic Selection Screen
}
}
//If the Back Button is Pressed
if (ButtonPress(LastBack,CurrentBack)){
if (ScreenType == 2){ //If on the Plastic Selection Screen or Manual Selection Screen
lcd.clear(); //Clear the LCD
ScreenType = 1; //Change the ScreenType to Main Menu
ResetPages(); //Resets all Pages
MenuScreen(); //Load the Main Menu
}
if (ScreenType == 3 && ManualPage == 1){
lcd.clear(); //Clear the LCD
ScreenType = 1; //Change the ScreenType to Main Menu
ResetPages(); //Resets all Pages
MenuScreen(); //Load the Main Menu
}
if (ScreenType == 4){
lcd.clear(); //Clear the LCD
ScreenType = 3; //Change the ScreenType to Manual Selection
ResetPages(); //Resets all Pages
if (PlasticName != "Manual"){ //If it came from Plastic Selection
ScreenType = 2; //Change the ScreenType to Plastic Selection
PlasticScreen(); //Load the Plastic Selection Screen
}
else{ //If it came from Manual Selection
ScreenType = 3; //Change the ScreenType to Manual Selection
ManualScreen(); //Load the Manual Selection
}
}
}
LastUp = CurrentUp; //Make sure you can't accidently click and hold
LastDown = CurrentDown; //Make sure you can't accidently click and hold
LastConfirm = CurrentConfirm; //Make sure you can't accidently click and hold
LastBack = CurrentBack; //Make sure you can't accidently click and hold
}