Complex menu for controlling multiple I/O pins
In this video I show you how to set up a relatively complex menu for controlling several I/O pins using a single rotary encoder. I made a GUI for a 1.8" LCD panel which allows you to see and modify the status of the different I/O pins. This kind of menu is very useful when you want to have control over several switches, LEDs or other switchable devices.
Schematics
The above figure shows the wiring scheme of the circuit shown in the video. The I/O expander boards are set up in the following way: SDA is connected to A4 and SCL is connected to A5. The first circuit on the left has its A0-A1-A2 jumpers untouched and it is on the 0x20 address. The middle unit is simply plugged in to the first unit and its A0 jumper is on the left side which gives it the 0x21 address. The last unit is plugged into the middle unit and its A1 (middle) jumper is on the left side which results in the 0x22 i2C address. As I mentioned in the video, the I/O pins are used to pull to ground.
The rotary encoder is simply connected to three I/O pins and the power. The CLK pin has to be an interrupt, which is the D2 in this case.
The display is a bit more complicated. It uses the standard SPI pins, however since the display is 3.3 V compatible, it needs a level shifter. A TXS0108E level shifter is used in this example. The B side takes the 5 V signal and the A side provides the 3.3 V signal. The VCCA on the 3.3 V side is connected to the OE pin, then this pin is connected to the ground by a 10 kOhm resistor. The pins on the two sides (A and B) of the board are connected directly so what goes to A1 appears on B1… and so on. The pin of the display are connected to the Arduino (level shifter) in the following way:
VCC → 3.3 V
GND → GND
CS → D10
Reset → D8
A0 → D9
SDA → D11
SCK → D13
LED → 3.3 V
Another notice for the video demonstration: When you connect some large external devices such as the relay panel I used, you must use an external power supply for it. Do not power those devices from the Arduino! Also, make sure that the ground is shared all across the circuit components.
Arduino source code
#include <Wire.h> #include <SPI.h> #include <Adafruit_ST7735.h> //graphics libraries #include <Adafruit_GFX.h> #define TFT_CS 10 #define TFT_RST 8 #define TFT_DC 9 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); //Defining pins const int RotaryCLK = 2; //CLK pin on the rotary encoder const int RotaryDT = 4; //DT pin on the rotary encoder const int RotarySW = 5; //SW pin on the rotary encoder (Button function) //Statuses of the DT and CLK pins on the encoder int CLKNow; int CLKPrevious; int DTNow; int DTPrevious; int RotaryButtonValue; //stores the button reading float RotaryButtonTime = 0; //timing/debounce volatile int MainMenuCounter = 0; //0,1,2,3,4 - 4 items volatile int PreviousMainMenuCounter = 0; // volatile int Menu1Counter = 0; volatile int PreviousMenu1Counter = 0; // volatile int Menu2Counter = 0; volatile int PreviousMenu2Counter = 0; // volatile int Menu3Counter = 0; volatile int PreviousMenu3Counter = 0; // volatile int Menu4Counter = 0; volatile int PreviousMenu4Counter = 0; //Booleans bool MainMenuChanged = false; bool Menu1Changed = false; bool Menu2Changed = false; bool Menu3Changed = false; bool Menu4Changed = false; bool mainMenuSelected = true; bool Menu1Selected = false; bool Menu2Selected = false; bool Menu3Selected = false; bool Menu4Selected = false; //These are the names in the buttons, you can edit them, but do not use too long names String MainMenuItems[5] = {"MENU 1", "MENU 2", "MENU 3", "MENU 4", "RESET"}; String Menu1Items[9] = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Back"}; String Menu2Items[9] = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Back"}; String Menu3Items[8] = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "OFF", "Back"}; String Menu4Items[8] = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "OFF", "Back"}; //They store whether a pin is active or not bool Menu1Activation[8] = {false, false, false, false, false, false, false, false}; bool Menu2Activation[8] = {false, false, false, false, false, false, false, false}; bool Menu3Activation[7] = {false, false, false, false, false, false, false}; bool Menu4Activation[7] = {false, false, false, false, false, false, false}; uint8_t SwitchPanel1Value = 255; //8 channels (11111111) uint8_t SwitchPanel2Value = 255; uint8_t SwitchPanel3Value = 255; uint8_t SwitchPanel4Value = 255; //6 channels (2x3 channels) void setup() { Wire.begin(); Wire.setClock(400000L); //LED panel Wire.beginTransmission(0x20); Wire.write(B11111111); //Turn all the LEDs OFF Wire.endTransmission(); //RELAY panel Wire.beginTransmission(0x21); Wire.write(B11111111); //Turn all the relays OFF Wire.endTransmission(); //RF panel Wire.beginTransmission(0x22); Wire.write(B11111111); //Turn all the RF switches OFF Wire.endTransmission(); tft.initR(INITR_BLACKTAB); tft.fillScreen(ST7735_BLACK); //Definition of the pins pinMode(2, INPUT); //CLK pinMode(4, INPUT); //DT pinMode(5, INPUT_PULLUP); //SW //Store states CLKPrevious = digitalRead(RotaryCLK); DTPrevious = digitalRead(RotaryDT); //Rotary encoder interrupts attachInterrupt(digitalPinToInterrupt(RotaryCLK), RotaryEncoder, CHANGE); drawMainMenu(); } void loop() { checkMainMenu(); CheckRotaryButton(); checkSubMenus(); } void checkSubMenus() { if (Menu1Changed == true) { tft.setTextSize(1); //set font before printing the menu //Based on the previous menu position, we reset the coloring of the previously highlighted item //(X, Y, WIDTH, HEIGHT) <--- All units are in pixels tft.fillRect (10, 20 + (PreviousMenu1Counter * 15), 96, 9, ST7735_WHITE); tft.setCursor(20, 21 + (PreviousMenu1Counter * 15)); //Text cursor (X,Y) tft.setTextColor(ST7735_BLACK); tft.print(Menu1Items[PreviousMenu1Counter]); //Highlight the current position in the menu tft.fillRect (10, 20 + (Menu1Counter * 15), 96, 9, ST7735_GREEN); tft.setCursor(20, 21 + (Menu1Counter * 15)); tft.setTextColor(ST7735_RED); tft.print(Menu1Items[Menu1Counter]); if (Menu1Counter < 8) //We don't print anything on the back button (i = 8) { if (Menu1Activation[Menu1Counter] == true) { tft.fillRect (109, 21 + (Menu1Counter * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (Menu1Counter * 15), 6, 7, ST7735_RED); } } Menu1Changed = false; PreviousMenu1Counter = Menu1Counter; return; //jump out } if (Menu2Changed == true) { tft.setTextSize(1); tft.fillRect (10, 20 + (PreviousMenu2Counter * 15), 96, 9, ST7735_WHITE); tft.setCursor(20, 21 + (PreviousMenu2Counter * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu2Items[PreviousMenu2Counter]); tft.fillRect (10, 20 + (Menu2Counter * 15), 96, 9, ST7735_GREEN); tft.setCursor(20, 21 + (Menu2Counter * 15)); tft.setTextColor(ST7735_RED); tft.print(Menu2Items[Menu2Counter]); if (Menu2Counter < 8) { if (Menu2Activation[Menu2Counter] == true) { tft.fillRect (109, 21 + (Menu2Counter * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (Menu2Counter * 15), 6, 7, ST7735_RED); } } Menu2Changed = false; PreviousMenu2Counter = Menu2Counter; return; } if (Menu3Changed == true) { tft.setTextSize(1); tft.fillRect (10, 20 + (PreviousMenu3Counter * 15), 96, 9, ST7735_WHITE); tft.setCursor(20, 21 + (PreviousMenu3Counter * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu3Items[PreviousMenu3Counter]); tft.fillRect (10, 20 + (Menu3Counter * 15), 96, 9, ST7735_GREEN); tft.setCursor(20, 21 + (Menu3Counter * 15)); tft.setTextColor(ST7735_RED); tft.print(Menu3Items[Menu3Counter]); Menu3Changed = false; PreviousMenu3Counter = Menu3Counter; return; } if (Menu4Changed == true) { tft.setTextSize(1); tft.fillRect (10, 20 + (PreviousMenu4Counter * 15), 96, 9, ST7735_WHITE); tft.setCursor(20, 21 + (PreviousMenu4Counter * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu4Items[PreviousMenu4Counter]); tft.fillRect (10, 20 + (Menu4Counter * 15), 96, 9, ST7735_GREEN); tft.setCursor(20, 21 + (Menu4Counter * 15)); tft.setTextColor(ST7735_RED); tft.print(Menu4Items[Menu4Counter]); Menu4Changed = false; PreviousMenu4Counter = Menu4Counter; return; } } void checkMainMenu() { if (MainMenuChanged == true) { tft.setTextSize(2); //Select a larger fonts (because of the larger buttons) tft.fillRect (10, 18 + (PreviousMainMenuCounter * 25), 108, 20, ST7735_WHITE); tft.setCursor(20, 21 + (PreviousMainMenuCounter * 25)); tft.setTextColor(ST7735_BLACK); tft.print(MainMenuItems[PreviousMainMenuCounter]); tft.fillRect (10, 18 + (MainMenuCounter * 25), 108, 20, ST7735_GREEN); tft.setCursor(20, 21 + (MainMenuCounter * 25)); tft.setTextColor(ST7735_RED); tft.print(MainMenuItems[MainMenuCounter]); PreviousMainMenuCounter = MainMenuCounter; } MainMenuChanged = false; } void RotaryEncoder() { if (Menu1Selected == true) { CLKNow = digitalRead(RotaryCLK); //Read the state of the CLK pin // If last and current state of CLK are different, then a pulse occurred if (CLKNow != CLKPrevious && CLKNow == 1) { // If the DT state is different than the CLK state then // the encoder is rotating in A direction, so we increase if (digitalRead(RotaryDT) != CLKNow) { if (Menu1Counter < 8) { Menu1Counter++; } else //if the next increment would change the value to 8, we "manually" set the value to 0 { Menu1Counter = 0; } } else //otherwide we decrease the value of the variable { if (Menu1Counter < 1) //if the next increment would change the value to -1, we "manually" set the value to 8 { Menu1Counter = 8; } else { Menu1Counter--; } } Menu1Changed = true; //Let the code know that the value is updated } CLKPrevious = CLKNow; } else if (Menu2Selected == true) { CLKNow = digitalRead(RotaryCLK); if (CLKNow != CLKPrevious && CLKNow == 1) { if (digitalRead(RotaryDT) != CLKNow) { if (Menu2Counter < 8) { Menu2Counter++; } else { Menu2Counter = 0; } } else { if (Menu2Counter < 1) { Menu2Counter = 8; } else { Menu2Counter--; } } Menu2Changed = true; } CLKPrevious = CLKNow; } else if (Menu3Selected == true) { CLKNow = digitalRead(RotaryCLK); if (CLKNow != CLKPrevious && CLKNow == 1) { if (digitalRead(RotaryDT) != CLKNow) { if (Menu3Counter < 7) { Menu3Counter++; } else { Menu3Counter = 0; } } else { if (Menu3Counter < 1) { Menu3Counter = 7; } else { Menu3Counter--; } } Menu3Changed = true; } CLKPrevious = CLKNow; } else if (Menu4Selected == true) { CLKNow = digitalRead(RotaryCLK); // if (CLKNow != CLKPrevious && CLKNow == 1) { if (digitalRead(RotaryDT) != CLKNow) { if (Menu4Counter < 7) { Menu4Counter++; } else { Menu4Counter = 0; } } else { if (Menu4Counter < 1) { Menu4Counter = 7; } else { Menu4Counter--; } } Menu4Changed = true; } CLKPrevious = CLKNow; } else { CLKNow = digitalRead(RotaryCLK); if (CLKNow != CLKPrevious && CLKNow == 1) { if (digitalRead(RotaryDT) != CLKNow) { if (MainMenuCounter < 4) { MainMenuCounter++; } else { MainMenuCounter = 0; } } else { if (MainMenuCounter < 1) { MainMenuCounter = 4; } else { MainMenuCounter--; } } MainMenuChanged = true; } CLKPrevious = CLKNow; } } void drawMainMenu() { tft.fillScreen(ST7735_BLACK); //Erase the whole previous screen before redrawing the main menu tft.setTextSize(1); //Small font tft.setCursor(0, 0); //Text cursor (X,Y) tft.setTextColor(ST7735_WHITE); //Font color == WHITE tft.print("Menu random top text"); //Text (single line) ---> you can write anything here but keep it short tft.setTextSize(2); //set font large before printing the menu for (int i = 0; i < 5; i++) //iterate over the buttons and draw them, then fills them up with text { tft.fillRect (10, 18 + (i * 25), 108, 20, ST7735_WHITE); //white background box tft.setCursor(20, 21 + (i * 25)); //Text cursor (X,Y) tft.setTextColor(ST7735_BLACK); //Font color tft.print(MainMenuItems[i]); //ith item (text) in the MainMenuItems[] array } //Bottom text tft.setTextSize(1); //set font size to small tft.setCursor(10, 150); //Text cursor tft.setTextColor(ST7735_WHITE); //Font color tft.print("Bottom text v1.0"); //Bottom text, for example version number, or "signature"...etc } void drawMenu_1() { for (int i = 0; i < 9; i++) { tft.fillRect (10, 20 + (i * 15), 108, 9, ST7735_WHITE); tft.setCursor(20, 21 + (i * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu1Items[i]); if (i < 8) //We don't print anything on the back button (i = 8) { if (Menu1Activation[i] == true) { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); } } } } void drawMenu_2() { for (int i = 0; i < 9; i++) { tft.fillRect (10, 20 + (i * 15), 108, 9, ST7735_WHITE); tft.setCursor(20, 21 + (i * 15)); //Text cursor x,y tft.setTextColor(ST7735_BLACK); tft.print(Menu2Items[i]); if (i < 8) { if (Menu2Activation[i] == true) { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); } } } } void drawMenu_3() { for (int i = 0; i < 8; i++) { tft.fillRect (10, 20 + (i * 15), 108, 9, ST7735_WHITE); tft.setCursor(20, 21 + (i * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu3Items[i]); if (i < 7) { if (Menu3Activation[i] == true) { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); } } } } void drawMenu_4() { for (int i = 0; i < 8; i++) { tft.fillRect (10, 20 + (i * 15), 108, 9, ST7735_WHITE); tft.setCursor(20, 21 + (i * 15)); tft.setTextColor(ST7735_BLACK); tft.print(Menu4Items[i]); if (i < 7) { if (Menu4Activation[i] == true) { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_GREEN); } else { tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); } } } } void CheckRotaryButton() { RotaryButtonValue = digitalRead(RotarySW); //read the button state if (RotaryButtonValue == 0) //0 and 1 can differ based on the wiring { if (millis() - RotaryButtonTime > 1000) //1 sec debounce { if (mainMenuSelected == true) { switch (MainMenuCounter) { case 0: //Main Menu 1 mainMenuSelected = false; //We are not in the main menu anymore Menu1Selected = true; //We jumped into the Menu 1 tft.fillScreen(ST7735_BLACK); //erase the previous screen //Menu title tft.setTextSize(1); tft.setCursor(0, 0); tft.setTextColor(ST7735_WHITE); tft.print("Menu 1 items"); //Title of the 1st submenu drawMenu_1(); //Draw the submenu break; // case 1: //Main Menu 2 mainMenuSelected = false; Menu2Selected = true; tft.fillScreen(ST7735_BLACK); tft.setTextSize(1); tft.setCursor(0, 0); tft.setTextColor(ST7735_WHITE); tft.print("Menu 2 items"); drawMenu_2(); break; // case 2: //Main Menu 3 mainMenuSelected = false; Menu3Selected = true; tft.fillScreen(ST7735_BLACK); tft.setTextSize(1); tft.setCursor(0, 0); tft.setTextColor(ST7735_WHITE); tft.print("Menu 3 items"); drawMenu_3(); break; // case 3: //Open Menu 4 mainMenuSelected = false; Menu4Selected = true; tft.fillScreen(ST7735_BLACK); //top text tft.setTextSize(1); tft.setCursor(0, 0); tft.setTextColor(ST7735_WHITE); tft.print("Menu 4 items"); drawMenu_4(); break; case 4: //RESET - default values SwitchPanel1Value = 255; SwitchPanel2Value = 255; SwitchPanel3Value = 255; SwitchPanel4Value = 255; Wire.beginTransmission(0x20); Wire.write(B11111111); Wire.endTransmission(); delay(1000); Wire.beginTransmission(0x21); Wire.write(B11111111); Wire.endTransmission(); delay(1000); Wire.beginTransmission(0x22); Wire.write(B11111111); Wire.endTransmission(); delay(1000); //Reset the booleans too for (int i = 0; i < 8; i++) { Menu1Activation[i] = false; Menu2Activation[i] = false; if (i < 7) { Menu3Activation[i] = false; Menu4Activation[i] = false; } } break; } RotaryButtonTime = millis(); } else if (Menu1Selected == true) { switch (Menu1Counter) { case 0: //Submenu 1 Item 1 Menu1Activation[0] = !Menu1Activation[0]; if (Menu1Activation[0] == true) { SwitchPanel1Value = SwitchPanel1Value & B11111110; // P7<-----P0 //Binary is read backwards (last digit is P0, first digit is P7). //The circuit SINKS! and does not power. //1 does nothing, 0 switches the component on. } else { SwitchPanel1Value = SwitchPanel1Value | B00000001; } break; // case 1: //Submenu 1 Item 2 Menu1Activation[1] = !Menu1Activation[1]; if (Menu1Activation[1] == true) { SwitchPanel1Value = SwitchPanel1Value & B11111101; } else { SwitchPanel1Value = SwitchPanel1Value | B00000010; } break; // case 2: //Submenu 1 Item 3 Menu1Activation[2] = !Menu1Activation[2]; if (Menu1Activation[2] == true) { SwitchPanel1Value = SwitchPanel1Value & B11111011; } else { SwitchPanel1Value = SwitchPanel1Value | B00000100; } break; // case 3: //Submenu 1 Item 4 Menu1Activation[3] = !Menu1Activation[3]; if (Menu1Activation[3] == true) { SwitchPanel1Value = SwitchPanel1Value & B11110111; } else { SwitchPanel1Value = SwitchPanel1Value | B00001000; } break; // case 4: //Submenu 1 Item 5 Menu1Activation[4] = !Menu1Activation[4]; if (Menu1Activation[4] == true) { SwitchPanel1Value = SwitchPanel1Value & B11101111; } else { SwitchPanel1Value = SwitchPanel1Value | B00010000; } break; // case 5: //Submenu 1 Item 6 Menu1Activation[5] = !Menu1Activation[5]; if (Menu1Activation[5] == true) { SwitchPanel1Value = SwitchPanel1Value & B11011111; } else { SwitchPanel1Value = SwitchPanel1Value | B00100000; } break; // case 6: //Submenu 1 Item 7 Menu1Activation[6] = !Menu1Activation[6]; if (Menu1Activation[6] == true) { SwitchPanel1Value = SwitchPanel1Value & B10111111; } else { SwitchPanel1Value = SwitchPanel1Value | B01000000; } break; // case 7: //Submenu 1 Item 8 Menu1Activation[7] = !Menu1Activation[7]; if (Menu1Activation[7] == true) { SwitchPanel1Value = SwitchPanel1Value & B01111111; } else { SwitchPanel1Value = SwitchPanel1Value | B10000000; } break; // case 8: //Submenu 1 back button mainMenuSelected = true; Menu1Selected = false; drawMainMenu(); RotaryButtonTime = millis(); return; //jump out from the whole stuff, otherwise the Menu1Changed will be set to true break; } //Send the new value to the corresponding I/O board Wire.beginTransmission(0x20); Wire.write(SwitchPanel1Value); Wire.endTransmission(); Menu1Changed = true; RotaryButtonTime = millis(); } else if (Menu2Selected == true) { switch (Menu2Counter) { case 0: //Submenu 2 Item 1 Menu2Activation[0] = !Menu2Activation[0]; if (Menu2Activation[0] == true) { SwitchPanel2Value = SwitchPanel2Value & B11111110; } else { SwitchPanel2Value = SwitchPanel2Value | B00000001; } break; // case 1: //Submenu 2 Item 2 Menu2Activation[1] = !Menu2Activation[1]; if (Menu2Activation[1] == true) { SwitchPanel2Value = SwitchPanel2Value & B11111101; } else { SwitchPanel2Value = SwitchPanel2Value | B00000010; } break; // case 2: //Submenu 2 Item 3 Menu2Activation[2] = !Menu2Activation[2]; if (Menu2Activation[2] == true) { SwitchPanel2Value = SwitchPanel2Value & B11111011; } else { SwitchPanel2Value = SwitchPanel2Value | B00000100; } break; // case 3: //Submenu 2 Item 4 Menu2Activation[3] = !Menu2Activation[3]; if (Menu2Activation[3] == true) { SwitchPanel2Value = SwitchPanel2Value & B11110111; } else { SwitchPanel2Value = SwitchPanel2Value | B00001000; } break; // case 4: //Submenu 2 Item 5 Menu2Activation[4] = !Menu2Activation[4]; if (Menu2Activation[4] == true) { SwitchPanel2Value = SwitchPanel2Value & B11101111; } else { SwitchPanel2Value = SwitchPanel2Value | B00010000; } break; // case 5: //Submenu 2 Item 6 Menu2Activation[5] = !Menu2Activation[5]; if (Menu2Activation[5] == true) { SwitchPanel2Value = SwitchPanel2Value & B11011111; } else { SwitchPanel2Value = SwitchPanel2Value | B00100000; } break; // case 6: //Submenu 2 Item 7 Menu2Activation[6] = !Menu2Activation[6]; if (Menu2Activation[6] == true) { SwitchPanel2Value = SwitchPanel2Value & B10111111; } else { SwitchPanel2Value = SwitchPanel2Value | B01000000; } break; // case 7: //Submenu 2 Item 8 Menu2Activation[7] = !Menu2Activation[7]; if (Menu2Activation[7] == true) { SwitchPanel2Value = SwitchPanel2Value & B01111111; } else { SwitchPanel2Value = SwitchPanel2Value | B10000000; } break; // case 8: //Submenu 2 back button mainMenuSelected = true; Menu2Selected = false; drawMainMenu(); RotaryButtonTime = millis(); return; break; } Wire.beginTransmission(0x21); Wire.write(SwitchPanel2Value); Wire.endTransmission(); Menu2Changed = true; RotaryButtonTime = millis(); } else if (Menu3Selected == true) { //RF1-RF6A : P0, P1, P2 ResetMenu3Activation(); //First, deactivate the previous switch (we cannot have 2 concurrent switch states) switch (Menu3Counter) { case 0: //Submenu 3 Item 1 Menu3Activation[0] = true; SwitchPanel3Value = B11111000; //LLL break; // case 1: //Submenu 3 Item 2 Menu3Activation[1] = true; SwitchPanel3Value = B11111001; //HLL break; // case 2: //Submenu 3 Item 3 Menu3Activation[2] = true; SwitchPanel3Value = B11111010; //LHL break; // case 3: //Submenu 3 Item 4 Menu3Activation[3] = true; SwitchPanel3Value = B11111011; //HHL break; // case 4: //Submenu 3 Item 5 Menu3Activation[4] = true; SwitchPanel3Value = B11111100; //LLH break; // case 5: //Submenu 3 Item 6 Menu3Activation[5] = true; SwitchPanel3Value = B11111101; //HLH break; // case 6: //Submenu 3 Item 7 -> OFF Menu3Activation[6] = true; SwitchPanel3Value = B11111111; //HHH = OFF break; // case 7: //Submenu 3 back button mainMenuSelected = true; Menu3Selected = false; RotaryButtonTime = millis(); drawMainMenu(); return; break; } if (Menu3Counter != 7) { //This part redraws the green rectangle. In this menu, there's only 1 active item at a time tft.fillRect (109, 21 + (Menu3Counter * 15), 6, 7, ST7735_GREEN); } Wire.beginTransmission(0x22); Wire.write(SwitchPanel3Value & SwitchPanel4Value); Wire.endTransmission(); Menu3Changed = true; RotaryButtonTime = millis(); } else if (Menu4Selected == true) { //RF1-6 B: P4, P5, P6 ResetMenu4Activation(); switch (Menu4Counter) { case 0: //Submenu 4 Item 1 Menu4Activation[0] = true; SwitchPanel4Value = B11000111; //LLL break; // case 1: //Submenu 4 Item 2 Menu4Activation[1] = true; SwitchPanel4Value = B11001111; //HLL break; // case 2: //Submenu 4 Item 3 Menu4Activation[2] = true; SwitchPanel4Value = B11010111; //LHL break; // case 3: //Submenu 4 Item 4 Menu4Activation[3] = true; SwitchPanel4Value = B11011111; //HHL break; // case 4: //Submenu 4 Item 5 Menu4Activation[4] = true; SwitchPanel4Value = B11100111; //LLH break; // case 5: //Submenu 4 Item 6 Menu4Activation[5] = true; SwitchPanel4Value = B11101111; //HLH break; // case 6: //Submenu 4 Item 7 = OFF Menu4Activation[6] = true; SwitchPanel4Value = B11111111; //HHH = OFF break; // case 7: //Submenu 4 back button mainMenuSelected = true; Menu4Selected = false; RotaryButtonTime = millis(); drawMainMenu(); return; break; } if (Menu4Counter != 7) { tft.fillRect (109, 21 + (Menu4Counter * 15), 6, 7, ST7735_GREEN); } Wire.beginTransmission(0x22); Wire.write(SwitchPanel3Value & SwitchPanel4Value); Wire.endTransmission(); Menu4Changed = true; RotaryButtonTime = millis(); } } } } void ResetMenu3Activation() { if (Menu3Counter != 7) { for (int i = 0; i < 7; i++) { if (Menu3Activation[i] == true) { Menu3Activation[i] = false; tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); //paint the ith rectangle red } } } } void ResetMenu4Activation() { if (Menu4Counter != 7) { for (int i = 0; i < 7; i++) { if (Menu4Activation[i] == true) { Menu4Activation[i] = false; tft.fillRect (109, 21 + (i * 15), 6, 7, ST7735_RED); //paint the ith rectangle red } } } }