Go Down

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

artisticforge

I really appreciate your time, But I have tried everything to understand how to make this, I've seem a lot of code for menu and all of them have a sub screen which I don't need, I have spend several hours in front of the computer trying different thing to make any of the code i get work and trying to understand how they work I'm just not understand it. I'm trying my best to give you what I know so you can help me.

I think it be easier for both of us to start over, You need to know the encoder I'm using and I'm not for sure with one, I know I download it from the library, But if you know of one off the top of your head we can work with lets try that so we are on the same page.

I do apologize for not know how to do, I never done encoder or menu on LCD screen before. Mostly all i have done is use them to display message of machine.

As you know I have a Encode and 20x4 LCD display with the IC2 backpack. I need a menu that I can scroll through and pick what I want the machine to.

Display exmaple:

>LED1
>LED2
>LED3
>LED4
Etc.

After scrolling though and finding the LED I want to use. I will then click the encode(singleClick). It will turn the LED that I pick to true.

Example: Scroll down to >LED8
Click the Encoder.
LED8 = true.
After it done runnning the code.
LED8 = false.
return the Menu back to LED.

I'm asking for you help in Pretty much everything in Writing this code because I haven't got anywhere.
I haven't learned anything.

I really hope you can help me because I have worked so hard in the project and this is the last thing I need for it to be done.

If you like to Private message me I can give you my email.

Allow me to help you.
Would you mind restating your problem/project?

I will try my best to provide you with a workable solution.
Being frustrated does no one any good.
It turns you (generic you) off programming and arduino.
I will read your posts in the morning and go through the background.

Delta_G

#16
Dec 07, 2017, 05:28 am Last Edit: Dec 07, 2017, 05:29 am by Delta_G
I really appreciate your time, But I have tried everything to understand how to make this, I've seem a lot of code for menu and all of them have a sub screen which I don't need, I have spend several hours in front of the computer trying different thing to make any of the code i get work and trying to understand how they work I'm just not understand it. I'm trying my best to give you what I know so you can help me.
The one I posted in reply #1 will work with any number of screens.  It is probably a little more complex than what you are after, but really all you'd have to do is switch out the LCD library to the one you use and write all of the functions to light the light and return true. 

I think it be easier for both of us to start over, You need to know the encoder I'm using and I'm not for sure with one, I know I download it from the library, But if you know of one off the top of your head we can work with lets try that so we are on the same page.
I don't use a library for an encoder.  It's a really simple device.  I find it easier to understand how it works than to hide the details behind some library.  Give me a second and I'll post my normal type of encoder code.

I do apologize for not know how to do, I never done encoder or menu on LCD screen before. Mostly all i have done is use them to display message of machine.
Don't apologize.  We all have things we don't know how to do.  I bet you can do lots of things I can't. 

As you know I have a Encode and 20x4 LCD display with the IC2 backpack. I need a menu that I can scroll through and pick what I want the machine to.

Display exmaple:

>LED1
>LED2
>LED3
>LED4
Etc.

After scrolling though and finding the LED I want to use. I will then click the encode(singleClick). It will turn the LED that I pick to true.

Example: Scroll down to >LED8
Click the Encoder.
LED8 = true.
After it done runnning the code.
LED8 = false.
return the Menu back to LED.

I'm asking for you help in Pretty much everything in Writing this code because I haven't got anywhere.
I haven't learned anything.
Haven't learned anything?  That's troubling.  Maybe you have just started off with something too complex.  When you learn to swim, you don't do so by trying to swim across an ocean.  You would just drown and get nowhere.  Maybe it would help to put this aside for a bit and study up on the basics a little.

I really hope you can help me because I have worked so hard in the project and this is the last thing I need for it to be done.

If you like to Private message me I can give you my email.

Help on the forum is free.  Private help means you have to hire me and I am VERY VERY expensive.  We should probably keep this on the forum.  I only really come on here when I'm out on the road stuck in some hotel room bored out of my mind.  When I get home or have some work to do I will just disappear and you might not hear from me for some time.  But out here on the forum someone else can jump in and continue helping you out. 


Expect another post in a few minutes with some encoder code.
If at first you don't succeed, up - home - sudo - enter.

Nicole1998

Alright So I have a machine that has 10 different thing it can do. All the thing are set to false in the program until I Press a button, I would like to change the buttons so I don't need 10 of them.

I need the button on the encoder and the LCD display to change (int) to true. After it runs through the code, at the end I have it setting the (int) back to false so i can run something else.

I buy a encoder, and a 20x4 LCD display to take place of the buttons.

I would like to have a scroll menu with a cursor that scroll down the left side of the LCD screen till I get to the function I would like to run.

I have no code for it, I have try multiple menu codes and all of them are using different layers and changing values.

All I need is a menu(1 Layer). and as I scroll the Encode I need the cursor to move down the LCD display until I get to what I want to run.

If i press down on the encoder(single Click). The menu will go away and the LCD Display will print what the machine is doing until it is done. After its done it will return to the Menu to start over. (NO Values to change, no Sub menu inside menus, just ONE layer).

I have searched and couldn't find anyone that has done anything like this, I though it was going to be a little easier then what i have been though to get this to work.

Delta_G

#18
Dec 07, 2017, 05:57 am Last Edit: Dec 07, 2017, 05:59 am by Delta_G
If you look at the gray code that an encoder puts out, you can see an easy way to tell which way it is turning.  Start by looking only at one pin.  When its state changes, if the other pin is in the same state then the encoder is going one way and if the other pin is in the opposite state then the encoder is going the other way.  If you are looking at state changes on the second pin then the same holds true but the directions are reversed.  If that doesn't make sense yet then google "encoder gray code" and see if you can learn how the waveform works. 

Here's a picture:





Now one more thing about encoders.  As you spin them that waveform keeps moving, so you really need to check the state of the other line at the very instant that you notice the state change on one pin.  So it is common to use an interrupt for that.  If you don't know about those, stop here and google "Arduino Hardware Interrupt" and do some reading to learn what those are.  The important thing is that on an UNO those are on pins 2 and 3 so we MUST use those pins.


So here is some code that illustrates the point well, but won't work for a reason I'll explain afterwards.

Code: [Select]

// Code compiles but is untested
// In reality it would be too slow
// But it is easier to understand the
// concept here with digitalRead than
// it is with diret port reads
// I have used the same code written
// with port reads many times to read
// encoders.  It works. 

// If your encoder gives four increments per "click"
// and you only want one, then remove one interrupt
// entirely and set the other to RISING or FALLING
// instead of CHANGE. 

// The two pins from the encoder
const byte epinA = 2;
const byte epinB = 3;

int printInterval = 500;

volatile int encoderCount = 0;

void setup(){

  Serial.begin(115200);

  attachInterrupt(digitalPinToInterrupt(epinA), eintA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(epinB), eintB, CHANGE);
 
}

void loop(){

  static unsigned long pt = millis();
  unsigned long ct = millis();
 
  int encoderRead = 0;

  if(ct - pt >= printInterval){
    cli();
    encoderRead = encoderCount;
    sei();
    Serial.println(encoderRead);
  }
 
}
/*
  This is actually too slow for fast encoders.
  Should use direct port reads instead of
  digitalRead.  But this illustrates the point.
  if your encoder ends up going backwards
  just switch the ++ and -- in both ISR's.
*/

void eintA(){
  // if the pins read the same we're going one direction
  // else we're going the other direction.
  if(digitalRead(epinA) == digitalRead(epinB)){
    encoderCount++;
  }
  else {
    encoderCount--;
  }
}

void eintB(){
  // Same as above, except the directions are switched for
  // the other pin. 
  if(digitalRead(epinB) == digitalRead(epinA)){
    encoderCount--;
  }
  else {
    encoderCount++;
  }
}


The loop is just a regular Blink Without Delay style timing code that prints the encoder count to the screen once every so often.  The important bit is the cli() and sei() which turn off and then back on the interrupts on either side of copying that reading to another variable.  This is important because it takes more than one clock cycle to copy that value and we don't want the interrupt to trigger and change it in the middle of while we are reading it.  (google "critical section" for more information on that)

Unfortunately that code will *almost* work.  But I included it because what is about to happen is probably a little over your head and I want you to be able to see what is really going on in the next code.  See, the problem is that digitalRead can be too slow to catch the state on an encoder that is moving very fast.  We need a faster way to read a digital pin and this comes from direct port reads.  Please take a little while to study that page.  You don't really need to know all of it, you just need to get the basic idea that I am reading the hardware directly.  This is what digitalRead does for you behind the scenes. 


So now my code becomes this:

Code: [Select]

// The two pins from the encoder
const byte epinA = 2;
const byte epinB = 3;

int printInterval = 500;

volatile int encoderCount = 0;

void setup(){

  Serial.begin(115200);

  attachInterrupt(digitalPinToInterrupt(epinA), eintA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(epinB), eintB, CHANGE);
 
}

void loop(){

  static unsigned long pt = millis();
  unsigned long ct = millis();
 
  int encoderRead = 0;

  if(ct - pt >= printInterval){
    cli();
    encoderRead = encoderCount;
    sei();
    Serial.println(encoderRead);
  }
 
}
/*
  Port reads are way faster than digitalRead
  if your encoder ends up going backwards
  just switch the ++ and -- in both ISR's.
*/

void eintA(){
  // if the pins read the same we're going one direction
  // else we're going the other direction.
  if(!!(PIND & 4) == !!(PIND & 8)){
    encoderCount++;
  }
  else {
    encoderCount--;
  }
}

void eintB(){
  // Same as above, except the directions are switched for
  // the other pin. 
  if(!!(PIND & 8) == !!(PIND & 4)){
    encoderCount--;
  }
  else {
    encoderCount++;
  }
}



The !! looks confusing, but all it is doing really is letting me treat a number as a boolean.  !someNumber is true if the number is 0 and false if the number is not 0.  An extra ! gets me back to true for numbers that aren't 0 and false for 0.  Basically, it converts any number that isn't 0 into a 1.  So my bitmath would result in 4 or 8 for the two pins which obviously isn't equal.  But by using !! I can say !!8 == !!4.  If that's still confusing then just take my word for it that it works. 

So now I have a counter that will count up or down depending on which way I turn my encoder. 

Look now, I gave you a lot of links here and things to google.  That whole thing about you not learning anything is about to change.  I expect this might take a while for you to study through, maybe even a day or two.  If you will, then you will learn a lot more than just how to work an encoder.  Take your time and when you get how this is working then we will put it together with your display to make a menu. 

PLEASE, if you don't understand some part of this ask questions, but ask specific questions.  I'm not going to like "I just don't get it".  If that is the case then you need to keep at the things I told you to read or google until you do start to get it. 
If at first you don't succeed, up - home - sudo - enter.

Nicole1998

Quote
The one I posted in reply #1 will work with any number of screens.  It is probably a little more complex than what you are after, but really all you'd have to do is switch out the LCD library to the one you use and write all of the functions to light the light and return true.  
I have try download it but I can't find the library to? do you have a link?

Delta_G

#20
Dec 07, 2017, 06:05 am Last Edit: Dec 07, 2017, 06:05 am by Delta_G
This is another important page.  You should really just read everything on it or linked from it. 

https://www.arduino.cc/reference/en/
If at first you don't succeed, up - home - sudo - enter.

Delta_G

I have try download it but I can't find the library to? do you have a link?
There is a link in the very first post on that second thread that I linked to in #1.  Still, that one may be a bit complex for you.  I don't know that it is a good fit.  You'll have to learn about virtual classes and it might be easier to just learn how to read an encoder.  You really don't need most of the things that code is capable of.  I was just pointing out that it does work for a single layer.  But it isn't going to be a drop in solution.  You'll have to do some editing of it to switch it to work with the I2C LCD and you'll have to really understand the explanation of how to write the functions you want the menu to call.  They must have a very specific function signature.   
If at first you don't succeed, up - home - sudo - enter.

Nicole1998

I have when back through everything, I when back to the Link you send to me using MenuClass, I got the libeary and I have try to use it and it throws Error fun1 is not in scope.
I think I understand a little bit more now and I might be about to get this code to work. But I'm not sure on the Error.
Any Ideas?

Delta_G

#23
Dec 08, 2017, 01:36 am Last Edit: Dec 08, 2017, 01:37 am by Delta_G
I got the libeary and I have try to use it and it throws Error fun1 is not in scope.
Did you make the modifications that it needs?  Did you read the part where I said it probably wasn't what you needed? 

I don't have a copy of the IDE with me right now so I can't try to compile it.  Will try later.  It worked last time I tried it, but it's been a long time since I've tried to use that example. 
If at first you don't succeed, up - home - sudo - enter.

Nicole1998

Quote
Did you make the modifications that it needs?  Did you read the part where I said it probably wasn't what you needed?
I didn't know anything need to be changed just to get it upload? I known that i need to add the LCD screen but I was just going to see how it worked with the serial to get a understand?

I couldn't fine anywhere that need to change something?

Delta_G

Are you playing with the Simple menu (works with buttons) or REBL (works with encoders).  REBL has the LCD pretty well integrated into it.  It's going to be hard to run that on the serial monitor without serious modifications. 

If you're using the Simple Serial Menu then you have to derive your own class from it.  Like I said, it's not the kind of code you can just copy in and see it work.  This is code for coders who know how to code and can look at it and pick it apart and make it work for them.  I think you should probably just stick to what you were doing. 

Have you been able to get an encoder to work yet?  Forget the LCD and everything else.  Can you get just an encoder working by itself to increase or decrease a variable?
If at first you don't succeed, up - home - sudo - enter.

Go Up