线性自抗扰(LADRC)的stm32f1程序,实现用编码器反馈控制直流电机调速,控制器采用加了TD的LADRC,控制效果良好,.h和.c分开,代码清晰有注释。 有调试说明

前言

在电机控制领域,如何实现精准的调速一直是个重要课题。线性自抗扰控制(LADRC)以其独特的优势,能有效应对系统的不确定性和干扰,在直流电机调速中表现出色。本文将分享基于STM32F1的LADRC实现直流电机调速,且采用加了TD(跟踪微分器)的LADRC,配合编码器反馈,实现良好的控制效果,同时代码以.h和.c文件分开编写,保证清晰且注释丰富。

整体架构

整个项目分为硬件和软件两大部分。硬件上,主要涉及STM32F1开发板、直流电机以及编码器。编码器用于实时反馈电机的转速信息,STM32F1通过读取编码器数据,运用LADRC算法计算出合适的控制量来驱动直流电机。

线性自抗扰(LADRC)的stm32f1程序,实现用编码器反馈控制直流电机调速,控制器采用加了TD的LADRC,控制效果良好,.h和.c分开,代码清晰有注释。 有调试说明

软件层面,核心代码以.h和.c文件分开编写,方便模块化管理和代码复用。

代码实现

1. 定义LADRC相关参数的头文件 `ladrc.h`

#ifndef _LADRC_H
#define _LADRC_H

// 定义结构体来存储LADRC的参数
typedef struct
{
    float b0;  // 控制增益
    float beta01;  // TD参数
    float beta02;  // TD参数
    float beta1;  // ESO参数
    float beta2;  // ESO参数
    float beta3;  // ESO参数
    float kp;  // 控制律参数
    float ki;  // 控制律参数
    float kd;  // 控制律参数
    float r;  // 跟踪微分器快速因子
    float h;  // 采样步长
    float h0;  // TD滤波因子
} LADRC_Parameters;

// 定义结构体来存储LADRC的状态
typedef struct
{
    float x1;  // TD状态1
    float x2;  // TD状态2
    float z1;  // ESO状态1
    float z2;  // ESO状态2
    float z3;  // ESO状态3
    float u0;  // 控制量
    float e1;  // 误差1
    float e2;  // 误差2
} LADRC_State;

// 初始化LADRC参数
void LADRC_Init(LADRC_Parameters *parameters, LADRC_State *state);

// 运行LADRC算法
float LADRC_Run(LADRC_Parameters *parameters, LADRC_State *state, float ref, float feedback);

#endif

在这个头文件里,我们定义了两个结构体,一个用来存放LADRC的各种参数,比如控制增益b0,跟踪微分器(TD)和扩张状态观测器(ESO)的参数等。另一个结构体则用来存储LADRC运行过程中的状态变量。同时还声明了初始化函数LADRCInit和运行函数LADRCRun

2. `ladrc.c`文件实现LADRC算法

#include "ladrc.h"
#include <math.h>

// 初始化LADRC参数
void LADRC_Init(LADRC_Parameters *parameters, LADRC_State *state)
{
    state->x1 = 0;
    state->x2 = 0;
    state->z1 = 0;
    state->z2 = 0;
    state->z3 = 0;
    state->u0 = 0;
    state->e1 = 0;
    state->e2 = 0;
}

// 运行LADRC算法
float LADRC_Run(LADRC_Parameters *parameters, LADRC_State *state, float ref, float feedback)
{
    // TD部分
    float fhan;
    float d = parameters->r * parameters->h0;
    float d0 = parameters->h0 * d;
    float y = state->x1 - ref;
    float a0 = parameters->h * state->x2;
    if (fabs(y) > d0)
    {
        fhan = -parameters->r * (y / fabs(y));
    }
    else
    {
        fhan = -parameters->r * y / d;
    }
    state->x1 = state->x1 + parameters->h * state->x2;
    state->x2 = state->x2 + parameters->h * fhan;

    // ESO部分
    state->e1 = state->z1 - feedback;
    state->z1 = state->z1 + parameters->h * (state->z2 - parameters->beta1 * state->e1);
    state->z2 = state->z2 + parameters->h * (state->z3 - parameters->beta2 * state->e1);
    state->z3 = state->z3 - parameters->h * parameters->beta3 * state->e1;

    // 控制律部分
    state->e2 = state->x1 - state->z1;
    state->u0 = state->kp * state->e2 + state->kd * (state->x2 - state->z2) + state->ki * state->e1;
    float u = (state->u0 - state->z3) / parameters->b0;

    return u;
}

