Go Down

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

dougp

You don't want this for loop: for (int i = 0; i < numOfInputs; i ++),  line #49.

Just put the if/then that is within the for loop directly after enc().
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

Hi dougp,

 Like this;
Code: [Select]
void loop() {
  enc();
  int i = 0; i < numOfInputs; i ++;
  {
    if (encoderTurned != 0);
    {
      inputAction(i);
    }
  }
  //setInputFlags();
  //resolveInputFlags();
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}


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

dougp

This:  int i = 0; i < numOfInputs; i ++; is (was) part of the for loop - it goes away.

This: { is part of the for loop - it goes away.

This: } is part of the for loop - it goes away.
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

Hi dougp,

 If I do the following I get a compile error "too few arguments to function 'void inputAction(int)'";
Code: [Select]
void loop() {
  enc();
  if (encoderTurned != 0);
  {
    inputAction();
  }
  //setInputFlags();
  //resolveInputFlags();
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}


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

dizzwold

Hi,

 I've removed the "int input" from the "void inputActions" and also the i from "inputAction, in void resolveInputFlags", to the following;
Code: [Select]
void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction();
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction()


 This just give's me a blank backlit screen. I've also been playing with setting start values for the parameters, instead of them starting a 0. I've got this now to control the backlight. Heres the current sketch;
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);
#define DIR_CW +1
#define DIR_CCW -1

//Input & Button Logic
const int numOfInputs = 2;
const int inputPins[numOfInputs] = {20, 21};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW};
//long lastDebounceTime[numOfInputs] = {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 lastbutton = false;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens] = {255,0,0,0,0,0,0,0,0,0};
long oldP = 0;
int encoderTurned = 0;

void setup() {
  pinMode(backlight_pin10, OUTPUT);
 
  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);
}

void loop() {
  enc();
  analogWrite(10, parameters[0]);
  if (encoderTurned != 0);
  {
    inputAction();
  }
  //setInputFlags();
  //resolveInputFlags();
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}

void enc() {
  long newP = myEnc.read();  //  check for encoder rotation
  encoderTurned = 0;  // Reset previous turned value.
  if ( oldP != newP) {
    if (newP > oldP) encoderTurned = DIR_CW;
    if (newP < oldP) encoderTurned = DIR_CCW;
    oldP = newP; // set oldP equal to newP so next rotation can be detected
  }
}

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();
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0 && 1)
      {
        currentScreen = numOfScreens - 1;
      }
      currentScreen--;
    }
  }



  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}

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]); // first part of array, Motor Voltage.
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]); // second part of array, Volts.
}


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

dougp

Is there anywhere in the sketch where printScreen(); is called?
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

Hi dougp,

 
Quote
Is there anywhere in the sketch where printScreen(); is called?
Yes there is in void resolve inpur flags. I did try this and moved it yesterday to the main loop after the call input actions(), but for some reason I got a lot of screen flicker.

 Today when moving the print scrren I don't get any flicker. that might have been the level of contrast and the angle of viewing it, but it still counts erratically.
Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Encoder.h>
Encoder myEnc(20, 21);
#define DIR_CW +1
#define DIR_CCW -1

//Input & Button Logic
const int numOfInputs = 2;
const int inputPins[numOfInputs] = {20, 21};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW};
//long lastDebounceTime[numOfInputs] = {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 lastbutton = false;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens] = {255, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long oldP = 0;
int encoderTurned = 0;

void setup() {
  pinMode(backlight_pin10, OUTPUT);

  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);
}

void loop() {
  enc();
  analogWrite(10, parameters[0]);
  if (encoderTurned != 0);
  {
    inputAction();
    printScreen();
  }
  //setInputFlags();
  //resolveInputFlags();
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}

void enc() {
  long newP = myEnc.read();  //  check for encoder rotation
  encoderTurned = 0;  // Reset previous turned value.
  if ( oldP != newP) {
    if (newP > oldP) encoderTurned = DIR_CW;
    if (newP < oldP) encoderTurned = DIR_CCW;
    oldP = newP; // set oldP equal to newP so next rotation can be detected
  }
}

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();
      inputFlags[i] = LOW;
      //printScreen();
    }
  }
}

void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0 && 1)
      {
        currentScreen = numOfScreens - 1;
      }
      currentScreen--;
    }
  }



  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}

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]); // first part of array, Motor Voltage.
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]); // second part of array, Volts.
}


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

dougp

With the exception of line 92:  if (currentScreen == 0 && 1) I see nothing that would cause erratic counting.

Looks like it's time to focus on the encoder library and make sure it's working correctly or find another.
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

#53
Dec 17, 2017, 08:51 pm Last Edit: Dec 17, 2017, 08:51 pm by dizzwold
Hi dougp,

 Hummm!

 Before removing the software debounce in void set input flags and removing the call's for set input flags and resolve input flags, I could get a serial print starting with 11, then with one detent turn of the encoder I would see 0011 for evey detent.
