基于stm32采用PWM驱动伺服控制器学习笔记


     一、方案设计及选型阶段:

      采用伺服控制器来驱动电机转动是工控领域常用的控制方案,大部分是需要控制电机转动或设备行走到具体的位置,在选型之前,我们需要了解驱动控制的原理,如下:

      这里我们就需要生成PWM波形及输出DIR信号来控制伺服驱动器,推荐使用带FPU和定时器编码器接口的型号(如STM32F407,主打一个量大便宜),PWM采用高级定时器(TIM1/TIM8),支持互补输出和死区控制,用于驱动H桥。编码器反馈信号则可采用TIM2/TIM3/TIM4/TIM5,读取增量式编码器ABZ信号。


      二、PWM生成及私服驱动算法实现:

         PWM频率:通常为10-20kHz(避免可闻噪声,降低开关损耗):

      可采用cubemx工具进行TIM定时器初始化:

// PWM初始化代码片段(以TIM1通道1为例)
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 8399;  // 20kHz PWM
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim1);

TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;  // 初始占空比0%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

      伺服控制算法实现(基于位置-速度-电流三环控制):

      pid控制器代码如下:

typedef struct {
  float Kp, Ki, Kd;
  float integral;
  float prev_error;
} PID_Controller;

float PID_Update(PID_Controller* pid, float error, float dt) {
  float derivative = (error - pid->prev_error) / dt;
  pid->integral += error * dt;
  pid->prev_error = error;
  return pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative;
}

// 在定时中断中调用(如1kHz)
void TIMx_IRQHandler() {
  float position = Encoder_Read();  // 读取编码器
  float error = target_position - position;
  float speed_cmd = PID_Update(&pid_pos, error, 0.001f);
  
  float current_speed = (position - last_position) / 0.001f;
  float current_cmd = PID_Update(&pid_vel, speed_cmd - current_speed, 0.001f);
  
  PWM_SetDuty(current_cmd * MAX_DUTY);  // 输出PWM
  last_position = position;
}

      关键参数整定技巧:

      1.关于位置环:先调Kp至系统开始震荡,再设为临界值的60%。

      2.关于速度环:带宽设置为位置环的5-10倍。

      3.关于电流环:响应最快,一般由伺服控制器内部进行处理。


三、软硬件设计过程中需要注意抗干扰问题。

     1. PCB设计时需要注意电机电源与信号地分离,并进行单点接地,PWM信号线需要使用双绞线或者是屏蔽线。编码器信号输入需要做RC滤波(推荐100Ω+100pf)。

      2.软件设计方面,着重注意编码器的读数去噪,建议采用滑动均值滤波:

#define FILTER_SIZE 5
float filter_buf[FILTER_SIZE];
float Moving_Average(float new_val) {
  static int idx = 0;
  filter_buf[idx++] = new_val;
  if(idx >= FILTER_SIZE) idx = 0;
  float sum = 0;
  for(int i=0; i

四、实际调试过程中可能存在的问题:

1.电机啸叫,主要排查PWM频率是否合适,建议提高PWM频率至18khz以上。

2.定位精度较差,考虑原因为编码器分辨率不足,改用多圈绝对值编码器或细分处理。

3.高速时丢步,考虑中断时间过长,进行软件优化或提高MCU主频。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 3
关注 151
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