Partie 2 :


Principe de fonctionnement de l'encodeur
un encodeur et un ecran LCD
Un encodeur commande un menu sur lcd 16*2
Le code ci dessous modifie
un tuto avec un code qui marche à condition d'adapter le code comme suit :
/*
 * MARK VAN VEGGEL
 * ARDUINO LCD MENU V0.1
 * YOUTUBE.COM/AMPSOURCE
 * 
 */

#include 
#include 
#include 
#include 
//#include 
//#include 

//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// ROTARY ENCODER
long oldPosition  = 0;
int encoderDTpin = A0;
int encoderCLKpin = A1;
Encoder myEnc(encoderDTpin, encoderCLKpin);

int buttonPin = A2;
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);
  • analogWrite(8,15);
  • 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(" "); } }

image rotaryencoderfordummiesforarduinoraspberrypitechnology.jpg (0.1MB)