Go Down

Topic: LCD Encoder Menu (Read 1 time) previous topic - next topic

dizzwold

Hi all,

 I've been working with a sktch writen by Vladimir Ronamov found here;

https://www.youtube.com/watch?v=Q58mQFwWv7c&t=212s

 The sketch was writen for 4 button swtches and I'm trying to re-write it to use an encoder.

 So-far I've managed to get the encoder to scroll through the menu's, but I'm struggling to find a way to enter the values and change them.
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {20, 21, 53};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0};
long debounceDelay = 5;
int backlight_pin10 = 10;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
const char* screens[numOfScreens][2] = {{"1Motor Voltage", "Volts"}, {"2Motor Current", "Amps"},
  {"3Motor Rated HP", "HP"}, {"4Overload Temp.", "degC"}, {"5Accel Time", "Secs"}, {"6Restart Time", "Mins"},
  {"7Analog Out. Curr.", "mA"}, {"8Input Temp.", "degC"}, {"9Run Time", "Hours"}, {"10Start Times", "times"}
};
int button = 53;
int led = 13;
int status = false;
int parameters[numOfScreens];

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  analogWrite(10, 200);
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
  Serial.begin(9600);
  lcd.begin(20, 4);
}

long old = 0;

void loop() {
  setInputFlags();
  resolveInputFlags();

}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
      //Serial.println(reading);
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input)
{
  if (digitalRead(button) == true)
  {
    status = !status;
    digitalWrite(led, status);
    Serial.print(status);
  }

  delay(50); // keeps a small delay
  long newP = myEnc.read() / 4;
  {
    if (newP < old)
    {
      old = newP;
      if (currentScreen == 0 && 1)
      {

        currentScreen = numOfScreens - 1;
      }
      else
      {
        currentScreen--;
      }
    }
    if (newP > old)
    {
      old = newP;
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
  }
  if (digitalRead(button) == false);
  {
    status = !status;
    delay(50); // keeps a small delay
    {
      if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }
    }
  }
}

void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}


 I would like to ask for some guidance.

 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

You need a variable to know which mode you're in: scrolling through the menu item names or, scrolling through a particular menu item's parameters/values.  A pushbutton (possibly the one integrated into the encoder) set up to give a push on-push off function would work but any switch would do.

This mode flag then directs the code to execute or ignore one or the other of the two choices.  Things get more complicated if you have multi-level menus.

dizzwold

Hi dougp,

 Thank you for the reply.

 Sorry I forgot to state that I wish to use the intergrated encoder switch and what you have suggested is exactly what I was trying to achieve.

 I wrote the void inputactions to try to do that. Is this where I should have the variable to select which mode to change?

 I've tried it in it's own void and called it in the void loop, but that didn't work either, it just went mad, as you would expect.

 Please excuse my lack of coding knowledge.

 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

Sorry I forgot to state that I wish to use the intergrated encoder switch and what you have suggested is exactly what I was trying to achieve.

 I wrote the void inputactions to try to do that. Is this where I should have the variable to select which mode to change?

 I've tried it in it's own void and called it in the void loop, but that didn't work either, it just went mad, as you would expect.
First, let's clear up a terminology issue.  'void' is not the name of a function, it's a keyword - read about it here.  The word 'loop' after   void, as in 'void loop()' is the function name.

Secondly, this bit of code:

Code: [Select]
void inputAction(int input)
{
  if (digitalRead(button) == true)
  {
    status = !status;
    digitalWrite(led, status);
    Serial.print(status);
  }

The use of digitalRead(button) == true  directly reads the button state from the input pin, after you have already debounced and determined its state in setInputFlags.  Also, the state will follow the input, with a slight debouncing delay.  Since the input is normally HIGH due to the pullups this code will be executed continuously until the button is pressed.  What you want here is a one time action to change the state of status.  Use instead:

Code: [Select]
inputFlags[2]  // the position of the button in the input flags array
It's clunky but this corresponds to the array location for the pushbutton which will be high for only one scan through the code when the button is released.

Also, in resolveInputs() you're passing the loop variable (i) as a parameter to inputActions but never using it.  In order to distinguish what should happen in inputActions the basic structure should be something like:
Code: [Select]

if(input == 0){
// do some stuff
}
else if(input == 1){
  // do other stuff
}
else if(input == 2){
  // do still more other stuff - like change the state of 'status', update the display, and so on
  }
// et cetera, et cetera, et cetera


This way the function can act appropriately on the passed value.


dizzwold

Hi dougp,

 Thank you for your reply,
Quote
Also, in resolveInputs() you're passing the loop variable (i) as a parameter to inputActions but never using it.
I see what you mean, and i have corrected this.
Quote
inputFlags[2]  // the position of the button in the input flags array
Is this pointing to the second part of the array "the values"? Then if it was "[1]" it would be pointing to the first part of the array "1motor voltage, 2 motor current etc"?

 I'm not sure how to use this correctly, where to use it and how to relate it to the intergrated button / switch of the encoder, apart from "if (input == 2)"

 I've tried this below, but another fail;
Code: [Select]
if (input == 0)
    {
      inputFlags[1];

Code: [Select]
else if (input == 1)
    {
      inputFlags[1];

Code: [Select]
else if (input == 2);
    {
      inputFlags[2];


 Here's what the sketch is currently;
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {20, 21, 53};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0};
long debounceDelay = 10;
int backlight_pin10 = 10;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
const char* screens[numOfScreens][2] = {{"1Motor Voltage", "Volts"}, {"2Motor Current", "Amps"},
  {"3Motor Rated HP", "HP"}, {"4Overload Temp.", "degC"}, {"5Accel Time", "Secs"}, {"6Restart Time", "Mins"},
  {"7Analog Out. Curr.", "mA"}, {"8Input Temp.", "degC"}, {"9Run Time", "Hours"}, {"10Start Times", "times"}
};
int button = 53;
int led = 13;
int status = false;
int parameters[numOfScreens];

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  analogWrite(10, 200);
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
  Serial.begin(9600);
  lcd.begin(20, 4);
}

long old = 0;

void loop() {
  setInputFlags();
  resolveInputFlags();

}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
      //Serial.println(reading);
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input)
{
  long newP = myEnc.read() / 4;
  {
    if (input == 0)
    {
      if (newP < old)
      {
        old = newP;
        if (currentScreen == 0 && 1)
        {
          currentScreen = numOfScreens - 1;
        }
        else
        {
          currentScreen--;
        }
      }
    }
    else if (input == 1)
    {
      if (newP > old)
      {
        old = newP;
        if (currentScreen == numOfScreens - 1)
        {
          currentScreen = 0;
        }
        else
        {
          currentScreen++;
        }
      }
    }

    else if (input == 2);
    {
      if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }
    }
  }
}




void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}


 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

Quote
Code: [Select]
inputFlags[2]  // the position of the button in the input flags array

Is this pointing to the second part of the array "the values"? Then if it was "[1]" it would be pointing to the first part of the array "1motor voltage, 2 motor current etc"?
No.  Toss that, it was a poor example.

You have five arrays holding values dealing with the three inputs.  Each array element zero has to do with some value or state pertaining to the input on pin 20.  The others follow in succession.  Element one deals with pin 21, etc.

Imagine that you refer to element zero with a name like 'encoderCLK' instead.  Every place you would put a 0 inside square brackets to refer to the first element , substitute encoderCLK.

Now you can think of the various states of input 20 as;
Code: [Select]
inputState[encoderClk]
lastDebounceTime[encoderCLK]

// etc.


To toggle the menu variable the input of interest here is :
Code: [Select]
inputflags[encoderSW]
since this variable is true for only one scan - scan being a shorthand way of thinking of one pass through loop().

Now, releasing the encoder pushbutton (meaning 'toggle mode') sends a value of '2' to inputActions.  There the pushbutton gets tangled up with the encoder values.  Forget that.  The only thing that a value of '2' sent to inputActions should do is toggle the state of a variable which determines whether you're manipulating the menu text or manipulating the values associated with a menu selection. 

Create a variable to do this and prove it works as it should by printing its value on the serial monitor.  Since, at this point, there are only two alternatives for the pushbutton action you could use a bool variable.


dizzwold

