top of page
Writer's pictureRamesh G

ESP32 Rotary Encoder LED Control with 7segment Display


In this tutorial, you'll learn how to control an LED using a rotary encoder and display the status on a Max7912 8-digit 7-segment display with an ESP32. We’ll go through the steps to connect the hardware, write the code, and control the LED based on rotary encoder input. Let's break it down.


Circuit Diagram:


Components Required:

ESP32 Development Board

Rotary Encoder

Max7912 8-Digit 7-Segment Display

LED

220 Ohm Resistor (for LED)

Breadboard and Jumper Wires

Power Supply (5V or 3.3V depending on your setup)


The KY-040 rotary encoder is a rotary input device (as in knob) that provides an indication

of how much the knob has been rotated AND what direction it is rotating in. It’s a great

device for stepper and servo motor control. You could also use it to control devices like

digital potentiometers.



A rotary encoder has a fixed number of positions per revolution. These positions are easily felt as small “clicks” you turn the encoder. The KY-040 module has thirty of these positions. On one side of the switch there are three pins. They are normally referred to as A, B and C. In the case of the KY-040, they are oriented as shown. Inside the encoder there are two switches. Once switch connects pin A to pin C and the other switch connects pin B to C. In each encoder position, both switches are either opened or closed. Each click causes these switches to change states as follows:

  • If both switches are closed, turning the encoder either clockwise or counterclockwise

one position will cause both switches to open.

  • If both switches are open, turning the encoder either clockwise or counterclockwise

one position will cause both switches to close.

The illustration below is representative of how the switch is constructed.


A rotary encoder has a fixed number of positions per revolution. These positions are easily felt as small “clicks” you turn the encoder. The KY-040 module has thirty of these positions. On one side of the switch there are three pins. They are normally referred to as A, B and C. In the case of the KY-040, they are oriented as shown. Inside the encoder there are two switches. Once switch connects pin A to pin C and the other switch connects pin B to C.

In each encoder position, both switches are either opened or closed. Each click causes these

switches to change states as follows:

  • If both switches are closed, turning the encoder either clockwise or counterclockwise

one position will cause both switches to open

  • If both switches are open, turning the encoder either clockwise or counterclockwise

one position will cause both switches to close.

The illustration below is representative of how the switch is constructed.

As you can see, the angular position of the A terminal and the B terminal is such that:

  • Rotating the switch clockwise will cause the switch connecting A and C to change states first.

  • Rotating the switch counterclockwise will cause the switch connecting B and C to change states first.

If we were to represent the opening and closing of the switches as wave forms, it would look something like this.

Essentially, determining which switch changed states first is how the direction of rotation is determined. If A changed states first, the switch is rotating in a clockwise direction. If B changed states first, the switch is rotating in a counter clockwise direction.


.


Wiring the Rotary Encoder

  • VCC of the rotary encoder to 3.3V (or 5V if the encoder supports it).

  • GND of the rotary encoder to GND on ESP32.

  • DT (Data) pin of rotary encoder to GPIO 34 on ESP32.

  • CLK (Clock) pin of rotary encoder to GPIO 35 on ESP32.

  • SW (Switch) pin of rotary encoder (optional for additional functionality) to GPIO 32 on ESP32.


Max7912 Serially Interfaced, 8-Digit LED Display Driver 


.Wiring the Max7912 Module

  • Max7912 Pinout:

  • VCC (Red) – Connect to 3.3V on the ESP32.

  • GND (Black) – Connect to GND on the ESP32.

  • DIN (Green) – Connect to a GPIO pin on the ESP32 GPIO 25.

  • CS (Blue) – Connect to a GPIO pin on the ESP32 GPIO 26.

  • CLK (Orange) – Connect to a GPIO pin on the ESP32 GPIO 27.


LED to ESP32:

  • Anode (long leg) of the LED to GPIO 27 on ESP32.

  • Cathode (short leg) of the LED through a 220 Ohm resistor to GND.



Install Required Libraries:

Make sure you have the following libraries installed in the Arduino IDE:


 Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries.


MAX7219_7Seg_Display for 7egment display driver.


After installed the libraries, restart your Arduino IDE.




Arduino Code

 

#include <MAX7219_7Seg_Disp.h>

/*DIN CS CLK*/

MAX7219_7Seg_Disp disp(25, 26, 27);


// Rotary Encoder Inputs

