Incremental ENCODER and STM32

This tutorial will cover How to use Incremental Encoder with STM32. Also we will see how can we control the angle in Servo motor.

I have already covered the Servo motor earlier, and you can take a look at that article first,

As I have already mentioned in that article, even though the standard servo motors operate between 1ms to 2ms Pulse width, some motors (even mine) works between 0.5ms to 2.5ms. For 0.5ms, the angle of rotation remains 0, and for 2.5ms the angle changes to 180.

We will talk about servo in the later part of this tutorial, let’s see the ENCODER first.


You can use the TIMER in the ENCODER mode to interface the encoder. I have also added the speed feature (experimental). The code can be accessed at

Incremental ENCODER

An incremental encoder is a linear or rotary electromechanical device that has two output signals, A and B, which issue pulses when the device is moved. Together, the A and B signals indicate both the occurrence of and direction of movement.

Unlike an absolute encoder, an incremental encoder does not indicate absolute position. It only reports changes in position, and for each reported position change, the direction of movement.

In the above picture, the CLK and DT are the two output signals that I was talking about. These will be considered as the A and B signals from the Encoder. To explain it more clearly, below is the GIF from the Wikipedia page

source: Wikipedia

As you can see above, at some point both the signals are HIGH.

  • Now when we move the shaft in Clockwise Direction, the A goes to LOW and after some time, Pin B will go to LOW.
  • And when the shaft is moved in the CCK Direction, the Pin B will go LOW first and then Pin A.

This is our queue. We will be continuously checking for these pins, and based on which goes LOW first, we will make a decision about whether the movement was CK or CCK.

The picture above is the result of the CK movement. Here we can see that first the Pin A goes to LOW and later the pin B.

Similarly the picture below shows the CCK movement of the shaft

As expected during the CCK movement, the Pin B goes Low first, and then the pin A.

Some Insight into the code

 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_RESET)  // If OUTB is also reset... CCK
  while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_RESET){};  // wait for the OUTB to go high
  while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){};  // wait for the OUTA to go high
  HAL_Delay (10);  // wait for some more time

 else if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_SET)  // If OUTB is also set
  while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_SET){};  // wait for the OUTB to go LOW.. CK
  while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){};  // wait for the OUTA to go high
  while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_RESET){};  // wait for the OUTB to go high
  HAL_Delay (10);  // wait for some more time

 if (counter<0) counter = 0;
 if (counter>180) counter =180;
  • We will first check if the Pin A is low, and then check for Pin B
  • If the Pin A goes to LOW, and at that point if Pin B was already LOW, that means Pin B must have gone low before Pin A, and this would be a CCK movement.
  • We will decrease the counter here
  • If the Pin goes to LOW, and at that point if Pin B was HIGH, that means Pin A have gone LOW before Pin B, and this would be a CK movement.
  • We will increase the counter here.
  • I am limiting the counter between 0 to 180, so that it would be easier to deal with Servo motor.

Servo Motor

Now we will integrate the Encoder with the Servo Motor.

As I already mentioned before, the servo I have, works between 0.5ms to 2.5ms Pulse width. This means the servo covers the angle of 180 degrees in 2ms Pulse difference.

We can use this to calculate the pulse width required for each 1 degree increment in the angle. I have tried to explain it in the picture below

The Timer clock was originally running at 72 MHz, and in order to supply a pulse of 20ms Period, we need to bring this clock down to 50 Hz.

This can be done by using Prescalar along with ARR values.

Using the Prescalar of 144 and the ARR of 10000 will bring the timer clock to 50 Hz. 72000000/(144×10000) = 50.

Based on the counter value from the Encoder, we can rotate the servo by a definite angle.

PWMVal = counter*55/10;

htim1.Instance->CCR1 = 250 + PWMVal;
  • Here we will multiply the counter value (angle) by 5.5 (value for 1 degree rotation).
  • 250 is the CCR equivalent of 0.5ms. We need to add this with every value, because it’s the value for 0 degrees.
  • For example, if the angle is 90, the PWMVal will be approximately 500, and that will make the CCR = 750
  • This 750/10000 is same as 1.5/20.

Check the video to see it in action.


Check out the Video Below


You can help with the development by DONATING
To download the code, click DOWNLOAD button and view the Ad. The project will download after the Ad is finished.

Leave a Reply

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

Fill out this field
Fill out this field
Please enter a valid email address.


Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add to your ad blocking whitelist or disable your adblocking software.