Interface Servo motor with STM32

I have already covered a tutorial about Pulse Width Modulation in STM32 HERE and in this tutorial i am going to cover one of its applications. Today we will see how to control servo motor with STM32 by using PWM.

Servo motors use feedback to determine the position of the shaft, you can control that position very precisely. As a result, servo motors are used to control the position of objects, rotate objects, move legs, arms or hands of robots, move sensors etc. with high precision.

Most servo motors have the following three connections:

  • Black/Brown ground wire.
  • Red power wire (around 5V).
  • Yellow or White PWM wire.

HOW IT WORKS

Servos can go from 0 to 180 degrees depending on the width of the pulse. Basically you need to keep the pulse (+5v) high  for particular amount of time. Few are listed below:

  •  1 milliseconds and corresponds to 0 degrees
  • 1.5 milliseconds and corresponds to 90 degrees
  • 2 milliseconds and corresponds to 180 degrees

The period between two pulses must be 20ms or we can say the frequency of the pulse must be 50 Hz.

How to program

This is very important part because it involves messing up with the timers. I know it’s very hard to understand what is what when it comes to timers. So I am going to keep it simple here so that you guys can understand what’s going on.

I am going to use TIM2 of my STM32F446RE. TIM2 is connected to APB1 bus which gives me timer clock max upto 90 MHz. But the prescalar register is only 16 bit so max value I can write there is 65535. Keeping this in mind, I am going to set the clock such that my TIM2 gets only 45 MHz. my setup is below:

  • As I mentioned above that the frequency must be 50 Hz, it is time to divide the clock using prescalar and the ARR registers. Let’s do some calculations than–>  (45 MHz/50 Hz) = 900 KHz.
  • So now to get a  50 Hz of frequency, I have to divide this 900 KHz between Prescalar and ARR. So I am going to write 900 to prescalar Register and 1000 to ARR.
  • The reason behind this is this 1000 will also act as 1000% pulse width and if I want to change the pulse width to any other value, all I have to do is write X% to CCR1 register. This simplifies the things a lot.
  • For example, If I want to give a pulse width of 1 ms i.e. (1*1000/20) = 50%, I will write 50 instead of X in CCR1 register. For 2 ms, It will be 100%, and for 1.5 ms, It will be 75% and so on..
  • After testing it from 1 ms to 2ms, I found that the servo was not rotating the full 180 degrees as it should So I decided to take it a little further and tested it from 0.5 ms to 2.5 ms and It performed well.
  • So the code below is for 0.5 to 2.5 ms, However I commented out the section for 1 to 2 ms.


Some Insight Into the CODE

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

Will start the timer in PWM mode.


while (1)
  {
	  htim2.Instance->CCR1 = 25;  // duty cycle is .5 ms
	  HAL_Delay(2000);
	  htim2.Instance->CCR1 = 75;  // duty cycle is 1.5 ms
	  HAL_Delay(2000);
	  htim2.Instance->CCR1 = 125;  // duty cycle is 2.5 ms
	  HAL_Delay(2000);
  }
  • If you remember above, I chose the ARR value of 1000.
  • That means the CCR of 25 will be 2.5 % duty cycle. Also remember the cycle time for the pulse is 20ms.
  • Now 2.5% of 20ms = 0.5ms.
  • This 0.5ms will correspond to a rotation of 0 degrees.
  • Similarly CCR of 75 = 7.5% duty cycle = 7.5% of 20ms = 1.5ms HIGH Pulse. This will correspond to 90 degree rotation
  • And at last, a CCR of 125 = 12.5% duty cycle = 12.5% of 20ms = 2.5ms HIGH Pulse. This will correspond to 180 degree rotation


Result

duty cycle .5ms

1.5 ms duty cycle

2.5 ms duty cycle

Check out the Video Below








Info

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.

8 Comments. Leave new

  • (45 MHz/50 Hz) = 900 KHz. no… its 900k. No Hz.

    Reply
  • Hello,
    I want to control 2 servo motors. How can I do that? I opened 2 timer but it isnt work.

    Reply
  • why it doesnt happen when i make timer clock 90 MHz and double prescaler to 1800 -1 and keep arr 1000 -1

    Reply
  • Great post, I think people should learn a lot from this weblog it’s rattling user genial. So much great information on here.

    Reply
  • Hi Great WORK!

    Reply
  • Hi
    what a rich site!
    tnx a lot
    sorry I have a question:
    1)is there any usefull sources to learn Stm32 with cube and Hal library with its detail?
    I know them to some extent but I want to learn completely
    tnx a lot.

    Reply
    • I am not aware of any source. Just watch some videos, try yourself the basic stuff. And later build on those basic principals.
      Also there are some samples provided by ST, you can find them in the repository folder in your pc, where the cubemx is installed

      Reply

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.

keyboard_arrow_up

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 controllerstech.com to your ad blocking whitelist or disable your adblocking software.

×