#define CLK 13

#define DT 14

#define SW 12


int currentStateCLK;

int lastStateCLK;

unsigned long lastButtonPress = 0;


int leds [] = {4, 0, 2, 15};


unsigned int menu = 0;

int ledStatus[5] = {0};

int timer = 1000;


void setup() {

Serial.begin(9600);

disp.Initialize(15); /*initialize MAX7219 & set brightness level-max 15*/

disp.Clear(); /*clear all 8 digits of display*/

// Set encoder pins as input

pinMode(CLK, INPUT);

pinMode(DT, INPUT);

pinMode(SW, INPUT_PULLUP);


for (int i = 0; i < 4; i++) {

pinMode(leds[i], OUTPUT);

}


menu = 0;

updateMenu();

}


void loop() {

currentStateCLK = digitalRead(CLK);


if (currentStateCLK != lastStateCLK && currentStateCLK == 1) {

if (digitalRead(DT) != currentStateCLK) {

menu --;

updateMenu();

} else {

menu ++;

updateMenu();

}

}

lastStateCLK = currentStateCLK;


int btnState = digitalRead(SW);

if (btnState == LOW) {

if (millis() - lastButtonPress > 50) {

executeAction();

updateMenu();

}

lastButtonPress = millis();

}

delay(1);

}


void MatrixSegment(){

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Char (5, ' ');

disp.Char (4, 'C');

disp.Char (3, 'N');

disp.Char (2, 'T');

disp.Char (1, 'L');

}


void updateMenu() {

switch (menu) {

case 0:

menu = 1;

break;


case 1:

MatrixSegment();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '1');

break;


case 2:

MatrixSegment();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '2');

break;

case 3:

MatrixSegment();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '3');

break;

case 4:

MatrixSegment();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '4');

break;

case 5:

menu = 4;

break;

}

}

void executeAction() {

switch (menu) {

case 1:

action1();

break;

case 2:

action2();

break;

case 3:

action3();

break;

case 4:

action4();

break;

}

}


void action1() {

if (ledStatus[menu] != 0) {

ledStatus[menu] = 0;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '1');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'F');

disp.Char (1, 'F');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

} else {

ledStatus[menu] = 1;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '2');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'N');

disp.Char (1, ' ');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

}

}

void action2() {

if (ledStatus[menu] != 0) {

ledStatus[menu] = 0;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '2');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'F');

disp.Char (1, 'F');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

} else {

ledStatus[menu] = 1;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '2');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'N');

disp.Char (1, ' ');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

}

}

void action3() {

if (ledStatus[menu] != 0) {

ledStatus[menu] = 0;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '3');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'F');

disp.Char (1, 'F');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

} else {

ledStatus[menu] = 1;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '3');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'N');

disp.Char (1, ' ');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

}

}

void action4() {

if (ledStatus[menu] != 0) {

ledStatus[menu] = 0;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '4');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'F');

disp.Char (1, 'F');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

} else {

ledStatus[menu] = 1;

disp.Clear();

disp.Char (8, 'L');

disp.Char (7, 'E');

disp.Char (6, 'D');

disp.Number (5, '4');

disp.Char (4, ' ');

disp.Char (3, 'O');

disp.Char (2, 'N');

disp.Char (1, ' ');

digitalWrite(leds[menu - 1], ledStatus[menu]);

delay(timer);

}

}


 

After a successful upload, open the Serial Monitor at a baud rate of 115200. Press the “EN/RST” button on the ESP32 board.


Explanation of the Code

  • Libraries: The Encoder library reads rotary encoder values, and the MAx7912 library communicates with the Max7912 display.

  • Pin Definitions: The pins for the rotary encoder and Max7912 are defined.

  • Setup: Initializes the display and sets initial values.

  • Loop: Reads the rotary encoder value and updates the LED and display based on changes.

  • Update Display: Shows the current value on the 7-segment display.


Testing

  1. Upload the code to the ESP32.

  2. Rotate the rotary encoder and observe the LED toggling on/off and the 7-segment display updating accordingly.


Troubleshooting

  • Ensure all connections are secure and correct.

  • Check if the libraries are correctly installed and included in the sketch.

  • Use Serial Monitor to debug and check encoder values if needed.

With this setup, you should be able to control an LED using a rotary encoder and display the state on a Max7912 8-digit 7-segment display using your ESP32.


Demo:

Comments


bottom of page