#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// 'icon_dashboard', 16x16px
const unsigned char bitmap_icon_dashboard [] PROGMEM = {
0x07, 0xe0, 0x18, 0x18, 0x21, 0x24, 0x50, 0x02, 0x48, 0x0a, 0x84, 0x01, 0x83, 0x81, 0xa2, 0x45,
0x82, 0x41, 0x81, 0x81, 0xa0, 0x05, 0x40, 0x02, 0x4b, 0xd2, 0x23, 0xc4, 0x18, 0x18, 0x07, 0xe0
};
// 'icon_3dcube', 16x16px
const unsigned char bitmap_icon_3dcube [] PROGMEM = {
0x00, 0x00, 0x01, 0x80, 0x07, 0x60, 0x19, 0x18, 0x61, 0x06, 0x51, 0x0a, 0x45, 0xa2, 0x41, 0x02,
0x45, 0x22, 0x41, 0x02, 0x45, 0xa2, 0x51, 0x0a, 0x61, 0x06, 0x19, 0x18, 0x07, 0x60, 0x01, 0x80
};
// 'icon_knob_over_oled', 16x16px
const unsigned char bitmap_icon_knob_over_oled [] PROGMEM = {
0x00, 0x00, 0x1f, 0xf0, 0x13, 0x50, 0x1b, 0xb0, 0x11, 0x50, 0x1f, 0xf0, 0x03, 0x80, 0x01, 0x00,
0x00, 0x00, 0x09, 0x20, 0x49, 0x24, 0x20, 0x08, 0x00, 0x01, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 384)
const unsigned char* bitmap_icons[3] = {
bitmap_icon_dashboard,
bitmap_icon_3dcube,
bitmap_icon_knob_over_oled
};
// 'scrollbar_background', 8x64px
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00
};
// 'item_sel_outline', 128x21px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0
};
const int NUM_ITEMS = 8; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Dashboard" },
{ "Settings" },
{ "Instruction" }
};
// note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
const byte numRows = 4;
const byte numCols = 4;
char keys[numRows][numCols] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[numRows] = {19, 18, 5, 4};
byte colPins[numCols] = {2, 15, 13, 12};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, numRows, numCols);
// Define states for menu
enum MenuState {
MAIN_MENU,
SUB_MENU,
PARAMETER_MENU
};
MenuState menuState = MAIN_MENU;
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();
}
void loop() {
display.clearDisplay();
switch (menuState) {
case MAIN_MENU:
displayMainMenu();
break;
case SUB_MENU:
displaySubMenu();
break;
case PARAMETER_MENU:
displayDashboard();
break;
default:
break;
}
display.display();
char key = keypad.getKey();
if (key != NO_KEY) {
switch (menuState) {
case MAIN_MENU:
switch (key) {
case '1':
menuState = PARAMETER_MENU;
break;
case '2':
menuState = SUB_MENU;
break;
default:
break;
}
break;
case SUB_MENU:
// Handle submenu options
if (key == '*') {
menuState = MAIN_MENU;
}
else if (key >= '1' && key <= NUM_SUBMENU_OPTIONS + '0') {
int optionIndex = key - '0' - 1;
if (optionIndex >= 0 && optionIndex < NUM_SUBMENU_OPTIONS) {
submenuFunctions[optionIndex]();
}
}
break;
case PARAMETER_MENU:
// Handle dashboardmenu options
if (key == '*') {
menuState = MAIN_MENU ;
}
break;
default:
break;
}
}
}
void print_icon(String icon_text, int column, int row, int text_size , bool bold) {
display.setTextSize(text_size);
display.setTextColor(SSD1306_WHITE);
if (bold) {
display.setCursor(column + 0.5, row + 0.5);
display.println(icon_text);
}
display.setCursor(column, row);
display.println(icon_text);
}
// Define submenu options and their corresponding functions
String submenuOptions[] = {"Humidity", "Temperature", "pH Value", "E.Conductivity", "LDR", "Exhaust Fan" , "Misting" , "Heating", "Wifi"};
void (*submenuFunctions[])() = {submenuFunction1, submenuFunction2, submenuFunction3, submenuFunction4, submenuFunction5, submenuFunction6};
const int NUM_SUBMENU_OPTIONS = sizeof(submenuOptions) / sizeof(submenuOptions[0]);
void displayMainMenu() {
print_icon("Dashboard", 20, 10, 1.5,true);
print_icon("Settings", 20, 30, 1.5,true);
print_icon("Instruction", 20, 50, 1.5,true);
}
void displaySubMenu() {
for (int i = 0; i < NUM_SUBMENU_OPTIONS; i++) {
print_icon(submenuOptions[i], 10, 10 + i * 10, 1, false);
}
}
// Variables to store the entered humidity
String humidity = "";
// Variables to store the entered temperature
String temperature = "";
void displayDashboard() {
print_icon("T1 , T2 :",10,10,1,false);
print_icon("SV: " + temperature ,10,30,1,false);
print_icon("HUMIDITY :",10,20,1,false);
print_icon("SV: " + humidity ,10,30,1,false);
print_icon("PV: ",10,40,1,false);
print_icon("pH : ",10,50,1,false);
print_icon("LDR : ",10,60,1,false);
}
void submenuFunction1() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Set H : ");
// Display the current temperature string
display.setCursor(0, 20);
display.println(humidity);
display.display();
while (true) {
char key = keypad.getKey();
if (key != NO_KEY) {
if (key == '#') { // Exit temperature input mode
break;
} else if (key == 'D') { // Clear entered temperature
humidity = "";
} else if (isdigit(key)) { // Append digit to temperature
humidity += key;
}
// Update displayed temperature
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Set H : ");
display.setCursor(0, 20);
display.println(humidity);
display.display();
}
}
// After exiting the loop, you can convert the entered temperature string to an integer
int humidityValue = humidity.toInt();
// Can use the tempValue variable for further processing
}
// Handle submenu option 2
void submenuFunction2() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Set T : ");
// Display the current temperature string
display.setCursor(0, 20);
display.println(temperature);
display.display();
while (true) {
char key = keypad.getKey();
if (key != NO_KEY) {
if (key == '#') { // Exit temperature input mode
break;
} else if (key == 'D') { // Clear entered temperature
temperature = "";
} else if (isdigit(key)) { // Append digit to temperature
temperature += key;
}
// Update displayed temperature
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Set T : ");
display.setCursor(0, 20);
display.println(temperature);
display.display();
}
}
// After exiting the loop, you can convert the entered temperature string to an integer
int tempValue = temperature.toInt();
// Can use the tempValue variable for further processing
}
void submenuFunction3() {
// Handle submenu option 3
}
void submenuFunction4() {
// Handle submenu option 4
}
void submenuFunction5() {
// Handle submenu option 5
}
void submenuFunction6() {
// Handle submenu option 6
}