Hi dougp,

 Thank you again for your reply.

 I can only get the led to toggle on and off with the encoder switch, but not the values.
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {20, 21, 53};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0};
long debounceDelay = 10;
int backlight_pin10 = 10;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
const char* screens[numOfScreens][2] = {{"1Motor Voltage", "Volts"}, {"2Motor Current", "Amps"},
  {"3Motor Rated HP", "HP"}, {"4Overload Temp.", "degC"}, {"5Accel Time", "Secs"}, {"6Restart Time", "Mins"},
  {"7Analog Out. Curr.", "mA"}, {"8Input Temp.", "degC"}, {"9Run Time", "Hours"}, {"10Start Times", "times"}
};
int button = 53;
int led = 13;
int status = false;
int parameters[numOfScreens];

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  analogWrite(10, 200);
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
  Serial.begin(9600);
  lcd.begin(20, 4);
}

long old = 0;

void loop() {
  setInputFlags();
  resolveInputFlags();

}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
      //Serial.println(reading);
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input)
{
  long newP = myEnc.read() / 4;
  {
    if (input == 0)
    {
      if (newP < old)
      {
        old = newP;
        if (currentScreen == 0 && 1)
        {
          currentScreen = numOfScreens - 1;
        }
        else
        {
          currentScreen--;
        }
      }
    }
    else if (input == 1)
    {
      if (newP > old)
      {
        old = newP;
        if (currentScreen == numOfScreens - 1)
        {
          currentScreen = 0;
        }
        else
        {
          currentScreen++;
        }
      }
    }

    else if (input == 2);
    {
      status = ! status;
      digitalWrite(led, status);
      inputFlags[2];
      if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }
    }
  }
}




void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}


 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

Reference code:

Code: [Select]
else if (input == 2);
    {
      status = ! status;
      digitalWrite(led, status);
      inputFlags;
      if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }


Where does the variable 'status' come from?  The encoder?  It's not a user-declared variable because I see it highlighted in red in my IDE.  I'm not certain you want to be changing that.

And, as stated above, since the encoder pushbutton is associated with the value '2' in the arrays, and the only function of the pushbutton is to go on and off, the only activity in if(input == 2) should be toggling the menu select variable.

Once you can control this variable, let's call it menuToggle, the two options become:

  • if menuToggle is false the encoder direction signal(s) changes which menu option is displayed.
  • if menuToggle is true, the encoder direction signal(s) changes a parameter value

In both cases a decision will have to be made whether to stop the selection at the limits or to wrap around to the first/last item.

dizzwold

Hi,

 I'm still not grasping this.

 My understanding is, I'm checking for input 2 the encoder switch on pin 53, if that is toggled then check the encoder position for up or down movement if so change the value or parameter?
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {20, 21, 53};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0};
long debounceDelay = 10;
int backlight_pin10 = 10;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
const char* screens[numOfScreens][2] = {{"1Motor Voltage", "Volts"}, {"2Motor Current", "Amps"},
  {"3Motor Rated HP", "HP"}, {"4Overload Temp.", "degC"}, {"5Accel Time", "Secs"}, {"6Restart Time", "Mins"},
  {"7Analog Out. Curr.", "mA"}, {"8Input Temp.", "degC"}, {"9Run Time", "Hours"}, {"10Start Times", "times"}
};
int button = 53;
int led = 13;
int status = false;
int parameters[numOfScreens];

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  analogWrite(10, 200);
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
  Serial.begin(9600);
  lcd.begin(20, 4);
}

long old = 0;

void loop() {
  setInputFlags();
  resolveInputFlags();

}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
      //Serial.println(reading);
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input)
{
  long newP = myEnc.read() / 4;
  {
    if (input == 0)
    {
      if (newP < old)
      {
        old = newP;
        if (currentScreen == 0 && 1)
        {
          currentScreen = numOfScreens - 1;
        }
        else
        {
          currentScreen--;
        }
      }
    }
    else if (input == 1)
    {
      if (newP > old)
      {
        old = newP;
        if (currentScreen == numOfScreens - 1)
        {
          currentScreen = 0;
        }
        else
        {
          currentScreen++;
        }
      }
    }

    else if (input == 2);
    {
      status = ! status;
      digitalWrite(led, status);
      if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }
    }
  }
}




void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}


 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

Code: [Select]
status = ! status;

What is status?  Is it part of the encoder library?  What does it indicate the status of?

dizzwold

Hi dougp,

 No it's not part of the encoder library.

 I cant remember where I found the example, but it is basically as follows for toggling an LED;
Code: [Select]
int button = 53;
int led = 13;
int status = false;

void setup()
{
  Serial.begin (9600);
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
}

void loop()
{
  //a) if the button is not pressed the false status is reversed by !status and the LED turns on
  //b) if the button is pressed the true status is reveresed by !status and the LED turns off

  if (digitalRead(button) == true)
  {
    status = !status;
    digitalWrite(led, status);
    Serial.print(status);
  }
  while (digitalRead(button) == true);
  delay(50); // keeps a small delay
}


 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

dougp

Well, as I say, 'status' is colored red in my IDE.   That means it's a keyword for something  and  you're changing that unknown something.  To what effect who can say?

Give 'status' some different, meaningful name and make it a Boolean - since it's only going to have two states.

Code: [Select]
else if (input == 2);
    {
      newNameForStatus = ! newNameForStatus;
      digitalWrite(led, status);
//      if (newP < old)   // disable all the code from here
//        old = newP;
//      {
//        parameterChange(1);
//      }
//      if (newP > old)
//        old = newP;
//      {
//        parameterChange(0);  //  to here
      }
    }

Delta_G

Well, as I say, 'status' is colored red in my IDE.   That means it's a keyword for something  and  you're changing that unknown something.  To what effect who can say?

It's not a keyword.  More likely that somebody decided to put it in their keywords.txt file for some library that the OP might not even be using. 
If at first you don't succeed, up - home - sudo - enter.

dougp

It's not a keyword.  More likely that somebody decided to put it in their keywords.txt file for some library that the OP might not even be using.  
Thanks.  I don't know enough to have even considered that.  In any case, the amorphous 'status' could still be improved, IMHO.

dizzwold

Hi,

 Thank you for your comments;
Quote
Well, as I say, 'status' is colored red in my IDE.   That means it's a keyword for something  and  you're changing that unknown something.  To what effect who can say?
@ dougp, at first I didn't realise what you ment, but have now changed "status to dizzwold". Thank you for pointing this out clearly.

Quote
It's not a keyword.  More likely that somebody decided to put it in their keywords.txt file for some library that the OP might not even be using.
@ Delta_G, Wow, you wouldn't think that some random word in a library txt file would effect a sketch that doesn't use said library! Thank you for this insight.

 Before moving on to being able to change the values or parameters, one thing I have noticed is when loading the sketch /start  /boot, the LED is high and on, push the encoder switch and the change of state works fine, on, off, on, off etc, but if I rotate the encoder really fast this also sometimes changes the state of the LED. Is this just because these are cheap encoders?

 Here's the current sketch;
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {20, 21, 53};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0};
long debounceDelay = 10;
int backlight_pin10 = 10;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
const char* screens[numOfScreens][2] = {{"1Motor Voltage", "Volts"}, {"2Motor Current", "Amps"},
  {"3Motor Rated HP", "HP"}, {"4Overload Temp.", "degC"}, {"5Accel Time", "Secs"}, {"6Restart Time", "Mins"},
  {"7Analog Out. Curr.", "mA"}, {"8Input Temp.", "degC"}, {"9Run Time", "Hours"}, {"10Start Times", "times"}
};
int button = 53;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens];

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  analogWrite(10, 200);
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
  Serial.begin(9600);
  lcd.begin(20, 4);
}

long old = 0;

void loop() {
  setInputFlags();
  resolveInputFlags();

}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
      //Serial.println(reading);
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input)
{
  long newP = myEnc.read() / 4;
  {
    if (input == 0)
    {
      if (newP < old)
      {
        old = newP;
        if (currentScreen == 0 && 1)
        {
          currentScreen = numOfScreens - 1;
        }
        else
        {
          currentScreen--;
        }
      }
    }
    else if (input == 1)
    {
      if (newP > old)
      {
        old = newP;
        if (currentScreen == numOfScreens - 1)
        {
          currentScreen = 0;
        }
        else
        {
          currentScreen++;
        }
      }
    }

    else if (input == 2);
    {
      dizzwold = ! dizzwold;
      digitalWrite(led, dizzwold);
      /*if (newP < old)
        old = newP;
      {
        parameterChange(1);
      }
      if (newP > old)
        old = newP;
      {
        parameterChange(0);
      }*/
    }
  }
}




void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}


 Dizzwold.
I'm not a student or a lecturer. I'm a hobbyist.

Go Up