Instantly share code, notes, and snippets.
-
Save adrianbn/6d833e594e70348e931d937e5f573342 to your computer and use it in GitHub Desktop.
Menu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <LiquidCrystal.h> | |
#include <Keypad_I2C.h> | |
#define I2C_PFC8574_ADDR 0x20 | |
#define I2C_DS1307_ADDR 0x68 | |
// PIN DEFINITIONS | |
const int LED_PIN = 16; | |
const int LCD_BKL_PIN = 6; | |
const int PUMP_PIN = 5; | |
// LCD | |
// initialize the library with the numbers of the interface pins | |
LiquidCrystal lcd(8, 9, 13, 12, 11, 10); | |
const int LCD_BKL_PWM = 170; // (255 * 3.3)/5 = 168.3 But measured 170 is 3.1V | |
const int LCD_ROWS = 2; | |
const int LCD_COLS = 16; | |
const int NUM_MENUS = 4; | |
int current_menu = 0; | |
int frame = 0; | |
int cursor_pos = 0; | |
String menu_items[] = {"Schedule 1", "Schedule 2", "Start Pump", "Stop Pump"}; | |
// Keypad | |
const byte ROWS = 4; // four rows | |
const byte COLS = 4; // four columns | |
//define the two-dimensional array on the buttons of the keypads | |
char hexa_keys[ROWS][COLS] = {{'1','2','3','A'}, | |
{'4','5','6','B'}, | |
{'7','8','9','C'}, | |
{'*','0','#','D'} | |
}; | |
byte rowPins[ROWS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad | |
byte colPins[COLS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad | |
Keypad_I2C key_pad(makeKeymap(hexa_keys), rowPins, colPins, ROWS, COLS, I2C_PFC8574_ADDR); | |
const char UP = 'C'; | |
const char DOWN = 'D'; | |
const char CONFIRM = '*'; | |
const char BACK = '#'; | |
// As opposed to Python, % of negative numbers is, welp, negative. | |
int mod(int x, int y) { | |
return x<0 ? ((x + 1) % y) + y - 1 : x % y; | |
} | |
void displayMenu() { | |
for (int i=0; i < LCD_ROWS; i++) { | |
lcd.setCursor(1,i); | |
lcd.print(menu_items[(i + frame) % NUM_MENUS]); | |
} | |
} | |
void displayCursor() { | |
printCursor((cursor_pos + frame) % LCD_ROWS); | |
} | |
void printCursor(int row) { | |
for (int i=0; i < LCD_ROWS; i++) { | |
if (i != row) { | |
lcd.setCursor(0, i); | |
lcd.print(" "); | |
} | |
} | |
lcd.setCursor(0, row); | |
lcd.print(">"); | |
} | |
void updateTimeMenu(int start_pos, int sched) { | |
int idx = 0; | |
lcd.setCursor(start_pos, 0); | |
lcd.blink(); | |
char key_press = NULL; | |
while ((idx < DATE_LENGTH) && !(key_press == BACK || key_press == CONFIRM)) { | |
key_press = key_pad.getKey(); | |
if (key_press < '9' && key_press > '0') { | |
if ((idx == 0 && key_press > '2') || | |
(idx == 1 && key_press > '3' && schedules[sched].date[idx - 1] == '2') || | |
(idx == 2 && key_press > '5')) { | |
continue; | |
} | |
schedules[sched].date[idx] = key_press; | |
lcd.print(key_press); | |
if (idx == 1) | |
lcd.print(":"); | |
idx++; | |
} | |
} | |
lcd.noBlink(); | |
} | |
void updateDurationMenu(int start_pos, int sch) { | |
char duration[2]; | |
String d = String(schedules[sch].duration); | |
int idx = 0; | |
char key_press = NULL; | |
lcd.setCursor(start_pos, 1); | |
lcd.blink(); | |
while ((idx < DURATION_LENGTH) && !(key_press == BACK || key_press == CONFIRM)) { | |
key_press = key_pad.getKey(); | |
if (key_press <= '9' && key_press >= '0') { | |
duration[idx] = key_press; | |
lcd.print(key_press); | |
idx++; | |
} | |
} | |
if (idx == 1) { // only first digit entered | |
duration[1] = d.charAt(d.length() - 1); | |
} | |
schedules[sch].duration = String(duration).toInt(); | |
lcd.noBlink(); | |
} | |
void updateScheduleMenu(int sch) { | |
int cur = 0; | |
printCursor(cur); | |
lcd.setCursor(1,0); | |
lcd.print("Time: "); | |
printTime(schedules[sch].date); | |
lcd.setCursor(1,1); | |
lcd.print("Duration: "); | |
printDuration(schedules[sch].duration); | |
lcd.print("min"); | |
char key_press = NULL; | |
while (key_press != BACK) { | |
key_press = key_pad.getKey(); | |
switch(key_press) { | |
case CONFIRM: | |
if (cur == 0) { | |
updateTimeMenu(7, sch); | |
} else{ | |
updateDurationMenu(11, sch); | |
} | |
break; | |
case DOWN: | |
cur = (cur + 1) % LCD_ROWS; | |
printCursor(cur); | |
break; | |
} | |
} | |
} | |
void startPumpMenu() { | |
lcd.setCursor(0,0); | |
lcd.print(" Pump is now on"); | |
digitalWrite(LED_PIN, HIGH); | |
analogWrite(PUMP_PIN, 255); | |
// Wait for a key press | |
char key_press = NULL; | |
while (!(key_press = key_pad.getKey())) { | |
if (key_press == BACK) break; | |
} | |
} | |
void stopPumpMenu() { | |
lcd.setCursor(0,0); | |
lcd.print(" Pump is now off"); | |
digitalWrite(LED_PIN, LOW); | |
analogWrite(PUMP_PIN, 0); | |
// Wait for a key press | |
char key_press = NULL; | |
while (!(BACK == key_pad.getKey())); | |
} | |
void goIntoMenu() { | |
lcd.clear(); | |
switch(cursor_pos) { | |
case 0: | |
case 1: | |
updateScheduleMenu(cursor_pos); | |
break; | |
case 2: | |
startPumpMenu(); | |
break; | |
case 3: | |
stopPumpMenu(); | |
break; | |
} | |
lcd.clear(); | |
} | |
char mainMenu() { | |
char key_press = key_pad.getKey(); | |
if (key_press) { | |
lcd.clear(); | |
lcdOn(); | |
} | |
switch(key_press) { | |
case BACK: | |
break; | |
case CONFIRM: | |
goIntoMenu(); | |
break; | |
case DOWN: | |
cursor_pos = mod((cursor_pos + 1), NUM_MENUS); | |
if ((cursor_pos + frame) % 2 == 0) | |
frame = mod((frame + 1), NUM_MENUS); | |
break; | |
case UP: | |
cursor_pos = mod((cursor_pos - 1), NUM_MENUS); | |
if ((cursor_pos + frame) % 2 != 0) | |
frame = mod((frame - 1), NUM_MENUS); | |
break; | |
default: | |
if (key_press != NO_KEY) { | |
Serial.print("Pressed: "); | |
Serial.println(key_press); | |
} | |
} | |
return key_press; | |
} | |
void setup() { | |
// Serial for debugging | |
Serial.begin(9600); | |
// Configure in/out pins | |
pinMode(LED_PIN, OUTPUT); | |
pinMode(LCD_BKL_PIN, OUTPUT); // The LCD Backlight control | |
// Init the I2C bus | |
Wire.begin(); | |
// Init the Keypad library | |
key_pad.begin(); | |
// End of Keypad init | |
// We have a 16x2 (column/row) LCD | |
lcd.begin(LCD_COLS, LCD_ROWS); | |
lcdOff(); | |
lcd.clear(); | |
} | |
void loop() { | |
displayMenu(); | |
displayCursor(); | |
mainMenu(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment