Skip to content

uPesy now ships to the entire European Union

Contents Menu Expand Light mode Dark mode Auto light/dark mode

Using a rotary encoder on a Raspberry Pi Pico in Arduino code

apercu codeur rotatif KY 040

A rotary encoder is a sensor that converts an angular position into an output signal to determine the position and direction of rotation. It is widely used in motors for servo control, but also in user interfaces to replace potentiometers. In addition, most DIY modules have an integrated push button!

exemple utilisation encodeur rotatif imprimante 3d

Le bouton de contrôle des imprimantes 3D est en général un codeur rotatif

Handling a rotary encoder: the KY-040

In this tutorial, we will discover how to use this very practical module: the rotary encoder KY-040 rotary encoder, which is frequently found in DIY kits. This module can be used to create a user interface with our program: select a menu, adjust a variable..

Difference between rotary encoder and potentiometer

At first glance, the rotary encoder KY-040 rotary encoder can easily look like a potentiometer. But in fact, the potentiometer is an analog sensor and the rotary encoder is digital. While a potentiometer changes the value of a resistor, the rotary encoder has no limit of revolutions: it turns infinitely.

The rotary encoder, on the other hand, detects a number of “steps” per revolution and sends a signal at each step. The difference can be felt by touch: the potentiometer turns smoothly, while the rotary encoder turns jerkily.

The rotary encoder can be directly used by a microcontroller, as it emits logic levels. Its accuracy is determined by the number of steps per revolution, while the accuracy of the potentiometer depends on the accuracy of the ADC needed to estimate its position.

Note

A potentiometer is used to adjust analog parameters, like the volume of an amplifier. On the other hand, a rotary encoder is used to precisely determine an angular position and direction.

Theoretical operation of a rotary encoder

This tutorial doesn’t go into too much technical detail, but there’s a lot to talk about 🤓. If you want to really know the physical operation, the different technologies and the classical topologies (for example, understanding the operation of an optical quadrature phase rotary encoder 😨), I redirect you to the theoretical presentation of a rotary encoder .

Connections of the KY-040 rotary encoder to the Pi Pico

This rotary encoder has 2 signals to know the position: CLK and DT . The pin SW pin is connected to the integrated push button (SWitch).

Warning

This tutorial is more geared towards makers and does not cover the technical details in depth. However, if you want to know the technologies, the classical topologies and the physical functioning, I invite you to have a look at the theoretical presentation of a rotary encoder 🤓.

Here is a proposal to connect the Raspberry Pi Pico and the uPesy RP2040 DevKit board:

Codeur Rotatif

Rasperry Pi Pico

CLK

GP14

DT

GP13

SW

Pas utilisé ici

+

3V3

GND

GND

The scheme to be done is as follows:

ky40 rotary encoder circuit diagram Pi Pico breadboard

Circuit électronique à reproduire

ky40 rotary encoder circuit diagram RP2040 breadboard

Circuit électronique à reproduire

Note

I recommend you to supply the encoder with 3.3V in order to have logic levels according to the Pi Pico specifications.

And here is an example of breadboard mounting:

schéma breadboard codeur rotatif Pi Pico
schéma breadboard codeur rotatif Pi Pico

Knowing the angular position of the KY-040 rotary encoder

With an incremental encoder, we do not get the angle in degrees directly, but the number of increments made by the user. It is up to us to deduce the angle from the program. Here in this example, we just want to know the value of the increment.

There are different methods to determine the encoder increment. The ideal method would be to detect the steps without blocking the program as opposed to a “naive” approach which constantly checks the logic signals received by the encoder. Otherwise, the Pico may not take into account some steps if the encoder is turned very quickly.

Note

The use of hardware interrupts offers an optimal approach to detect logic level changes. These interrupts are completely detached from the CPU: we can use the loop() function to do other things.

Unfortunately, there is no ready-made library optimized for the Raspberry Pi Pico compatible with Arduino code. However, there are several ready-to-use codes written in pure C (to work with the Pico SDK).

The libraries use either classic interrupts or the PIO pins of the Pico coupled with interrupts. In fact, to make it simple, we can associate a kind of basic assembly code which will be executed by hardware blocks PIO . This allows to delegate the counter logic.

I suggest you to use this library (which works more or less on the Arduino IDE). The installation is a bit particular because it is not planned to be installed from the Arduino IDE. You just have to copy and paste the file quadrature.pio and the file quadrature.pio.h in your project folder (which contains the .ino ). They are available here in the gitHub repo .

library rotary encoder rpi pi pico arduio ide

The source files are copied into your Arduino IDE project folder

And here is the basic code to retrieve the value of the increment.

#include "hardware/pio.h"
#include "quadrature.pio.h"

#define QUADRATURE_A_PIN 13
#define QUADRATURE_B_PIN 14

PIO pio = pio0;
uint offset, sm;

void setup() {
  Serial.begin(115200);
  offset = pio_add_program(pio, &quadrature_program);
  sm = pio_claim_unused_sm(pio, true);
  quadrature_program_init(pio, sm, offset, QUADRATURE_A_PIN, QUADRATURE_B_PIN);
}

void loop() {
  pio_sm_exec_wait_blocking(pio, sm, pio_encode_in(pio_x, 32));
  uint encoder_value = pio_sm_get_blocking(pio, sm);
  Serial.println(encoder_value);
  delay(200);
}

Here we use the pio0 . To retrieve the value of the increment we must use the 2 functions pio_sm_exec_wait_blocking() and pio_sm_get_blocking() .

Note

The counting is done in the background via PIO. The increment value is retrieved only when needed.

Detecting the pressure of the push button

The library does not integrate push button detection. However it can be done easily as with a classic button with Arduino code. We could even use an interrupt to have a background detection.

List of libraries for a rotary encoder

Here is a list of other libraries that can be used in your project. I invite you to look at the presentation of each on their respective Github repository, to choose the one that will best fit your need 😊.

This section is available to premium members only. You still have 14% to discover.

Subscribe for only 5$/month

Already subscribed? Sign in

We use cookies to make your visit to the site as pleasant as possible. Privacy Policy