Code: [Select]
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;
  }
}


 I now get nothing in the serial monitor.

 Could this be the problem?

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

dougp

#54
Dec 18, 2017, 03:09 am Last Edit: Dec 18, 2017, 03:45 am by dougp Reason: correction
In the code in post #51, line 50 - remove the semicolon after the for.

I have a modified version of your code and the library running, using the two UNO interrupts, and it navigates the menu correctly.  Pretty fast too.

Since printScreen() only runs one time when activated by encoderTurned != 0, you want to initialize the display by an unconditional call to printScreen(); in setup().

Code: [Select]
/*
 * Modified to run on Arduino UNO with 16 x 2 LCD
 */

//#include <AccelStepper.h> // AccelStepper Library
#include <LiquidCrystal.h>
LiquidCrystal lcd(6, 7, 5, 4, A1, A0); // define I/O pins for 1602 LCD (4-bit mode)
#include <Encoder.h>
Encoder myEnc(2, 3);
#define DIR_CW +1
#define DIR_CCW -1

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {2, 3, A2};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW};
//long lastDebounceTime[numOfInputs] = {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 = A2;
//int lastbutton = false;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens] = {255, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long oldP = 0;
int encoderTurned = 0;

void setup() {
//  pinMode(backlight_pin10, OUTPUT);
  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(16, 2);
  printScreen();
}
void loop() {
  enc();
//  analogWrite(10, parameters[0]);
Serial.print(encoderTurned);
  if (encoderTurned != 0)
  {
    inputAction();
    printScreen();
  }
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}
void enc() {
  long newP = myEnc.read();  //  check for encoder rotation
  encoderTurned = 0;  // Reset previous turned value.
  if ( oldP != newP) {
    if (newP > oldP) encoderTurned = DIR_CW;
    if (newP < oldP) encoderTurned = DIR_CCW;
    oldP = newP; // set oldP equal to newP so next rotation can be detected
  }
}
void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0 && 1)
      {
        currentScreen = numOfScreens - 1;
      }
      currentScreen--;
    }
  }
  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}
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]); // first part of array, Motor Voltage.
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]); // second part of array, Volts.
}


Update:  After fiddling with it some more I too am seeing multiple increments of menu selections as opposed to single up/down events.  No answer for this, yet.
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

Hi dougp,

 I've found the sneaky little problem that I think we've both overlooked.

 Line 69;
Code: [Select]
long newP = myEnc.read();

 Change this to;
Code: [Select]
long newP = myEnc.read()/4;

 This fixes the issue. The only problem I've found is when rotating in CCW going from the first screen "1Motor Voltage", it misses screen 10 and jumps to screen 9.

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

dizzwold

Hi dougp,

 I've fixed the missing screen 10 "or 9 from the array". A little couple of changes from line 94 - 101.
Code: [Select]
void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0)
      {
        currentScreen = 9;
      }
      else
      {
        currentScreen--;
      }
    }
  }
  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}


 Here's the full sketch;
Code: [Select]
/*
   Modified to run on Arduino UNO with 16 x 2 LCD
*/

//#include <AccelStepper.h> // AccelStepper Library
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 7, 6, 5, 4); // define I/O pins for 1602 LCD (4-bit mode)
#include <Encoder.h>
Encoder myEnc(2, 3);
#define DIR_CW +1
#define DIR_CCW -1

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {2, 3, A2};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW};
//long lastDebounceTime[numOfInputs] = {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 = A2;
//int lastbutton = false;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens] = {255, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long oldP = 0;
int encoderTurned = 0;

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  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);
  printScreen();
}
void loop() {
  enc();
  analogWrite(10, parameters[0]);
  Serial.print(encoderTurned);
  if (encoderTurned != 0)
  {
    inputAction();
    printScreen();
  }
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}
void enc() {
  long newP = myEnc.read() / 4; //  check for encoder rotation
  encoderTurned = 0;  // Reset previous turned value.
  if ( oldP != newP) {
    if (newP > oldP) encoderTurned = DIR_CW;
    if (newP < oldP) encoderTurned = DIR_CCW;
    oldP = newP; // set oldP equal to newP so next rotation can be detected
  }
}
void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0)
      {
        currentScreen = 9;
      }
      else
      {
        currentScreen--;
      }
    }
  }
  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}
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]); // first part of array, Motor Voltage.
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]); // second part of array, Volts.
}


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

dougp

Good catch with the /4 thing.

I modified your modification thusly:

Code: [Select]
else if (encoderTurned == DIR_CCW) {

      if (currentScreen == 0)
      {
        currentScreen = numOfScreens;
      }
      currentScreen--;
    }


The use of numOfScreens rather than the constant '9' allows for easy change if you ever add or subtract menu items.  I also had a problem with the menu select variable changing randomly.  I fixed this in setup() with:

Code: [Select]
pinMode(button, INPUT_PULLUP); // set the internal pull up resistor, unpressed button is HIGH
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

dizzwold

Hi dougp,

Code: [Select]
else if (encoderTurned == DIR_CCW) {

      if (currentScreen == 0)
      {
        currentScreen = numOfScreens;
      }
      currentScreen--;
    }

 That's a very good point regarding the possibility of adding or removing menu item's. Thank you for your input.

 I've figured out how to have a starting value for each of the parameters with the following;
Code: [Select]
int parameters[numOfScreens] = {125, 0, 0, 0, 0, 0, 0, 0, 0, 0};

 I've then figured how to use 1 of the parameters value's, in this case "in void loop", to use as a PWM for the backlight;
Code: [Select]
void loop() {
  enc();
  analogWrite(10, parameters[0]);


 I've then been able to set upper and lower bound to this with;
Code: [Select]
void loop() {
  enc();
  analogWrite(10, parameters[0]);
  if (parameters[0] < 16) parameters[0] = 16;
  else if (parameters[0] > 254) parameters[0] = 254;


 The only thing I've not figured out thus far, is how to increment or deincrement this by 15 for each detent turn of the encoder.

 At the moment, I'm only playing around with the 1 parameters value's "parameters[0]", but if I was to have a start value, a min value, a max value and an increment value for all 10 menu items, what would be the best solution for this;

 Change "int parameters[numOfScreens] = {125, 0, 0 etc", into a multidimensional array,
Or
 Have a void function for each parameters ie "void parameters0, void parameters1, void parameters2 etc"
Or both?

 Here's the full sketch;
Code: [Select]
/*
   Modified to run on Arduino UNO with 16 x 2 LCD
*/

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 7, 6, 5, 4); // define I/O pins for 1602 LCD (4-bit mode)
#include <Encoder.h>
Encoder myEnc(2, 3);
#define DIR_CW +1
#define DIR_CCW -1

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {2, 3, A2};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW};
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 = A2;
int led = 13;
int dizzwold = false;
int parameters[numOfScreens] = {125, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long oldP = 0;
int encoderTurned = 0;

void setup() {
  pinMode(backlight_pin10, OUTPUT);
  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);
  printScreen();
}
void loop() {
  enc();
  analogWrite(10, parameters[0]);
  if (parameters[0] < 16) parameters[0] = 16;
  else if (parameters[0] > 254) parameters[0] = 254;
  Serial.print(encoderTurned);
  if (encoderTurned != 0)
  {
    inputAction();
    printScreen();
  }
  if (digitalRead(button) == false)
  {
    dizzwold = !dizzwold;
    digitalWrite(led, dizzwold);
    //Serial.print(dizzwold);
  }
  while (digitalRead(button) == false);
  delay(50); // keeps a small delay
}
void enc() {
  long newP = myEnc.read() / 4; //  check for encoder rotation
  encoderTurned = 0;  // Reset previous turned value.
  if ( oldP != newP) {
    if (newP > oldP) encoderTurned = DIR_CW;
    if (newP < oldP) encoderTurned = DIR_CCW;
    oldP = newP; // set oldP equal to newP so next rotation can be detected
  }
}
void inputAction()
{
  if (dizzwold == 0) // adjust screen numbers
  {
    if (encoderTurned == DIR_CW)
    {
      if (currentScreen == numOfScreens - 1)
      {
        currentScreen = 0;
      }
      else
      {
        currentScreen++;
      }
    }
    else if (encoderTurned == DIR_CCW)
    {
      if (currentScreen == 0)
      {
        currentScreen = numOfScreens;
      }
        currentScreen--;
      }
    }
  else if (dizzwold == 1)  //  adjust parameters
  {
    if (encoderTurned == DIR_CW)
    {
      parameterChange(0);
    }
    else if (encoderTurned == DIR_CCW)
    {
      parameterChange(1);
    }
  }
}
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]); // first part of array, Motor Voltage.
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]); // second part of array, Volts.
}


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

dougp

#59
Dec 19, 2017, 05:25 pm Last Edit: Dec 19, 2017, 05:29 pm by dougp
This is my position:

As long as all the values of interest are the same type, say 16-bit integers, a multidimensional array will work.  It may be somewhat wasteful of memory but since you want a step value of other than '1' for one of the parameters I'd just add another array element to hold the step value.  Now you can set a step value for each parameter.  Most will hold a '1' but you can put in whatever you want.



The upside is uniformity.  One routine will handle all the parameters, you don't need to add any weird exception logic to detect one oddball step value.  Or, multiple step values, if it ends up like that.

You'll also need to more careful about array subscripts.  If the declared dimension value is [3] and you substitute a variable in there and at runtime the variable is >3 or, <0, memory outside your expected bounds will be stepped on.  Unknown, unexpected results ensue.  Double plus ungood!
So two neutrinos went into a bar.  Nothing happened.  They were just passing through.

Go Up