Using Rotary Shaft Encoder to Control Variables (phi_interface)

I am using the Phi_interface library and this code:

#include <phi_interfaces.h>

#define Encoder1ChnA 2
#define Encoder1ChnB 3
#define EncoderDetent 12

char mapping1[]={'U','D'}; // This is a rotary encoder so it returns U for up and D for down on the dial.
phi_rotary_encoders my_encoder1(mapping1, Encoder1ChnA, Encoder1ChnB, EncoderDetent);
multiple_button_input* dial1=&my_encoder1;

void setup()
{
  Serial.begin(9600);
  
}

void loop()
{
  char temp;
//Rotary encoder 1:  
//  temp=my_encoder1.getKey(); // Use phi_keypads object to access the keypad
  temp=dial1->getKey(); // Use the phi_interfaces to access the same keypad
  if (temp!=NO_KEY) Serial.println(temp);
}

I have 2 problems...

  1. How do I change the pin numbers of channel A and B (changing the numbers in the define command does not seem to work).

  2. How do I actually use the "U" and "D" to control a variable... for instance: If (temp == U); seconds++; and If (temp == D); seconds--;

So basically if the shaft encoder turns clockwise then the seconds increase and vice versa for anti clockwise.

Could you give me an example code please

  1. How do I change the pin numbers of channel A and B (changing the numbers in the define command does not seem to work).

If the encoders use interrupts, which is typical, you can't. The interrupts are tied to those two pins. You'd need to look at the source code to see if interrupts are used.

GUNN, PaulS,

The library is simple state machine and not using interrupts. To change pins, do the following:

#define Encoder1ChnA Your_channel_A_pin
#define Encoder1ChnB Your_channel_B_pin

These two defs are used in the later constructor:

phi_rotary_encoders my_encoder1(mapping1, Encoder1ChnA, Encoder1ChnB, EncoderDetent);

To use the return values say to turn on and off pin13 LED, you can do the following:

temp=dial1->getKey(); // Use the phi_interfaces to access the same keypad
if (temp=='U') digitalWrite(13,HIGH);
if (temp=='D') digitalWrite(13,LOW);

Be sure to use single quotation signs for the above.

You have to put this in the setup to make pin 13 output:

pinMode(13,OUTPUT);

@liudr
Hi
i am trying to use your lib example "phi_prompt_example_menu_20x4_display with encoder and Matrix keypad. The problems i have are:

  1. The example phi_rotary_encoders_example_01 works perfect
  2. The example phi_matrix_keypads_example also works
  3. I tried to implement both input devices in the above example
  4. scrolling thru the menu does not work in 20x4 mode. The jump from 1/5 is directly to 4/5
  5. In the 16x2 mode the EncoderDetent isn't detected.

My changes in the code:

char mapping[]={'1','2','3','4','5','6','7','8','9','*','0','#'}; // This is a matrix keypad.
byte pins[]={27, 26, 25, 24,30, 29, 28}; // The first four pins are rows, the next 4 are columns. If you have 4*3 pad, then the first 4 are rows and the next 3 are columns.

phi_matrix_keypads my_btns(mapping, pins, 4, 3);
/*
phi_serial_keypads debug_keypad(&Serial,9600);
multiple_button_input * keypads[]={&my_btns,&debug_keypad,0};
*/
char up_keys[]={1,0}; ///< All keys that act as the up key are listed here.
char down_keys[]={2,0}; ///< All keys that act as the down key are listed here.
char left_keys[]={3,0}; ///< All keys that act as the left key are listed here.
char right_keys[]={4,0}; ///< All keys that act as the right key are listed here.
char enter_keys[]={5,0}; ///< All keys that act as the enter key are listed here.
char escape_keys[]={6,0}; ///< All keys that act as the escape key are listed here.
char * function_keys[]={up_keys,down_keys,left_keys,right_keys,enter_keys,escape_keys}; ///< All function key names are gathered here fhr phi_prompt.

#define Encoder1ChnA 11
#define Encoder1ChnB 10
#define EncoderDetent 31

char mapping1[]={'2','8'}; // This is a rotary encoder so it returns U for up and D for down on the dial.

phi_rotary_encoders my_encoder1(mapping1, Encoder1ChnA, Encoder1ChnB, EncoderDetent);
//multiple_button_input* dial1=&my_encoder1;
multiple_button_input * keypads[]={&my_encoder1,&my_btns,0};

I also don't understand the code:
char up_keys[]={1,0}; ///< All keys that act as the up key are listed here.
char down_keys[]={2,0}; ///< All keys that act as the down key are listed here.
an so on.
What does this mean?

I would like to position on a menu line with the encoder, select with the encoder button or '#' button on the matrix keypad and the use the keypad for entry. Is this possible?

Please be so kind and give some help.
Thank you

Hah, I just coded an Optical Shaft Encoder: counts degrees, determines direction (clock-wise/counter-clock-wise), etc. If you need any help with it just send me a PM. Pretty simply stuff though, I'm sure you are capable.

The char up_keys[]={1,0}; is incorrect.

It should look like char up_keys[]={'1',0};