ladrc.c文件中,LADRCInit函数对LADRC的状态变量进行初始化,将所有状态变量设为0 。LADRCRun函数实现了LADRC的核心算法流程。首先是跟踪微分器(TD)部分,通过fhan函数来安排过渡过程,根据误差y的大小调整输出,进而更新x1x2状态。然后是扩张状态观测器(ESO)部分,通过误差e1不断更新z1z2z3,对系统状态和干扰进行观测。最后在控制律部分,结合TD和ESO的输出计算出控制量u

3. 编码器读取及主控制代码 `main.c`

#include "stm32f10x.h"
#include "ladrc.h"

// 假设编码器引脚初始化函数
void Encoder_Init(void)
{
    // 配置定时器及相关引脚为输入捕获模式
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能定时器和GPIO时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    // 配置PA6和PA7为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 定时器基本配置
    TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 输入捕获配置
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x00;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    // 使能定时器
    TIM_Cmd(TIM3, ENABLE);
}

// 获取编码器计数值
int16_t Get_Encoder(void)
{
    return TIM3->CNT;
}

int main(void)
{
    LADRC_Parameters ladrc_params;
    LADRC_State ladrc_state;
    float ref_speed = 1000;  // 设定目标转速
    float feedback_speed;
    float control_value;

    Encoder_Init();
    // 初始化LADRC参数
    ladrc_params.b0 = 1;
    ladrc_params.beta01 = 100;
    ladrc_params.beta02 = 200;
    ladrc_params.beta1 = 100;
    ladrc_params.beta2 = 200;
    ladrc_params.beta3 = 1000;
    ladrc_params.kp = 1;
    ladrc_params.ki = 0.1;
    ladrc_params.kd = 0.01;
    ladrc_params.r = 100;
    ladrc_params.h = 0.001;
    ladrc_params.h0 = 0.001;

    LADRC_Init(&ladrc_params, &ladrc_state);

    while (1)
    {
        feedback_speed = Get_Encoder();  // 获取当前转速反馈
        control_value = LADRC_Run(&ladrc_params, &ladrc_state, ref_speed, feedback_speed);
        // 将控制值转换为PWM占空比,控制直流电机
        // 假设这里有个函数Set_PWM来设置PWM占空比
        Set_PWM(control_value);
    }
}

main.c文件中,首先定义了编码器初始化函数EncoderInit,配置定时器和相关引脚为输入捕获模式,用于读取编码器数据。GetEncoder函数则用于获取当前编码器的计数值,以此来表示电机的转速反馈。在main函数里,初始化LADRC参数和状态,设定目标转速refspeed。在循环中,不断读取编码器反馈的转速feedbackspeed,通过LADRCRun函数计算出控制量controlvalue,并将其转换为PWM占空比来控制直流电机。

调试说明

  1. 参数调整:LADRC算法效果对参数比较敏感。在调试初期,可以先使用默认参数运行,观察电机的转速响应。如果电机响应过慢或超调过大,可以适当调整TD和ESO的参数,如beta01beta02beta1beta2beta3等。kpkikd控制律参数也会影响控制效果,kp增大可加快响应速度,但可能导致超调;ki用于消除稳态误差,kd可抑制超调。
  2. 编码器信号检查:确保编码器安装正确,输出信号稳定。可以通过示波器观察编码器输出的A相和B相脉冲信号,检查其频率和相位关系是否正常。在程序中,可以在初始化后打印编码器的初始计数值,确认编码器是否正常工作。
  3. 电机驱动检查:检查电机驱动电路是否正常工作,确保PWM信号能够正确控制电机转速。可以通过调整PWM占空比,观察电机是否有相应的转速变化。

通过上述步骤和代码实现,基于STM32F1的加TD的LADRC直流电机调速系统能够实现良好的控制效果,在实际应用中可根据具体需求进一步优化和调整。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