Contents

Interfacing Photoelectric Encoder Speed Sensor with Arduino

Photoelectric Encoder Module Features

Motors are used in a wide variety of applications such as robotics, industry, research and educational projects. In most of these applications, it is necessary to calculate the rotation speed, the direction of rotation and the position of the motor shaft. Rotary encoder modules can be used for this purpose. Rotary encoder is a type of module that converts rotation into electrical signals. The rotary encoder has two output pins: A and B. If the rotary encoder is installed properly, with motor rotation, electrical signals will be generated on pins A and B. By monitoring these signals, the rotation speed, the direction of rotation and position of motor can be obtained.

How it works

The photoelectric encoder module consists of two discs located across each other. There is a light source on one disc and two light-receiving elements (photoresistors) on the other disc. Between these disks, there is a moving disc with evenly spaced slits. By rotating this moving disc, the light receivers A and B are alternately connected and disconnected. So, a square wave will be generated at the outputs. If you count these pulses, you can calculate the amount of rotation. In addition, there is a phase difference of 90 degrees between the two outputs A and B, so we can find the direction of rotation by checking which output is ahead of the other.

Photoelectric Encoder Module Pinout

This module has 4 wires:

  • output A (Yellow): Output A
  • output B (Blue): Output B
  • VCC (Red): Module power supply – 5V
  • GND (Black): Ground

You can see the pinout of this module here.

Required Materials

Hardware Components

Arduino UNO R3 × 1
Photoelectric Encoder Module × 1
Male to Female jumper wire × 1

Software Apps

Arduino IDE

Interfacing Photoelectric Encoder Module with Arduino

Step 1: Circuit

The following circuit shows how you should connect Arduino to this sensor. Connect wires accordingly.

Step 2: Code

Upload the following code to your Arduino. After that, open the Serial Monitor.

 /*
  Made on Jan 30, 2021
  By MehranMaleki @ Electropeak
  
Home
*/ #include "Timer.h" Timer t; #define number_of_holes 20 #define interruptPin 3 int i = 0; void setup() { pinMode(interruptPin, INPUT); attachInterrupt(digitalPinToInterrupt(interruptPin), counter, RISING); Serial.begin(9600); t.every(500, print_speed); } void loop() { t.update(); } void print_speed() { Serial.print("Speed: "); Serial.print(i * 120 / number_of_holes); Serial.println(" rpm"); i = 0; } void counter() { i++; }

In the above code, we have calculated the number of changes in the status of output A in one minute. Then, by dividing it by the number of the rotating disc holes, we can obtain the rotation speed and display it on the Serial Monitor.

The output is as follows:  

Liked What You See?​
Get Updates And Learn From The Best​

Comments (15)

  • azhar Reply

    in line 29, why we need to multiply with 120?

    June 15, 2021 at 11:58 pm
    • Mehran Maleki Reply

      Hi my friend,
      For better explanation, let me put it this way. The variable “i” is actually the number of times that the interrupt has happened at a specific period of time. And as you can see in the line 18, this specific period of time is 500 milliseconds. So, when we want to calculate the RPM (Round Per Minute) speed of the rotating disc, we need to multiply the variable “i” by 120 (1 min = 60 seconds = 500 milliseconds * 120).
      Hope that’s clear! Good luck.

      June 19, 2021 at 6:30 am
  • SARATHKUMAR R Reply

    still i am confusing of 120 ?? , that 500 is for delay i think, timer.h shows no matching files in arudino

    July 9, 2021 at 6:22 am
  • SARATHKUMAR R Reply

    if don’t need 500 ms to wait for rpm , so i put in loop , what i should replace instead of 120

    July 9, 2021 at 6:27 am
    • Mehran Maleki Reply

      Hi,
      You can see a full explanation of the code in the reply to the previous comment. That is related to the use of “120” and can help you get over your confusion.
      In overall, to calculate the RPM (Round Per Minute) of a rotating disc, you need to count the number of rotations (Round) in every 60 seconds (1 minute).
      In this code, we have counted the number of rotations in every 500 milliseconds, so, we need to multiply it by 120 to calculate the number of rotations in every 60 seconds.
      If, for any reason, you want to change 500 ms to X ms, you need to replace “120” with “60000 / X”.

      July 10, 2021 at 5:51 am
  • SARATHKUMAR R Reply

    thnkq for your work its working because of your explanation

    July 10, 2021 at 7:46 am
    • Mehran Maleki Reply

      You’re quite welcome! Glad it worked.

      July 11, 2021 at 7:20 am
      • SARATHKUMAR R Reply

        can we program it for see the motor rotation direction , when i use to interrupt it always show clockiwse direction even i rotation in anticlockwise,

        July 12, 2021 at 3:48 am
        • Mehran Maleki Reply

          Yes, that’s also possible. As stated in the article, all rotary encoders have 2 outputs: A & B. There is a phase difference of 90 degrees between these two outputs, so we can find the direction of rotation by checking which output is ahead of the other.
          Here in this tutorial, we have used only one of the outputs since one of them is enough for calculating the speed of rotation. To see how to use them both and figure out the direction, you can check the following tutorial:
          “https://electropeak.com/learn/rotary-encoder-how-it-works-how-to-use-with-arduino/”

          July 12, 2021 at 7:01 am
  • Kavish Ladha Reply

    there is an issue with the included library “TIMER”, the library actually is not recognised and if i use TimerOne, how am supposed to declare t? an answer would be very helpful

    October 17, 2021 at 9:18 am
    • Mehran Maleki Reply

      Hi,
      As long as I know, there is nothing wrong with the “Timer” library. What actually might have caused the problem is that you already have some other timer libraries installed on your Arduino IDE, and they’re causing conflicts with the “Timer” library, so it can’t work properly. One thing you could do is to delete any timer library you have and just install the “Timer” library of this article. That would solve your problem. But anyway, if you prefer to use the “TimerOne” library, you can take a look at its examples to see how you can use it. You can find its examples in Arduino IDE, File → Examples → TimerOne.

      October 18, 2021 at 4:59 am
  • Ray Brok Reply

    Hi Mehran,

    Maybe it’s possible to explain why you define 20 holes while the coded disk has 100 holes.
    There is a logic story behind it but it could make fiddling with this kind of sensors a whole lot easier.

    July 17, 2022 at 12:16 pm
    • Mehran Maleki Reply

      Hi,
      Sorry for the delay in response. Well, the disk I used while doing this project had 20 holes, so I defined holes to be 20. If you have a disk with a different number of holes, you can just change line 10 of the code accordingly.

      July 25, 2022 at 6:04 pm
  • zahra rostami Reply

    hi i will so thank full if you reply me i used this code for Optical encoder but i recieved this reaction speed 0 rpm

    November 21, 2023 at 3:44 pm
    • Mohammad Damirchi Reply

      Hi zahra,
      Your data will remain 0 until there is a movement on the shaft side or on the encoder.
      You can use this code to test your component.

      volatile long counter = 0;
      void A() {
      if (digitalRead(21) == LOW) {
      counter++;
      } else {
      counter--;
      }
      }

      void B() {
      if (digitalRead(20) == LOW) {
      counter--;
      } else {
      counter++;
      }
      }
      void setup()
      {
      Serial.begin(115200);
      pinMode(20, INPUT_PULLUP);
      pinMode(21, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(20), A, RISING);
      attachInterrupt(digitalPinToInterrupt(21), B, RISING);
      }
      void loop(){
      if ( counter != x ) {
      Serial.println (counter);
      x = counter;
      }
      }

      November 22, 2023 at 7:31 am

Leave a Reply

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