The array should contain characters like '1', '2', 'U' etc., whose values are found in ASCII table. It should be terminated with a zero, not '0'. You used 1, which is not an ascii character.

The array provides a list of all key values (with getKey) that should be treated as UP. These key values are defined in the keypads and rotaryencoders classes. UP has many behaviors in different functions of phi_prompt. If you select menu, UP moves highlight on the menu item one line up. If you enter character with UP, then the character is incremented so if it is originally 'B', pressing up with 'B' in focus makes it go to 'C'. Think about the arcade games when you make to the high score. How do you enter your name, up-up-up.... until you see your last name initial, then right, some more ups until you get all 3 characters.

You also had this definition twice with different values:

multiple_button_input * keypads[]={&my_btns,&debug_keypad,0};

The following should be included and the duplicate deleted:

multiple_button_input * keypads[]={&my_btns,&my_encoder1, &debug_keypad,0};

This line tells phi_prompt to listen to all the listed input devices when you call its library functions. You are always recommended to include the serial port as a debug keypad so you can send key presses directly from your serial port to test your program if you want, cool?

I recommend using different key values for the keypad and the encoder. Say the keypad has the 12 key values you had already, then encoder has char mapping1[]={'U','D'};

Then you tell phi_prompt that either 'U' or '2' should be treated as up by this:

It should look like char up_keys[]={'1','U',0};

The order of '1' and 'U' is not important. Same goes with down_keys. You can also use a buttons_group to sense the rotary encoder shaft click if your shaft has a button.

Now if you rotate up or press '2' you see the UP behavior. Later if you wish to reappropriate rotary encoder for different things, just remove the 'U' from up_keys and rotating it up won't be treated as UP anymore.

Dottore you saved a life.
Everything now works perfect. But i still have a small problem. Your suggestion:

Now if you rotate up or press '2' you see the UP behavior. Later if you wish to reappropriate rotary encoder for different things, just remove the 'U' from up_keys and rotating it up won't be treated as UP anymore.

now my code looks like this:

char up_keys[]={'2','U',0}; ///< All keys that act as the up key are listed here.
char down_keys[]={'8','D',0}; ///< All keys that act as the down key are listed here.

I modified this procedure like this:

void top_menu_function_1() //Replace this with the actual function of menu item #1
{
  lcd.clear();
  lcd.print("Collecting data.");
  lcd.setCursor(0,1);
  lcd.print("-Encoder OFF-");
  char up_keys[]={'2',0};
  char down_keys[]={'8',0};
  wait_on_escape(4000);

}

Rotating the encoder is still working as Up and Down. Did i misunderstand something?
BTW is it possible to insert only one button in a Button Group ?

The following should go before your setup(). I believe you have them already in the right place:

char up_keys[]={'2','U',0}; ///< All keys that act as the up key are listed here.
char down_keys[]={'8','D',0}; ///< All keys that act as the down key are listed here.

These are not going to make any effect since the original arrays defined before setup() are STILL being used by phi_prompt.

  char up_keys[]={'2',0};
  char down_keys[]={'8',0};

To really disable the encoders, do this instead:

/* remove these two lines
  char up_keys[]={'2',0};
  char down_keys[]={'8',0};
*/
// Replace with these two lines
  up_keys[1]=0;
  down_keys[1]=0;

What "up_keys[1]=0;" does is to erase the 'U', which is stored in up_keys[1] location. If you want it back, up_keys[1]='U';

Give it a try!

If you want to trick somebody or enable "reverse pitch" like flying and shooting games for up/down reversal (don't know who would want that), do up_keys[1]='D'; and down_keys[1]='U'; at some point in your code :wink:

FYI, I have these neat things:

http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/rotary-encoder-keypad-kit-20x4-lcd/

http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/rotary-encoder-keypad-kit-20x4-lcd/

They work as a serial keypad and have integrated phi_prompt onboard.

Thanks for your help and the offer. I'll come back to if i ever get my system running perfect.

Sorry but your suggestion

/* remove these two lines
  char up_keys[]={'2',0};
  char down_keys[]={'8',0};
*/
// Replace with these two lines
  up_keys[1]=0;
  down_keys[1]=0;

did not work. The encoder was still alive. So what i changed is

/*i removed these two lines
  char up_keys[]={'2',0};
  char down_keys[]={'8',0};
*/
// in the init section this is declared
// char mapping_e[]={'U','D'}; // This is a rotary encoder so it returns U for up and D for down on the dial.
// i inserted these lines

  mapping_e[0] = 0;
  mapping_e[1] = 0;

This works. The encoder is quite now. But i'll have to init it each time i need the encoder. As i would like to enter numbers a text with the encoder will i have to write a complete new procedure? What am i doing wrong with your proposal ( up_keys[1]=0; down_keys[1]=0; ) ???

Post your complete code. I'll take a look when I have time.

Okay here is my code. It is actually your demo code which i modified a bit.
I neither got the encoder button running nor did i succeed in switching of the encoder.
Thanks for your help.

luidr.ino (5.18 KB)

Example_menu.ino (8.69 KB)