// /*
// * MARK VAN VEGGEL
// * ARDUINO LCD MENU V0.1
// * YOUTUBE.COM/AMPSOURCE
// *
// */
// #include <OneButton.h>
// #include <Encoder.h>
// #include <Wire.h>
// #include <LCD.h>
// #include <LiquidCrystal_I2C.h>
// LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);
// // ROTARY ENCODER
// long oldPosition = 0;
// int encoderDTpin = 2;
// int encoderCLKpin = 3;
// Encoder myEnc(encoderDTpin, encoderCLKpin);
// int buttonPin = 8;
// OneButton button0(buttonPin, true);
// // MENU ARRAY
// // First number in array = amount of menu items in root layer. Same goes for next layer. (Example: first value in array is 4. This means Layer 0 has 4 menu items. Layer 1 has only 2 menu items.)
// // First number infront of menu text is the layer number that item points to. (Example: 1_Rotation points to Layer 1)
// // Second number infront of menu text is the number of the value connected to that menu item in the values array. (Example: 15Direction points to position 5 in the values array)
// String menu[] = {"4","1__Rotation","056Active","3__Watches","4__Item4", // Layer 0
// "3","100Rotations","105Direction","109Speed", // Layer 1
// "3","256Active","2__Item2.2","2__Item2.3", // Layer 2
// "4","4__Watch 1","3__Watch 2","3__Watch 3","3__Watch 4", // Layer 3
// "2","4__Item3.1.1","4__Item3.1.2"}; // Layer 4
// // VALUES ARRAY
// // TYPES, 1 numeric / 2 character value range
// // 1 - type,value,increments,min,max
// // 2 - type,starting value in options array,lowest value options array,max value options array
// int values[] = {1,11,25,50,1450, //0-4 WATCH1
// 2,2,0,2, //5-8
// 1,600,25,75,600, //9-13
// 1,11,25,50,1450, //14-18 WATCH2
// 2,2,0,2, //19-22
// 1,600,25,75,600, //23-27
// 1,11,25,50,1450, //28-32 WATCH3
// 2,2,0,2, //33-36
// 1,600,25,75,600, //37-41
// 1,11,25,50,1450, //42-46 WATCH4
// 2,2,0,2, //47-50
// 1,600,25,75,600, //51-55
// 2,4,3,4, //56-59 WATCH1 ACTIVE
// 2,4,3,4, //60-63 WATCH2 ACTIVE
// 2,4,3,4, //64-67 WATCH3 ACTIVE
// 2,4,3,4}; //68-71 WATCH4 ACTIVE
// String options[] = {"CW","CCW","MIX",
// "No","Yes"};
// // Custom character for LCD.
// byte cursor[8] = {
// 0b10000,
// 0b10000,
// 0b01000,
// 0b00110,
// 0b01000,
// 0b10000,
// 0b10000,
// 0b00000
// };
// byte watch[8] = {
// 0b01110,
// 0b01110,
// 0b11011,
// 0b10001,
// 0b10001,
// 0b11011,
// 0b01110,
// 0b01110
// };
// int currentType = 0;
// int value = 0;
// int numIncr = 0;
// int Min = 0;
// int Max = 0;
// int currentLayer = 0;
// int lastLayer = 99;
// int currentLength = menu[0].toInt();
// int currentPosition = 0;
// int currentSelect = 1;
// int currentChange = 0;
// String currentPress = "";
// float currentlcdLayerFloat = 0;
// int currentlcdLayer = 0;
// int lastlcdLayer = 0;
// int lcdUpdated = 0;
// int currentLine = 0;
// int cursorLayer = 0;
// int cursorPosition = 0;
// int valueLength = 0;
// /*
// int homeScreen = 1;
// String currentTime = "00:00:00";
// String lastTime = "00:00:00";
// String temptime = "00";
// String currentDate = "";
// int watch1active = values[56] - 3;
// int watch2active = values[60] - 3;
// int watch3active = values[64] - 3;
// int watch4active = values[68] - 3;
// int watch1rotations = 0;
// int watch2rotations = 0;
// int watch3rotations = 0;
// int watch4rotations = 0;
// int watch1left = values[1];
// int watch2left = values[15];
// int watch3left = values[29];
// int watch4left = values[43];
// String temprotationsleft = "";
// */
// void setup() {
// Serial.begin(9600);
// // Map rotary button to actions single and doubleclick.
// button0.attachClick(singleClick);
// button0.attachDoubleClick(doubleClick);
// lcd.begin (16,2);
// lcd.setBacklightPin(3,POSITIVE);
// lcd.setBacklight(HIGH);
// lcd.home();
// // Create the custom character.
// lcd.createChar(0, cursor);
// lcd.createChar(1, watch);
// lcd.setCursor (2,0);
// lcd.print("Watch Winder");
// delay(1000);
// clearLine(0);
// // Set the select cursor on the first line.
// cursorLayer = 0;
// lcd.setCursor (0,cursorLayer);
// writeCursor();
// }
// void loop() {
// // Listen to button presses.
// button0.tick();
// // Listen if the rotary encoder moves.
// rotary_check();
// // Print the LCD menu.
// lcdMenu();
// }
// void singleClick() {
// // IF current layer number is the same as redirect layer number, we stay on the same layer
// // AND no item is selected in the menu
// // AND the selected item has a redirect to another layer
// if(currentLayer == menu[currentPosition + currentSelect].substring(0,1).toInt() && menu[currentPosition + currentSelect].substring(1,3) != "__" && currentPress == ""){
// currentPress = menu[currentPosition + currentSelect].substring(3);
// currentChange = menu[currentPosition + currentSelect].substring(1,3).toInt();
// Serial.println("Currentpress: " + currentPress);
// currentType = values[currentChange];
// value = values[currentChange + 1];
// // Type select change is numeric
// if(currentType == 1){
// Min = values[currentChange + 3];
// Max = values[currentChange + 4];
// numIncr = values[currentChange + 2];
// Serial.println("Currentvalue: " + String(value));
// Serial.println("Increments: " + String(numIncr));
// Serial.println("Min: " + String(Min));
// Serial.println("Max: " + String(Max));
// valueLength = String(value).length();
// // Type select change is character range
// } else if(currentType == 2){
// Min = values[currentChange + 2];
// Max = values[currentChange + 3];
// Serial.println("Currentvalue: " + options[value]);
// Serial.println("Options: ");
// for (int i=Min; i <= Max; i++){
// Serial.println(options[i]);
// }
// valueLength = options[value].length();
// }
// clearSelect();
// cursorPosition = 15 - valueLength;
// lcd.setCursor(cursorPosition,cursorLayer);
// writeCursor();
// // ELSE IF something is selected in the menu, and the button is pressed again. We deselect the item.
// } else if(currentPress != ""){
// currentValues();
// currentPress = "";
// currentChange = 0;
// clearChar(cursorPosition,cursorLayer);
// lcd.setCursor(0,cursorLayer);
// writeCursor();
// // IF nothing is selected and nothing will be deselected, move to the redirect layer listed in the first position of the array.
// } else {
// currentLayer = menu[currentPosition + currentSelect].substring(0,1).toInt();
// currentSelect = 1;
// currentlcdLayerFloat = 0;
// currentlcdLayer = 0;
// lastlcdLayer = 0;
// clearSelect();
// cursorLayer = 0;
// lcd.setCursor (0,cursorLayer);
// writeCursor();
// }
// }
// // Reset to layer 0.
// void doubleClick() {
// if(currentLayer == 0){
// currentLayer = 0;
// currentSelect = 1;
// currentlcdLayerFloat = 0;
// currentlcdLayer = 0;
// lastlcdLayer = 0;
// clearSelect();
// cursorLayer = 0;
// lcd.clear();
// lcdUpdated = 0;
// }
// if(currentLayer != 0){
// currentLayer = 0;
// currentSelect = 1;
// currentlcdLayerFloat = 0;
// currentlcdLayer = 0;
// lastlcdLayer = 0;
// clearSelect();
// cursorLayer = 0;
// lcd.setCursor (0,cursorLayer);
// writeCursor();
// }
// }
// void rotary_check(){
// // Constantly read the position of the rotary encoder
// long newPosition = myEnc.read() / 4;
// // IF the new position of the encoder is different then the old position
// if (newPosition != oldPosition) {
// // IF nothing has been selected in the menu
// if(currentPress == ""){
// if(newPosition > oldPosition && currentSelect < currentLength){
// clearSelect();
// currentSelect++;
// currentlcdLayerFloat = currentlcdLayerFloat + 0.5;
// currentlcdLayer = currentlcdLayerFloat;
// cursorSelect();
// lcd.setCursor (0,cursorLayer);
// writeCursor();
// Serial.println("> " + menu[currentPosition + currentSelect].substring(3));
// } else if (newPosition < oldPosition && currentSelect != 1){
// clearSelect();
// currentSelect--;
// currentlcdLayerFloat = currentlcdLayerFloat - 0.5;
// currentlcdLayer = currentlcdLayerFloat;
// cursorSelect();
// lcd.setCursor (0,cursorLayer);
// writeCursor();
// Serial.println("> " + menu[currentPosition + currentSelect].substring(3));
// }
// if(lastlcdLayer != currentlcdLayer){
// lcdUpdated = 0;
// }
// lastlcdLayer = currentlcdLayer;
// oldPosition = newPosition;
// // IF something has been selected in the menu, we are going to change the value of a menu item.
// } else if(currentPress != ""){
// lcd.setCursor(cursorPosition + 1,cursorLayer);
// // IF the new position is HIGHER then the old position
// if(newPosition > oldPosition){
// clearChar(cursorPosition,cursorLayer);
// // IF the selected item has a change type that is NUMERIC.
// // AND the MAXIMUM of the selected item has not been reached.
// // We change the value UPWARDS with the icrements listed in the array.
// // SAME applies for next ELSE IF, just for the change type character. And the next ELSE IF we just go down.
// if(currentType == 1 && value < Max){
// value = value + numIncr;
// values[currentChange + 1] = value;
// Serial.println(value);
// clearValue();
// valueLength = String(value).length();
// cursorPosition = 15 - valueLength;
// lcd.setCursor(cursorPosition + 1,cursorLayer);
// lcd.print(value);
// }
// if(currentType == 2 && value < Max){
// value++;
// values[currentChange + 1] = value;
// Serial.println(options[value]);
// clearValue();
// valueLength = options[value].length();
// cursorPosition = 15 - valueLength;
// lcd.setCursor(cursorPosition + 1,cursorLayer);
// lcd.print(options[value]);
// }
// lcd.setCursor(cursorPosition,cursorLayer);
// writeCursor();
// } else {
// clearChar(cursorPosition,cursorLayer);
// if(currentType == 1 && value > Min){
// value = value - numIncr;
// values[currentChange + 1] = value;
// Serial.println(value);
// clearValue();
// valueLength = String(value).length();
// cursorPosition = 15 - valueLength;
// lcd.setCursor(cursorPosition + 1,cursorLayer);
// lcd.print(value);
// }
// if(currentType == 2 && value > Min){
// value--;
// values[currentChange + 1] = value;
// Serial.println(options[value]);
// clearValue();
// valueLength = options[value].length();
// cursorPosition = 15 - valueLength;
// lcd.setCursor(cursorPosition + 1,cursorLayer);
// lcd.print(options[value]);
// }
// lcd.setCursor(cursorPosition,cursorLayer);
// writeCursor();
// }
// oldPosition = newPosition;
// } else {
// oldPosition = newPosition;
// }
// }
// }
// void lcdMenu(){
// if (lastLayer != currentLayer || lcdUpdated == 0){
// currentLength = menu[0].toInt();
// currentPosition = 0;
// for (int i=0; i < currentLayer; i++){
// currentPosition = (menu[currentPosition].toInt() + 1) + currentPosition;
// currentLength = menu[currentPosition].toInt();
// }
// clearMenu();
// int tempPosition = currentPosition;
// if(currentlcdLayer != 0){
// currentPosition = currentPosition + (currentlcdLayer * 2);
// }
// Serial.println("LCD-------------");
// for (int i=1; i <= 2; i++){
// lcd.setCursor (1,i - 1);
// lcd.print(menu[currentPosition + i].substring(3));
// currentType = 0;
// value = values[menu[currentPosition + i].substring(1,3).toInt() + 1];
// String tempvalue = "";
// if(menu[currentPosition + i].substring(1,3) != "__" && menu[currentPosition + i].substring(1,3) != ""){
// currentType = values[menu[currentPosition + i].substring(1,3).toInt()];
// if(currentType == 1){
// lcd.setCursor (16 - String(value).length(),i - 1);
// lcd.print(value);
// tempvalue = " "+ String(value);
// }else if(currentType == 2){
// lcd.setCursor (16 - options[value].length(),i - 1);
// lcd.print(options[value]);
// tempvalue = " "+ options[value];
// }
// }
// Serial.println(menu[currentPosition + i].substring(3) + tempvalue);
// }
// Serial.println("----------------");
// currentPosition = tempPosition;
// lastLayer = currentLayer;
// lcdUpdated = 1;
// /**
// Serial.println("Layer " + String(currentLayer + 1));
// Serial.println("Layer length " + String(currentLength));
// Serial.println("Layer position " + String(currentPosition));
// **/
// }
// }
// void currentValues(){
// Serial.println("Currentpress: " + currentPress);
// if(currentType == 1){
// Serial.println("Currentvalue: " + String(value));
// Serial.println("Increments: " + String(numIncr));
// Serial.println("Min: " + String(Min));
// Serial.println("Max: " + String(Max));
// } else if(currentType == 2){
// Serial.println("Currentvalue: " + options[value]);
// Serial.println("Options: ");
// for (int i=Min; i <= Max; i++){
// Serial.println(options[i]);
// }
// }
// }
// void clearChar(int charPosition, int line){
// lcd.setCursor (charPosition,line);
// lcd.print(" ");
// }
// void clearLine(int line){
// lcd.setCursor (0,line);
// lcd.print(" ");
// }
// void clearMenu(){
// lcd.setCursor (1,0);
// lcd.print(" ");
// lcd.setCursor (1,1);
// lcd.print(" ");
// }
// void clearSelect(){
// lcd.setCursor (0,0);
// lcd.print(" ");
// lcd.setCursor (0,1);
// lcd.print(" ");
// }
// void cursorSelect(){
// switch (currentSelect){
// case 1:
// cursorLayer = 0;
// break;
// case 2:
// cursorLayer = 1;
// break;
// case 3:
// cursorLayer = 0;
// break;
// case 4:
// cursorLayer = 1;
// break;
// case 5:
// cursorLayer = 0;
// break;
// case 6:
// cursorLayer = 1;
// break;
// }
// }
// void writeCursor(){
// lcd.write(byte(0));
// }
// void clearValue(){
// for (int i = 16 - valueLength; i <= 16; i++){
// lcd.setCursor (i,cursorLayer);
// lcd.print(" ");
// }
// }
// #include <LiquidCrystal.h>
// #include <RotaryEncoder.h>
// // Define LCD pins (replace with your actual pins)
// const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
// LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// // Define rotary encoder pins (replace with your actual pins)
// const int encoderA = 8;
// const int encoderB = 9;
// // Define switch pin for mode control (replace with your actual pin)
// const int modeSwitchPin = 10;
// RotaryEncoder encoder(encoderA, encoderB);
// bool controlMode = true; // Initial mode: Position control
// // Variables for position control (cursor movement)
// int cursorX = 0;
// int cursorY = 0;
// const int lcdColumns = 16; // Number of columns on your LCD
// const int lcdRows = 2; // Number of rows on your LCD
// // Variables for direction control (menu selection)
// const char* menuItems[] = {"Option A", "Option B"}; // Define your menu options
// int numMenuItems = sizeof(menuItems) / sizeof(menuItems[0]);
// int currentMenuItem = 0;
// // Function prototypes for custom actions in each mode
// void performPositionAction(int cursorX, int cursorY);
// void performMenuAction(int selectedMenuItem);
// void setup() {
// lcd.begin(lcdColumns, lcdRows);
// lcd.clear();
// // encoder.begin(encoderA, encoderB);
// pinMode(modeSwitchPin, INPUT_PULLUP); // Set switch pin as input with pull-up resistor
// lcd.print("Mode: Position"); // Display initial mode
// }
// void loop() {
// int newEncoderValue = encoder.getPosition();
// static int previousEncoderValue = newEncoderValue; // Store previous value
// // int currentEncoderValue = encoder.read(); // Read current encoder value
// // static int previousEncoderValue = currentEncoderValue; // Store previous value
// // Calculate change in value (avoiding redundant processing)
// int change = newEncoderValue - previousEncoderValue;
// // Update previous value for the next loop
// previousEncoderValue = newEncoderValue;
// // Check for mode switch press (active low with pull-up)
// bool modeSwitchPressed = !digitalRead(modeSwitchPin);
// if (modeSwitchPressed) {
// controlMode = !controlMode; // Toggle control mode between position and direction
// lcd.clear();
// if (controlMode) {
// lcd.print("Mode: Position"); // Display current mode
// cursorX = 0; // Reset cursor position for position control
// } else {
// lcd.print("Mode: Direction"); // Display current mode
// }
// }
// // Efficiently handle encoder changes (avoid redundant processing)
// // int change = newEncoderValue - encoder.previousEncoderValue();
// // Update previous value for the next loop
// // previousEncoderValue = newEncoderValue;
// if (controlMode) {
// // **Position Control Mode (Cursor Movement)**
// if (change) {
// if (change > 0) {
// // Clockwise rotation - move cursor right
// cursorX++;
// } else {
// // Counter-clockwise rotation - move cursor left
// }
// // Keep cursor within LCD bounds
// cursorX = constrain(cursorX, 0, lcdColumns - 1);
// // Update cursor position on LCD
// lcd.setCursor(cursorX, cursorY);
// // Call your custom function to perform actions based on cursor position
// performPositionAction(cursorX, cursorY);
// }
// } else {
// // **Direction Control Mode (Menu Selection)**
// if (change) {
// if (change > 0) {
// // Clockwise rotation - move selection up
// currentMenuItem--;
// } else {
// // Counter-clockwise rotation - move selection down
// }
// // Keep selection within menu bounds
// currentMenuItem = constrain(currentMenuItem, 0, numMenuItems - 1);
// // Clear LCD and display menu
// lcd.clear();
// for (int i = 0; i < numMenuItems; i++) {
// if (i == currentMenuItem) {
// lcd.print(">"); // Display arrow for selected item
// } else {
// lcd.print(" ");
// }
// lcd.print(menuItems[i]);
// lcd.setCursor(0, 1);
// }
// // Call your custom function to perform actions based on selected menu item
// performMenuAction(currentMenuItem);
// }
// }
// }
// -----
// LimitedRotator.ino - Example for the RotaryEncoder library.
// This class is implemented for use with the Arduino environment.
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// More information on: http://www.mathertel.de/Arduino
// -----
// 26.03.2017 created by Matthias Hertel
// -----
// This example checks the state of the rotary encoder in the loop() function.
// The current position is printed on output when changed.
// In addition to the SimplePollRotator example here the range of the rotator is limited to the range 0 - 16 and only incremental steps of 2 are realized.
// To implement this limit the boundaries are checked and eventually the current position is adjusted.
// The internal (physical) position of the rotary encoder library remains by stepping with the increment 1
// so the the logical position is calculated by applying the ROTARYSTEPS factor.
// Hardware setup:
// Attach a rotary encoder with output pins to A2 and A3.
// The common contact should be attached to ground.
#include <RotaryEncoder.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define ROTARYSTEPS 2
#define ROTARYMIN -1
#define ROTARYMAX 1
int sel=1 ;
int var ;
bool up= false;
bool down= false;
bool set1 =false;
bool set2 =false;
String dir =" ";
int sw=7;
bool sw_state = HIGH;
// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);
// Last known rotary position.
int lastPos = 1;
void setup()
{
Serial.begin(57600);
lcd.begin(16,2);
pinMode(sw,INPUT_PULLUP);
// lcd.print("Use encoder to select:");
Serial.println("LimitedRotator example for the RotaryEncoder library.");
encoder.setPosition(10 / ROTARYSTEPS); // start with the value of 10.
// You may have to modify the next 2 lines if using other pins than A2 and A3
PCICR |= (1 << PCIE1); // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11); // This enables the interrupt for pin 2 and 3 of Port C.
} // setup()
ISR(PCINT1_vect) {
encoder.tick(); // just call tick() to check the state.
}
// Read the current position of the encoder and print out when changed.
void loop()
{
// encoder.tick();
if(digitalRead(sw) == 0)
{
if (sel == 1) set1 = !set1;
if (sel == 2) set2 = !set2;
}
// get the current physical position and calc the logical position
int newPos = encoder.getPosition() * ROTARYSTEPS;
if (newPos < ROTARYMIN) {
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN;
} else if (newPos > ROTARYMAX) {
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX;
}
// if
if (lastPos != newPos) {
lastPos = newPos;
if (lastPos>0){
dir="cw";
up =true;
}
if (lastPos<0){
dir ="ACW";
down =true;
}
}
if (up && set1==false && set2== false){
sel=1;
up = false;
}
if (down && set1==false && set2== false ) {
sel=2;
down = false;
}
if (set1){
if (up){
var++;
up=false;
}
if (down){
var--;
down=false;
}
}
if (set2){
if (up){
dir ="CW";
up=false;
}
if (down){
dir ="ACW";
down=false;
}
}
if (sel ==1){
Serial.print(" pos : ");
Serial.print(var);
Serial.println();
}
if (sel == 2){
//
Serial.print("DIR: ");
Serial.print(dir);
Serial.println();
}
lcd.setCursor(2,0);
lcd.print("Pos: ");
lcd.setCursor(2,1);
lcd.print("Dir: ");
if(sel ==1 ){
lcd.setCursor(0,0);
lcd.print(">");
lcd.setCursor(0,1);
lcd.print(" ");
// if(sw_state==LOW){
//
// Serial.print("st is press for var");
lcd.setCursor(10,0);
lcd.print(var);
}
if(sel ==2 ){
lcd.setCursor(0,1);
lcd.print(">");
lcd.setCursor(0,0);
lcd.print(" ");
// if(sw_state==LOW){
// Serial.print("st is press for dir");
//
lcd.setCursor(10,1);
lcd.print(dir);
// }
}
}
// The End