Arduino, KY-040 Rotary Encoder and MAX7219 Interface

Introduction: Arduino, KY-040 Rotary Encoder and MAX7219 Interface


The Rotary encoder has fixed number of positions per revolution. Also it has press and release switch.

The rotation and switch press are felt by clicks, when we turn left, right or pressing the center switch.

In this project, a 16 turn KY-040 rotary encoder is used, as rotation sensor. The left turn, right turn and switch press are identified by the Arduino software, accordingly increment, decrement and reset to Zero of the integer will happen.

The integer values are displayed on the connected MAX7219 seven segment display, also prints via the serial port for further analysis.

Parts and components

Arduino Uno board = 1 No

KY-040 Rotary Encoder Module= 1 No

MAX7219 Seven Segment Display Module = 1 No

Step 1: Schematic

The rotary encoder, is an incremental electro-mechanical device that converts the angular position or motion of a shaft or axle to digital code.

It is a device that rotate infinitely. The rotary encoder can be used for speed, distance and position measurements.

It can also be used as control mechanism for audio, video and system parameters.

The end user can feel the small bumps, when he rotates left or right of the shaft.

The left or right rotation can be detected by the software accordingly process further.

The rotary encoder push button switch detection can be used for resetting the software parameters to initial state.

The STA, STB and SWITCH pins of rotary encoder is connected with 2,3 and 4 digital IO pins of Arduino.

The MAX7219 display module provides a 3-wire serial (SPI) interface to drive 7-segment LED displays (common-cathode type) up to 8 digits.

The on-chip includes a BCD decoder, multiplex scan circuitry, segment and digit drivers, and an 8×8 static RAM to store the digit values.

The DIN, LOAD and CLOCK pins of MAX7219 is connected with 7,5 and 6 digital IO pins of Arduino.

Step 2: Software

The Arduino LedControl library is used for displaying digits on MAX7219.

Left rotation of KY040 will trigger the interrupt, and interrupt routine will decrement the “rotation” variable by one count.

Right rotation of KY040 will trigger the interrupt, and interrupt routine will increment the “rotation” variable by one count.

Push button switch will reset the “rotation” variable to zero.

The “rotation”, will be displayed on MAX7219 and printed on serial port for every change in count.

Software, will increments or decrements the “rotation” variable between 0 to 9999.

The increment, decrement or rest value is send to the serial port and will be printed on the connected serial terminal.

//Demonstrates the use of MAX7219 and 2 of 4x7 Segment display

// The Arduino circuit connection for 7219: // MAX7219 DIN pin to digital pin 7 // MAX7219 LOAD pin to digital pin 5 // MAX7219 CLOCK pin to digital pin 6

// The Arduino circuit connection for KY040 Rotary encoder module // STA pin to digital pin 2 // STB pin to digital pin 3 // Switch pin to digital pin 4 // Name:- M.Pugazhendi // Date:- 18thAug2016 // Version:- V0.1 // e-mail:-

//Serial debug #define SERIAL_DEBUG

//Rotary encoder digital IO pins #define PinA 2 #define PinB 3 #define PinSW 4

//MAX7219 digital IO Pins #define DIN 7 #define CLOCK 6 #define LOAD 5

#include <LedControl.h>

// inputs: DIN pin, CLK pin, LOAD pin. number of chips LedControl mydisplay = LedControl(DIN,CLOCK,LOAD,1);

unsigned int count_two = 0; unsigned int rotation = 0; unsigned long time = 0; unsigned int num = 0;

void setup() { mydisplay.shutdown(0, false); // turns on display mydisplay.setIntensity(0, 15); // 15 = brightest mydisplay.setDigit(0, 0, 9, false); mydisplay.setDigit(0, 1, 8, false); mydisplay.setDigit(0, 2, 7, false); mydisplay.setDigit(0, 3, 6, false); mydisplay.setDigit(0, 4, 5, true); mydisplay.setDigit(0, 5, 4, false); mydisplay.setDigit(0, 6, 3, false); mydisplay.setDigit(0, 7, 2, false); #ifdef SERIAL_DEBUG Serial.begin(9600); Serial.print("Rotary Encoder Test"); #endif

pinMode(PinA,INPUT); pinMode(PinB,INPUT); pinMode(PinSW,INPUT);

attachInterrupt(0, blinkA, LOW); attachInterrupt(1, blinkB, LOW);

time = millis();

//2 Second delay delay(2000); }

void loop() {

while (num != rotation) { num = rotation; #ifdef SERIAL_DEBUG Serial.println(num); #endif } if(digitalRead(PinSW) == 0x00) { delay(10); rotation = 0x00; #ifdef SERIAL_DEBUG Serial.println("Switch Pressed"); #endif } //Clear display mydisplay.clearDisplay(0); count_two = HexToBCD(rotation); mydisplay.setDigit(0, 3, ((count_two>>12)&0x0F), false); mydisplay.setDigit(0, 2, ((count_two>>8)&0x0F), false); mydisplay.setDigit(0, 1, ((count_two>>4)&0x0F), false); mydisplay.setDigit(0, 0, ((count_two>>0)&0x0F), false);

//100mS delay delay(100); }

/**************************************************************************/ /*! * \brief Coverts hex into BCD * * This function will coverts hex into BCD * * \param[in] byte * \param[out] byte * \return Nill *
*/ /**************************************************************************/ unsigned int HexToBCD(unsigned int number) { unsigned char i=0; unsigned int k = 0;

while(number) { k = ( k ) | ((number%10) << i*4); number = number / 10; i++; }

return(k); }

//Interupt routine for incrementing the variable void blinkA() { if ((millis() - time) > 3) rotation++; if(rotation > 9999) { rotation = 0000; } time = millis(); }

//Interupt routine for decrementing the variable void blinkB() { if ((millis() - time) > 3) rotation--; if(rotation > 9999) { rotation = 9999; } time = millis(); }

Step 3: Conclusion

The project is successfully completed with Arduino UNO, KY-040 Rotary encoder and Max7219 Seven segment display module.

Detected rotation, and its incremented /decremented values on the serial port screen is given below.

Be the First to Share


    • Anything Goes Contest

      Anything Goes Contest



    26 days ago

    I had to change where it said "pinMode(PinSW,INPUT);" to pinMode(PinSW,INPUT_PULLUP);" because it treated the encoder button as continuously pressed even though I was never actually pressing it. But that was the only issue I ran into; everything else worked flawlessly. Thank you for posting this. :)


    Question 3 years ago

    Não funcionou dá erro no
    #ifdef SERIAL_DEBUG