Rotary encoder with Raspberry Pi – OLED Menu

Today we will be seeing how to use the rotary encoder with Raspberry Pi using python programming language.One of the common usage of rotary encoder is in Industrial control but did you know that it is used in certain photographic lenses? Also they are used in rotating radar platforms etc. They are also used to track the position of the motor shaft on brush less motors with permanent magnets which are are used in robot and CNC machines.

According to Wikipedia, the definition of  a rotary encoder is “A rotary encoder, also called a shaft encoder, is an electro-mechanical device that converts the angular position or motion of a shaft or axle to an analog or digital signal”. From the appearance it gives a deception of a potentiometer. Although they can be in way called similar but they are not the same. Now having spoken a bit about the rotary encoder, lets get to know more about it and do some useful projects using it.

Hardware required

The following links are part of my affiliate links.

Raspberry PI

Banggood: https://www.banggood.com/Raspberry-Pi-3-Model-B-ARM-Cortex-A53-CPU-1_2GHz-64-Bit-Quad-Core-1GB-RAM-10-Times-B-p-1041862.html?rmmds=search&p=W214159476515201703B&cur_warehouse=CN
Amazon US: http://amzn.to/2Dw3oKT
Amazon Germany : http://amzn.to/2FUW5Sj

Rotary encoder

Banggood: https://www.banggood.com/KY-040-Rotary-Decoder-Encoder-Module-For-Arduino-AVR-PIC-p-914010.html?p=W214159476515201703B&rmmds=search&cur_warehouse=CN

Amazon US: https://amzn.to/2HFqIc4

Amazon Germany : https://amzn.to/2r8gfyr

 OLED Display:

Banggood: https://www.banggood.com/0_96-Inch-4Pin-Blue-Yellow-IIC-I2C-OLED-Display-Module-For-Arduino-p-969144.html?p=W214159476515201703B&cur_warehouse=CN
Amazon US: http://amzn.to/2tNAw0X
Amazon Germany: http://amzn.to/2Dt9bk6

Dupont Wire

Banggood:  https://www.banggood.com/40pcs-20cm-Male-To-Female-Jumper-Cable-Dupont-Wire-For-Arduino-p-973822.html?p=W214159476515201703B&rmmds=search&cur_warehouse=CN
Amazon US: http://amzn.to/2FISFmg
Amazon Germany: http://amzn.to/2pkj27N

Keyes-40

The rotary encoder that I am using for this project is called Keyes-40. You can download the datasheet from here .

Rotary encoder with Raspberry Pi
Rotary encoder with Raspberry Pi

Pinout:

The Keyes-40 rotary encoder has 5 pins namely

VCC – 5V power supply

GND –  Ground

CLK – Encoder Pin 1

DT –  Encoder Pin 2

SW – Switch (push button)

Raspberry Pi Connection:

The CLK pin is connected to pin 17 of the Raspberry Pi . The DT pin is connected to pin 18 of the Pi  and SW pin is connected to pin 27 .

KY-40   –   RPi

CLK       –      17
DT          –      18
SW         –      27

Schematics:

Rotary encoder with Raspberry Pi

Hardware connection:

Rotary encoder with Raspberry Pi

Explanation of the working:

The rotary encoder consists of a disk with a single track. This track is connected to the ground. The sliding contacts CLK and DT remains in a fixed position. As you spin the encoder knob the shaft along with the track rotates. This makes the CLK and DT connected to common ground on every contact with the track. The track is evenly discontinuous. According to the datasheet of the rotary encoder Ky-40, both the CLK and the DT pin needs to be pulled up and this make them come back to voltage level 5V. We can derive the direction in which it is revolving by detecting the order in which the pins went low (GND). The below picture explains the digital wave pattern.

Rotary encoder with Raspberry Pi

Simulate with push button:

You can very well image the rotary encoder with two push buttons connected to GPIO 17 and 18 and the other terminals to GND. Below is the schematics.

Rotary encoder with Raspberry Pi

Lets name these two buttons as CLK and DT.  If you press DT first and CLK second, then release DT and then CLK. This represents a direction movement, same way if you press CLK  first and DT second, then release CLK  and then DT , then it represents the movement is opposite direction. Remember that both the GPIO pins are assumed to be pulled up. Pulled up means that the voltage level of the pins remain at 5V and the GPIO value will be “1” and when you press the push button then the GPIO value will go to “0”.

Basic example:

With the above code the value of the variable counter  increments when you spin it clockwise and decrements when you spin it anti clockwise.

Explanation:

Line no 4,5: definition of pin numbers

Line no 6,7,8: The pins numbering is set to BCM model and then the pins are configured as input and pulled up high.

Line no 9,10: Initialising variable counter and clkLastState takes the current value of the GPIO 17.

Line no 11-24: Now the block reads the value of CLK and it if the value is different from clkLastState then read the value of dt. If it differs from the value of CLK then its incrementing, otherwise it is decrementing.

Polling vs Interrupt handling:

The above code is using the polling method. In polling method, if you want to know the value of a variable or register you keep reading always or at a specific frequency and get the value. This is CPU consuming operation and this can be solved by using Interrupt based handling. In Interrupt handling you register a function called interrupt handler or irq and specify which event you are interested in.

Basic example using interrupt:

Output:

It does the same thing as the basic example did nothing more and nothing less.

Explanation:

The only difference here is that instead of doing the entire thing in a While loop infinitely we are using a interrupt handler in the form of

GPIO.add_event_detect(17, GPIO.FALLING , callback=my_callback, bouncetime=300)

Here I am adding an event detection for the pin CLK. The event will be triggered when the pin is falling from 5V to 0V. When the event happens, the callback my_callback will be called. The bounce time is the time between one call and the other call of the event. The my_callback function is just same as what was using in the basic example, but without a while true infinite loop.

Finally, the application just waiting for keyboard interrupt using raw_input function. The entire application consumes way less CPU resource than the previous example.

Creating an OLED Menu interface:

The rotary encoders are used in control system to provide user interface. The user interface includes, Menu, Text box, Keyboard, num pad etc. Here I am going to show you how to build a menu interface with custom functions.

For that you need to get OLED display interfaced with Raspberry Pi. Refer to the here for How to interface OLED display with Raspberry Pi.

Hardware connection:

Rotary encoder with Raspberry Pi

Output

Code:

I copied the sys_info.py and demo_opts.py from the https://github.com/rm-hull/luma.examples to the folder, where I have the oled_rot_menu_rpi.py. As I am importing the sys_info module, you need to install psutil as shown below.

#pip install psutil

If you have any questions related to the above example, please use the comment section below. I would be glad to help you out. As always, thank you for visiting my site and keep following.

Rotary encoder with Raspberry Pi

5 thoughts on “Rotary encoder with Raspberry Pi – OLED Menu

  • August 22, 2018 at 7:09 pm
    Permalink

    Hello.

    Thank you for this guide. Would it be possible to add the function of the click button from the rotary encoder for selection to the code using interrupt.

    Another question. Sorry I am a newbie to Python. I am using a headless system with putty to ssh to the raspberry. How can I import the code and compile.
    Can I use nano ? Where does the file need to be stored and how can I ensure that it gets started each time the device starts

    thank you in advance for the help.

    Reply
  • September 15, 2018 at 3:02 pm
    Permalink

    Hi,
    Great article. I am working on an old radio and am replacing the internals with a raspberry pi running osmc/kodi and have just purchased the Keyes rotary encoder you mentioned above. I have the wirong as well. I now need help with the code. I am a code rookie and am wondering if you might be able to help me or or point me to a resource. My goal is to use this rotary encoder as a menu selector for Kodi.

    Thanks,
    Matt

    Reply
  • December 24, 2018 at 12:32 am
    Permalink

    hello,

    I implemented your setup but rotary encoder seems to be very inaccurate. when i turn it, it goes to the next and then comes back or it doesnt go even if i turn it like 1 revolution.

    any idea why?

    Reply
  • January 20, 2019 at 12:58 pm
    Permalink

    REally use 5Volts?
    Really?
    mmm….

    Reply
  • June 7, 2019 at 6:40 pm
    Permalink

    Dear Codelectron,

    i tried out your Code “oled_rot_menu_rpi.py” and it worked. I thought in the first time…

    but then I had the

    I tried to insert the “Sleep(0.01)” with different values because I thought it has something to do with bouncing… then I recognized that there is a debouncing value at the and of the code. So I tried to Change it to different values. I even tried a different rotary Encoder. but the result wasn’t really different. This makes me Pretty sure that there is a mistake in the code but I don’t know where.
    If you have a look on the terminal it gives you the following Output for some turning on the knob:

    ###
    Ending
    1
    Ending
    0
    Ending
    Ending
    1
    Ending
    0
    Ending
    1
    Ending
    0
    Ending
    1
    Ending
    Ending
    Ending
    Ending


    ###

    If the multiple “Ending” Output appears I tried to turn very fast. Nothing Happening. Not printing the counter and not hopping through the menu entries.

    Since I would like to use this menu for a different Programm I would love to hear from you. Maybe you can tell me what’s wrong here?!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *