STM32 control servo explanation, from entry to abandonment.

STM32 control servo


foreword

Here we take STM32F103C8T6 as our chip, and output PWM through the PB9 port to control the servo. Here we take the 180° SG90 steering gear.


1. PWM


What is PWM?

PWM, English name Pulse Width Modulation, is the abbreviation of Pulse Width Modulation. It modulates the width of a series of pulses to equivalently obtain the required waveform (including shape and amplitude), and digitally encodes the level of the analog signal. That is to say, the change of signal, energy, etc. is adjusted by adjusting the change of the duty cycle. The duty cycle refers to the percentage of the entire signal cycle when the signal is at a high level in a cycle. For example, the duty cycle of a square wave is 50%.

STM32 timers except TIM6 and 7. Other timers can be used to generate PWM outputs. Among them, the advanced timers TIM1 and TIM8 can generate up to 7 PWM outputs at the same time. The general-purpose timer can also generate up to 4 PWM outputs at the same time, so that the STM32 can generate up to 30 PWM outputs at the same time! Here we only use CH4 of TIM4 to generate one PWM output.

insert image description here
PWM frequency: refers to the number of times the signal goes from high level to low level and back to high level in 1 second (one cycle);
that is, how many cycles of PWM in one second

Unit: Hz

Representation: 50Hz 100Hz

Period of PWM:

T=1/f

period=1/frequency

50Hz = 20ms one cycle

If the frequency is 50Hz, that is to say, a cycle is 20ms, then there are 50 PWM cycles in one
second . The period is 20ms, so (taking the servo turning 45° as an example), the duty cycle should be 1ms/20ms = 5%, so the TIMx capture compare 1 register value of TIM_SetCompare1 is 200-200*5% = 190

Unit: % (0%-100%)

Representation: 20%

How to realize PWM signal output?

<1> The PWM signal can be output directly through the internal module of the chip. The premise is that this I/O port has an integrated module, which only needs a few simple steps. This kind of function module with PWM output is easier to program and design. At the same time the data is more accurate. As shown in the figure below, the general IC port will indicate whether this is a PWM port;

insert image description here

<2> But if there is no PWM function module inside the IC, or if the requirements are not very high, you can use the I/O port to set some parameters to output the PWM signal, because the PWM signal is actually a combination of a series of high and low levels. The specific method is to add a timer to the I/O. The frequency of the PWM signal you require to output is consistent with your timer, and the timer interrupt is used to count, but this method is generally not used, unless the requirements for accuracy, frequency, etc. are not Very high can be achieved.

Second, the steering gear


What is a steering gear?

Steering gears are also called RC servos, which are usually used in robotics projects, and they can also be found in RC cars, airplanes, and other aircraft models.
Servo systems like servos usually consist of small electric motors, potentiometers, embedded controls and gearboxes.
The position of the motor output shaft is continuously sampled and measured by the internal potentiometer, and compared with the target position set by the microcontroller (such as STM32, Arduino);
according to the corresponding deviation, the control device will adjust the actual position of the motor output shaft to make it match target location match. This forms a closed-loop control system.

insert image description here

Control principle

Control the output of the steering gear by sending a PWM signal to the signal line of the steering gear;

Generally speaking, we can control the period and duty cycle of PWM, so the duty cycle of the PWM pulse directly determines the position of the output shaft.

Here is an example;

When we send a signal with a pulse width of 1.5 milliseconds (ms) to the servo, the output shaft of the servo will move to the middle position (90 degrees);

When the pulse width is 1ms, the output shaft of the servo will move to the minimum position (0 degrees);

When the pulse width is 2ms, the output shaft of the servo will move to the minimum position (180 degrees);

Note: The angles of the maximum and minimum positions may vary between different types and brands of servo motors. Many servos only rotate about 170 degrees (or only 90 degrees), but a servo pulse with a width of 1.5 ms will usually set the servo to the middle position (usually half of the specified full range);

For details, please refer to the following figure;
insert image description here

Duty cycle = t / T The relevant parameters are as follows:

t = 0.5ms--------Servo turns to 0°
t = 1.0ms--------Servo turns to 45°
t = 1.5ms--------Servo turns to 90 °
t = 2.0ms —————- the servo turns to 135°
t = 2.5ms —————- the servo turns to 180°

Because: PWM period is 20ms = (7200*200)/72000000=0.02
So: TIM_Period = 199, TIM_Prescaler = 7199, which are my program entry parameters


Reference Code

Writing steps:

<1> Turn on TIM4, GPIOB clock, configure PB9 as multiplexed output.

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器 4 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE); //复用时钟使能

<2> Initialize TIM4, set ARR and PSC of TIM4.

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的

<3> Set the PWM mode of TIM4_CH4 and enable the CH4 output of TIM4.

void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)

Take a look at the definition of the structure TIM_OCInitTypeDef
:

typedef struct
{
    
    
	uint16_t TIM_OCMode;
	uint16_t TIM_OutputState;
	uint16_t TIM_OutputNState; 
	uint16_t TIM_Pulse;
	uint16_t TIM_OCPolarity;
	uint16_t TIM_OCNPolarity;
	uint16_t TIM_OCIdleState;
	uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;

Let's take a look at the parameters inside:

The parameter TIM_OCMode sets whether the mode is PWM or output comparison, here we are PWM mode.
The parameter TIM_OutputState is used to set the comparison output enable, that is, enable the PWM output to the port.
The parameter TIM_OCPolarity is used to set whether the polarity is high or low.
The other parameters TIM_OutputNState, TIM_OCNPolarity, TIM_OCIdleState and TIM_OCNIdleState are
only used by the advanced timers TIM1 and TIM8.

The configuration is as follows:

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC4Init(TIM4, &TIM_OCInitStructure); //初始化 TIM4 OC4

<4> Enable TIM4.

TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_Cmd(TIM4, ENABLE); //使能 TIM4

<5> Modify TIM4_CCR4 to control the duty cycle.

void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4)

Final code snippet:

//time.c
#include "time.h"
#include "stm32f10x.h"
#include "sys.h"

void TIM4_PWM_Init(u16 arr,u16 psc)
{
    
    
	GPIO_InitTypeDef GPIO_InitStrue;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

	GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStrue);
	
	TIM_TimeBaseStructure.TIM_Period = arr; 
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; 
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC4Init(TIM4,&TIM_OCInitStructure);
	
	TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
	TIM_Cmd(TIM4,ENABLE);
}



Here is the code of the main function:

//main.c
#include "stm32f10x.h"
#include "time.h"
#include "sys.h"
#include "usart.h"
#include "delay.h"

int main(void)
{
    
    
	delay_init();
	TIM4_PWM_Init(199,7199);
  while (1)
 {
    
    
	 
		delay_ms(10);
	 
		TIM_SetCompare4(TIM4,190);
	
 }
}

Guess you like

Origin blog.csdn.net/qq_42866708/article/details/113355329