Go Down

Topic: LCD menu with encoder (Read 1 time) previous topic - next topic

Jul 31, 2018, 09:38 pm Last Edit: Jul 31, 2018, 09:43 pm by adamaero
Is this LCD menu missing code for the encoder?
https://forum.arduino.cc/index.php?topic=53265.0

I plan to integrate this code with the previous, if needed. I thought
#define MOVECURSOR 1
#define MOVELIST 2
were pins for the encoder...

The function read_encoder() is not declared--because it doesn't exist!

So I inserted this:
Code: [Select]
int8_t read_encoder(){ // By Oleg Mazurov
// returns change in encoder state (-1,0,1)
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
static uint8_t old_AB = 0;
/**/
old_AB <<= 2; //remember previous state
old_AB |= ( ENC_PORT & 0x03 ); //add current state
return ( enc_states[( old_AB & 0x0f )]);
}


Still working on other bugs, but the "Simple universal LCD menu code" is missing something involving the encoder, right?

econjack

Why not take an encoder example and expand that to do your LCD menu?

#2
Aug 01, 2018, 04:38 pm Last Edit: Aug 01, 2018, 05:03 pm by adamaero
Why not take an encoder example and expand that to do your LCD menu?
I plan to integrate [this code](https://www.instructables.com/id/Improved-Arduino-Rotary-Encoder-Reading/) with the previous, if needed. I thought
#define MOVECURSOR 1
#define MOVELIST 2
were pins for the encoder...

#3
Aug 01, 2018, 11:36 pm Last Edit: Aug 01, 2018, 11:41 pm by adamaero
Well, I know there is something that needs to be taken out. The LCD menu seemed to have some code for the encoder. Wish someone would've commented on if all that is needed is the read_encoder() routine.

Code: [Select]

/*
  Mega 2560 (Tools → Board)
*/
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define MOVECURSOR 9  // constants for indicating whether cursor should be redrawn
#define MOVELIST 10
#define ENC_PORT PINC // https://arduino.stackexchange.com/a/21296/47871

const byte totRows = 4;  // total rows of LCD
const byte totCols = 20;  // total columns of LCD
unsigned long timeoutTime = 0;  // this is set and compared to millis to see when the user last did something.
const int menuTimeout = 10000; // time to timeout in a menu when user doesn't do anything.
const int a = 30;  // Paragon // 30 mm = 1.2" = 0.1'
const int b = 61;  // 0.2 foot paragon
const int c = 91;  // 0.3 foot paragon       
const int d = 122;  // 0.4 foot paragon
const int e = 152;  // 0.5 foot paragon
const int f = 183;  // 0.6 foot paragon       
const int g = 213;  // 0.7 foot paragon

unsigned long startMillis;
unsigned long currentMillis;
unsigned long currentMillisA;
unsigned long currentMillisD;
unsigned long currentMillis1;
const unsigned long period = 1000;
const byte txPin3 = 14;
const byte rxPin3 = 15;
const byte txPin2 = 16;
const byte rxPin2 = 17;
const byte pinAnalog = 2;
const byte pinDigital = 3;  // slide switch switch allows user to select (input) test
const byte pinOneWire = 4;
const byte oneWireBus = 5;
const byte pinAnalogW = 6;    // write (output) to test datalogger
const byte pinDigitalW = 7;   //                                  ----------------
const byte pinOneWireW = 8;   //                                  ----------------
const byte pinA = 22; // 1st hardware interrupt: CLK
const byte pinB = 26; // 2nd hardware interrupt: DT
volatile int diffFromParagon = 0;
volatile int inch = 0;
// https://forum.arduino.cc/index.php?topic=418692.0 // volatile
volatile byte aFlag = 0; // indicates when expected rising edge: pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // (opposite direction to when aFlag is set for pinB)
volatile byte encoderPos = 0; // encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; // last encoder position value, compares to current reading (to know when to print to the serial monitor)
volatile byte reading = 0; // stores direct values read from interrupt pins before checking to see if moved a whole detent

LiquidCrystal lcd(52, 50, 49, 47, 43, 41); // Arduino pins. Creates object.
    // LCD pin (RS enable D4 D5 D6 D7) parameters
OneWire oneWire(oneWireBus);
    // Setup a oneWire instance to communicate with any OneWire devices 
    // (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire);
    // Passes oneWireBus reference to Dallas Temperature.

void setup() {
  startMillis = millis();  // initial start time
 
// LCD code:
  Serial.begin(9600);
  lcd.begin(20, 4);
 
// pinMode not needed for INPUT (default) operator
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
 
// encoder code:
  pinMode(pinA, INPUT_PULLUP); // pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT_PULLUP);
  attachInterrupt(0,PinA,RISING); // interrupt, looking for rising edge signal and
  attachInterrupt(1,PinB,RISING); // executing the "PinX" Interrupt Service Routine (below)
  Serial1.begin(115200); // pin 18 (TX) & 19 (RX)
  digitalWrite(pinB, HIGH);

// oneWire sensors:
  sensors.begin();
}

void loop() {
  currentMillis = millis(); // milliseconds since start
 
  lcd.setCursor(0, 0);
  lcd.print("Welcome.");
  lcd.setCursor(0, 1);
  lcd.print("Ready to make a selection.");
 
  byte analogSelection = digitalRead(pinAnalog);   // 2
  byte digitalSelection = digitalRead(pinDigital); // 3
  byte oneWireSelection = digitalRead(pinOneWire); // 4

  if(analogSelection == HIGH)
  {
    currentMillisA = millis();
    if(currentMillisA - startMillis > 1000*60) // one min.
    {
      lcd.clear();
      lcd.setCursor(0, 0);        // 1st line
      lcd.print("Testing...");
      lcd.setCursor(0, 1);        // 2nd
      lcd.print("Analog inputs");
      lcd.setCursor(0, 2);        // 3rd
      lcd.print("Please wait.");     
      for(int pin = 0; pin < 8; pin++)
        for(int s = 63; s <= 255; s += 64)
          {          // PWM: 255 = 5V
            analogWrite(pin, s);      // sweeps 1.24, 2.5, 3.75 & 5V
            delay(500);
         }
    }
  }
  else if(digitalSelection == HIGH)
  {
    currentMillisD = millis();
    if(currentMillisD - startMillis > 1000*60) // one min.
    basicMenu();    /////////////////////////////////////////////////// TEST CONTIUNITY FOR THE SENSOR ON PIN 4 TO CHEDFKCK!@!#@
  } 
  else if(oneWireSelection == HIGH)
  {
    currentMillis1 = millis();
    if(currentMillis1 - startMillis > 1000*60); // one min.
    lcd.print("Testing temperatures...");
    sensors.requestTemperatures(); // gets temperature readings
    lcd.print("Temperature is: ");
    lcd.print(sensors.getTempCByIndex(0)); // Why "byIndex"? 
   // "0" refers to the first IC on the wire
   // (You can have more than one DS18B20 on the same bus.)
  }
  else  // multiple inputs toggled at once, error message:
    lcd.print("Only select one test at a time.");
  // https://forum.arduino.cc/index.php?topic=223286.0  Maybe multiple things can happen...

   
  // Original encoder code (but it was incomple: had to read_encoder() routine
 static byte counter = 0;      //this variable will be changed by encoder input
 char tmpdata;
 tmpdata = read_encoder();

  // New encoder code (might conflict with original above)
  if(oldEncPos != encoderPos)
  {
    Serial1.println(encoderPos);
    oldEncPos = encoderPos;
  }   
}


The rest of the code--the function definitions--is in the complete sketch attached.

Delta_G

#4
Aug 01, 2018, 11:47 pm Last Edit: Aug 01, 2018, 11:48 pm by Delta_G
Well there's obviously this section:

Code: [Select]
// encoder code:
  pinMode(pinA, INPUT_PULLUP); // pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT_PULLUP);
  attachInterrupt(0,PinA,RISING); // interrupt, looking for rising edge signal and
  attachInterrupt(1,PinB,RISING); // executing the "PinX" Interrupt Service Routine (below)
  Serial1.begin(115200); // pin 18 (TX) & 19 (RX)
  digitalWrite(pinB, HIGH);


Which mentions two interrupt routines that look like they probably go with the encoder.

And if you look they are a bit bloated but it looks like they are meant to read an encoder in a slightly over-thought way.

Reading an encoder is WAY easier than all this mess.  All you need to do in the ISR is compare the two pins to see if they are in the same state or not.  If they are in the same state then you're rotating one way and if not then the other way.  For the other pin it will be exactly the opposite in direction. 

Otherwise I'm not real sure what exactly you are asking here.



BTW:  Big ole bug hiding here:

Code: [Select]
if(currentMillisA - startMillis > 1000*60)

60000 doesn't fit in an int but 1000 and 60 both do, so the math overflows.  Use:

Code: [Select]
if(currentMillisA - startMillis > 1000ul*60)
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

#5
Aug 03, 2018, 03:56 pm Last Edit: Aug 03, 2018, 03:59 pm by adamaero
I inserted the menu routine which seemed like it was for an encoder. I found it was incomplete (also asked about on that arduino forum's page).

So I added read_encoder(). I then integrated the "bloated" code because I think the menu routine is still missing things. So now I believe I have unnecessary code.


...Good this is my full-time job right now; it's taking forever for what I thought was adding a simple LCD menu functionality. I'll spend more hours trying to understand what is needed for it to work...


Delta_G

#6
Aug 03, 2018, 03:59 pm Last Edit: Aug 03, 2018, 04:00 pm by Delta_G
Here's one that I have been using.  It might have a little more than you want, but it is at least something to look at.  It is sort of advanced so if you don't know the basics of C++ coding it's probably going to go over your head.  It works well and has a small footprint, but you need to have some C++ knowledge to work with it. 

https://github.com/delta-G/REBL_UI

https://forum.arduino.cc/index.php?topic=358066.0
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

#7
Aug 03, 2018, 05:12 pm Last Edit: Aug 03, 2018, 05:13 pm by adamaero
I took a C++ course about three years ago, and now mostly use MATLAB during the semester. (I'm a senior electrical engineering student.)

I just want to complete this summer project, whatever the means. I decided to see if the current program works, and I'm getting a timeout error after uploading to the Mega 2560.

Delta_G

I decided to see if the current program works, and I'm getting a timeout error after uploading to the Mega 2560.
That's a communication issue between your computer and your board.  That has nothing to do with the code.  You need to get that fixed first.  Try uploading the blink example until you can get that to work to show that you have good communication and then come back to the larger code. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Thanks! You are right. (Took IT half-a-day to install the driver.) Blink is now blinking the LCD screen too...just trying to get the LCD examples to work...

#10
Aug 09, 2018, 08:39 pm Last Edit: Aug 09, 2018, 09:19 pm by adamaero
but you need to have some C++ knowledge to work with it.https://github.com/delta-G/REBL_UI

https://forum.arduino.cc/index.php?topic=358066.0
I do not know C++ classes that well. Although, I am still trying. Is Time.h built in? I couldn't find that on your GitHub.

#11
Aug 09, 2018, 09:30 pm Last Edit: Aug 09, 2018, 09:33 pm by adamaero
OK, well I found a Time library: https://github.com/PaulStoffregen/Time

I'm just trying to get the REBL_UI_Example to work:

Code: [Select]
MenuItem PROGMEM menuItems[] = {
 { "display", fun1   }  ,
 {"press", pressToExit   }  ,
 {"enter number", pickNumber   }  ,
 {"enter string", fourLetterWord   }  ,
 {"set time", enterTime   }  ,
 {"show time", showTime   }
};

fun1, pressToExit, etc

Says they're not declared.

Delta_G

Maybe you need forward declarations to those functions.

I've seen a few people say that they got this error, but I have yet to see anyone post the ACTUAL COMPLETE error message or the code as they have it entered.  So I don't know what else you want me to do without any information. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Today, I put the function definitions before void loop(). No change. I think I'll try to make the half-baked program work instead. That one compiles, at least for me. Although, I really hoped to use a menu + rotary encoder library; I will be using this HMI for future projects.

Delta_G

Again, I'd love to help you out with that but you'd have to give me the error messages first.  Seriously, how do you expect me to tell you how to fix an error if you won't show me the error messages?   
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Go Up