#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); //sometimes the LCD adress is not 0x3f. Change to 0x27 if it dosn't work.
//Vectors for musical note and arrow
uint8_t note[8] = {0x02, 0x03, 0x02, 0x0e, 0x1e, 0x0c, 0x00, 0x00};
uint8_t arrow[8] = {0x0, 0x04 ,0x06, 0x1f, 0x06, 0x04, 0x00, 0x00};
//Variables for the menu encoder
int counter = 0;
int page=1;
int Ready=1;
int submenu=0;
int last_counter = 0;
bool clk_State;
bool Last_State;
bool dt_State;
int pushed = 0;
//The pin for the push button
#define push 7
void setup() {
pinMode (push,INPUT); //Define the pin as input
lcd.init(); //Init the LCD
lcd.backlight(); //Activate backlight
lcd.createChar(0, note); //Create the note symbol
lcd.createChar(1, arrow); //Create the arrow symbol
lcd.home(); //Home the LCD
PCICR |= (1 << PCIE0); //enable PCMSK0 scan
PCMSK0 |= (1 << PCINT0); //Set pin D8 trigger an interrupt on state change.
PCMSK0 |= (1 << PCINT1); //Set pin D9 trigger an interrupt on state change.
DDRB &= B11111100; //8, 9 as input for the encoder clock and data pins
Last_State = (PINB & B00000001); //pin 8 state (clock pin)?
//Prepare the DFplayer module comunication and settings
Serial.begin(115200);
//Print the initial text. Delete these lines if you don't want that
lcd.clear();
lcd.setCursor(0,0);
//lcd.write(0);
lcd.print(" ELECTRONOOBS ");
//lcd.write(0);
lcd.setCursor(0,1);
lcd.print(" Coffee machine ");
delay(500);
//Print the first page menu.
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("Choose coffee");
lcd.setCursor(0,1);
lcd.print(" Sugar level");
}
void loop() {
if((last_counter > counter) || (last_counter < counter) || pushed) //Only print on the LCD when a step is detected or the button is pushed.
{
Ready=1;
//First page of the menu
if(submenu == 0)
{
if(0 <= counter && counter < 5)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("Choose coffee");
lcd.setCursor(0,1);
lcd.print(" Sugar level");
page=1;
if(pushed)
{
pushed=0;
}
}
if(5 < counter && counter < 10)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Choose coffee");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("Sugar level");
page=2;
if(pushed)
{
pushed=0;
}
}
if(10 < counter && counter < 15)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("Backlight");
lcd.setCursor(0,1);
lcd.print(" Volume");
page=3;
if(pushed)
{
pushed=0;
}
}
if(15 < counter && counter < 20)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Backlight");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("Volume");
page=4;
if(pushed)
{
pushed=0;
}
}
}//submenu = 0;
//Second page of the menu
if(submenu == 1)
{
if(0 <= counter && counter < 5)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("Latte");
lcd.setCursor(0,1);
lcd.print(" Cappuccino");
page=1;
pushed=0;
}
if(5 < counter && counter < 10)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Latte");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("Cappuccino");
page=2;
pushed=0;
}
if(10 < counter && counter < 15)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("Americano");
lcd.setCursor(0,1);
lcd.print(" Back");
page=3;
pushed=0;
}
if(15 < counter && counter < 20)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Americano");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("Back");
page=4;
pushed=0;
}
}//submenu = 1;
//Third page of the menu
if(submenu == 2)
{
if(0 <= counter && counter < 5)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("25%");
lcd.setCursor(0,1);
lcd.print(" 50%");
page=1;
pushed=0;
}
if(5 < counter && counter < 10)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" 25%");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("50%");
page=2;
pushed=0;
}
if(10 < counter && counter < 15)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("75%");
lcd.setCursor(0,1);
lcd.print(" 100%");
page=3;
pushed=0;
}
if(15 < counter && counter < 20)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" 75%");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("100%");
page=4;
pushed=0;
}
}//submenu = 2;
//Forth page of the menu
if(submenu == 3)
{
if(0 <= counter && counter < 5)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("ON");
lcd.setCursor(0,1);
lcd.print(" OFF");
page=1;
pushed=0;
}
if(5 < counter && counter < 10)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" ON");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("OFF");
page=2;
pushed=0;
}
}//submenu = 3;
if(submenu == 4)
{
if(0 <= counter && counter < 5)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("25%");
lcd.setCursor(0,1);
lcd.print(" 50%");
page=1;
pushed=0;
}
if(5 < counter && counter < 10)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" 25%");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("50%");
page=2;
pushed=0;
}
if(10 < counter && counter < 15)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.write(1);
lcd.print("75%");
lcd.setCursor(0,1);
lcd.print(" 100%");
page=3;
pushed=0;
}
if(15 < counter && counter < 20)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" 75%");
lcd.setCursor(0,1);
lcd.write(1);
lcd.print("100%");
page=4;
pushed=0;
}
}//submenu = 4;
}//end of the MENU prints on the LCD
last_counter = counter; //Save the value of the last state
//Now we detect when we push the button
if(digitalRead(push))
{
if(submenu == 1)
{
if(page==1)
{
submenu=0;
counter=1;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Making coffee...");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==2)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Making coffee...");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==3)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Making coffee...");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==4)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Going back... ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(2000);
}
}//end of submenu 1
if(submenu == 2)
{
if(page==1)
{
submenu=0;
counter=1;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Sugar level 25%");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==2)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Sugar level 50%");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==3)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Sugar level 75%");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==4)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Sugar level 100%");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
}//end of submenu 1
if(submenu == 3)
{
if(page==1)
{
submenu=0;
counter=1;
pushed=0;
Ready=0;
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Backlight ON ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==2)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.noBacklight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Backlight OFF");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
}//end of submenu 1
if(submenu == 4)
{
if(page==1)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Volume 25% ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==2)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Volume 50% ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==3)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Volume 75% ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
if(page==4)
{
submenu=0;
counter=0;
pushed=0;
Ready=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Volume 100% ");
lcd.setCursor(0,1);
lcd.print(" Wait ");
delay(4000);
}
}//end of submenu 1
if(submenu == 0 && Ready==1)
{
if(page==1)
{
submenu=1;
counter=0;
pushed=1;
delay(500);
}
if(page==2)
{
submenu=2;
counter=0;
pushed=1;delay(500);
}
if(page==3)
{
submenu=3;
counter=0;
pushed=1;delay(500);
}
if(page==4)
{
submenu=4;
counter=0;
pushed=1;delay(500);
}
}//end of submenu 0
}
//Add limit for the counter. Each line of the menu has 5 points. Since my menu has 4 lines the maximum counter will be from 0 to 20
//If you add more lines for the menu, increase this value
if(counter > 20)
{
counter=20;
}
if(counter < 0)
{
counter=0;
}
}//end void
//Interruption vector
ISR(PCINT0_vect){
clk_State = (PINB & B00000001); //pin 8 state, clock pin?
dt_State = (PINB & B00000010);
if (clk_State != Last_State){
// If the data state is different to the clock state, that means the encoder is rotating clockwise
if (dt_State != clk_State) {
counter ++;
}
else {
counter --;
}
}
Last_State = clk_State; // Updates the previous state of the data with the current state
}