BLDC电机无感FOC控制代码实例分享

BLDC电机无感FOC控制

    • 项目结构
    • [1. 主控文件 main.c](#1. 主控文件 main.c)
    • [2. FOC控制核心 foc_control.c](#2. FOC控制核心 foc_control.c)
    • [3. SVPWM生成模块 svpwm.c](#3. SVPWM生成模块 svpwm.c)
    • [4. 滑模观测器 observer.c](#4. 滑模观测器 observer.c)
    • [5. ADC采样处理 adc_handler.c](#5. ADC采样处理 adc_handler.c)
    • [6. PI控制器 pid_controller.c](#6. PI控制器 pid_controller.c)
    • [7. 安全保护模块 safety.c](#7. 安全保护模块 safety.c)
    • [8. 通信接口 uart_comm.c](#8. 通信接口 uart_comm.c)
    • [9. 头文件定义 foc_control.h](#9. 头文件定义 foc_control.h)
    • 关键特性说明
      • [1. **无传感器FOC算法**](#1. 无传感器FOC算法)
      • [2. **硬件优化**](#2. 硬件优化)
      • [3. **安全保护**](#3. 安全保护)
      • [4. **通信接口**](#4. 通信接口)
      • [5. **启动策略**](#5. 启动策略)
    • 使用说明
    • 注意事项

项目结构

复制代码
bldc_foc_controller/
├── Core/
│   ├── Src/
│   │   ├── main.c
│   │   ├── foc_control.c
│   │   ├── svpwm.c
│   │   ├── observer.c
│   │   ├── adc_handler.c
│   │   ├── pid_controller.c
│   │   └── safety.c
│   └── Inc/
│       ├── foc_control.h
│       ├── svpwm.h
│       ├── observer.h
│       ├── adc_handler.h
│       ├── pid_controller.h
│       └── safety.h

1. 主控文件 main.c

c 复制代码
/**
  * @file    main.c
  * @brief   BLDC无感FOC主控制器
  * @author  Motor Control Team
  */

#include "main.h"
#include "foc_control.h"
#include "adc_handler.h"
#include "safety.h"
#include "uart_comm.h"

/* 电机参数配置结构体 */
Motor_Params_t motor_params = {
    .pole_pairs = 7,           // 极对数
    .resistance = 0.05f,       // 相电阻 (Ω)
    .inductance = 0.0001f,     // 相电感 (H)
    .flux_linkage = 0.001f,    // 永磁体磁链 (Wb)
    .rated_current = 30.0f,    // 额定电流 (A)
    .rated_speed = 10000.0f,   // 额定转速 (RPM)
    .inertia = 0.0001f,        // 转动惯量 (kg·m²)
    .max_current = 50.0f,      // 最大电流 (A)
    .max_voltage = 24.0f       // 最大电压 (V)
};

/* FOC控制结构体 */
FOC_Handle_t hfoc;

/* 系统状态 */
System_State_t system_state = SYSTEM_IDLE;

int main(void)
{
    /* HAL库初始化 */
    HAL_Init();
    SystemClock_Config();
    
    /* 外设初始化 */
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_ADC2_Init();
    MX_ADC3_Init();
    MX_TIM1_Init();  // 高级定时器用于PWM
    MX_TIM2_Init();  // 用于速度计算
    MX_UART4_Init(); // 调试通信
    MX_CAN1_Init();  // CAN通信
    
    /* FOC系统初始化 */
    FOC_Init(&hfoc, &motor_params);
    
    /* ADC采样初始化 */
    ADC_Init();
    
    /* 安全保护初始化 */
    Safety_Init();
    
    /* 通信接口初始化 */
    UART_Comm_Init();
    CAN_Comm_Init();
    
    /* 启动ADC同步采样 */
    ADC_Start_DMA();
    
    /* 启动PWM输出 */
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
    
    /* 启动电机(三段式启动) */
    Motor_Start_Sequence(&hfoc);
    
    /* 主循环 */
    while (1)
    {
        /* 状态机处理 */
        switch (system_state)
        {
            case SYSTEM_IDLE:
                break;
                
            case SYSTEM_STARTUP:
                Motor_Startup_Handler(&hfoc);
                break;
                
            case SYSTEM_RUNNING:
                /* FOC控制循环 */
                FOC_Loop(&hfoc);
                
                /* 安全监测 */
                Safety_Monitor(&hfoc);
                
                /* 通信处理 */
                Comm_Handler();
                break;
                
            case SYSTEM_FAULT:
                Motor_Fault_Handler(&hfoc);
                break;
        }
        
        /* 系统节拍延时 */
        HAL_Delay(1);  // 1ms周期
    }
}

/**
  * @brief  TIM1 PWM初始化(中心对齐,互补带死区)
  */
void MX_TIM1_Init(void)
{
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;
    htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
    htim1.Init.Period = PWM_PERIOD;  // 例如: 4200-1 @ 170MHz = 20kHz
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&htim1);
    
    /* PWM通道配置 */
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);
    
    /* 死区时间配置 */
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = DEAD_TIME_NS;  // 例如: 500ns
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
    HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
    
    /* 主从模式配置 */
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
}

2. FOC控制核心 foc_control.c

c 复制代码
/**
  * @file    foc_control.c
  * @brief   FOC核心算法实现
  */

#include "foc_control.h"
#include "math.h"

/* 全局变量 */
static FOC_Handle_t* pFOC;
static PID_Handle_t pid_id, pid_iq, pid_speed;

/**
  * @brief  FOC系统初始化
  */
void FOC_Init(FOC_Handle_t* hfoc, Motor_Params_t* motor)
{
    pFOC = hfoc;
    
    /* 初始化结构体 */
    memset(hfoc, 0, sizeof(FOC_Handle_t));
    hfoc->motor = motor;
    
    /* 初始化角度和速度 */
    hfoc->theta_elec = 0.0f;
    hfoc->theta_mech = 0.0f;
    hfoc->speed_elec = 0.0f;
    hfoc->speed_mech = 0.0f;
    
    /* 初始化电流 */
    hfoc->I_alpha = 0.0f;
    hfoc->I_beta = 0.0f;
    hfoc->I_d = 0.0f;
    hfoc->I_q = 0.0f;
    
    /* 初始化电压 */
    hfoc->V_alpha = 0.0f;
    hfoc->V_beta = 0.0f;
    hfoc->V_d = 0.0f;
    hfoc->V_q = 0.0f;
    
    /* 初始化PI控制器 */
    PID_Init(&pid_id, 1.0f, 0.1f, 0.0f, 10.0f);    // d轴电流环
    PID_Init(&pid_iq, 1.0f, 0.1f, 0.0f, 10.0f);    // q轴电流环
    PID_Init(&pid_speed, 0.5f, 0.05f, 0.001f, 1000.0f); // 速度环
    
    /* 设置目标值 */
    hfoc->target_id = 0.0f;
    hfoc->target_iq = 0.0f;
    hfoc->target_speed = 0.0f;
    
    /* 初始化启动状态 */
    hfoc->startup_state = STARTUP_STAGE1;
    hfoc->startup_timer = 0;
}

/**
  * @brief  FOC主控制循环
  */
void FOC_Loop(FOC_Handle_t* hfoc)
{
    /* 1. 获取电流采样值 */
    ADC_Get_Currents(&hfoc->I_u, &hfoc->I_v, &hfoc->I_w);
    
    /* 2. Clark变换 (3相->2相) */
    Clarke_Transform(hfoc->I_u, hfoc->I_v, hfoc->I_w, 
                     &hfoc->I_alpha, &hfoc->I_beta);
    
    /* 3. 位置估算(滑模观测器) */
    SMO_Estimate(&hfoc->I_alpha, &hfoc->I_beta,
                 &hfoc->V_alpha, &hfoc->V_beta,
                 &hfoc->theta_elec, &hfoc->speed_elec);
    
    /* 4. Park变换 (静止->旋转) */
    Park_Transform(hfoc->I_alpha, hfoc->I_beta, hfoc->theta_elec,
                   &hfoc->I_d, &hfoc->I_q);
    
    /* 5. 速度环PI控制 */
    hfoc->speed_mech = hfoc->speed_elec / hfoc->motor->pole_pairs;
    hfoc->target_iq = PID_Calculate(&pid_speed, 
                                    hfoc->target_speed, 
                                    hfoc->speed_mech);
    
    /* 6. 电流环PI控制 */
    hfoc->V_d = PID_Calculate(&pid_id, hfoc->target_id, hfoc->I_d);
    hfoc->V_q = PID_Calculate(&pid_iq, hfoc->target_iq, hfoc->I_q);
    
    /* 7. 反Park变换 (旋转->静止) */
    Inverse_Park_Transform(hfoc->V_d, hfoc->V_q, hfoc->theta_elec,
                           &hfoc->V_alpha, &hfoc->V_beta);
    
    /* 8. SVPWM生成 */
    SVPWM_Generate(hfoc->V_alpha, hfoc->V_beta, 
                   hfoc->dc_bus_voltage,
                   &hfoc->PWM_A, &hfoc->PWM_B, &hfoc->PWM_C);
    
    /* 9. 更新PWM占空比 */
    TIM1->CCR1 = hfoc->PWM_A;
    TIM1->CCR2 = hfoc->PWM_B;
    TIM1->CCR3 = hfoc->PWM_C;
}

/**
  * @brief  Clark变换
  */
void Clarke_Transform(float Iu, float Iv, float Iw, 
                      float* Ialpha, float* Ibeta)
{
    /* Clarke变换矩阵:
     * I_alpha = Iu
     * I_beta = (Iu + 2*Iv)/√3
     */
    *Ialpha = Iu;
    *Ibeta = (Iu + 2.0f * Iv) * ONE_BY_SQRT3;
}

/**
  * @brief  Park变换
  */
void Park_Transform(float Ialpha, float Ibeta, float theta,
                    float* Id, float* Iq)
{
    float sin_theta, cos_theta;
    
    /* 计算sin/cos值 */
    sin_theta = arm_sin_f32(theta);
    cos_theta = arm_cos_f32(theta);
    
    /* Park变换:
     * I_d =  I_alpha * cosθ + I_beta * sinθ
     * I_q = -I_alpha * sinθ + I_beta * cosθ
     */
    *Id = Ialpha * cos_theta + Ibeta * sin_theta;
    *Iq = -Ialpha * sin_theta + Ibeta * cos_theta;
}

/**
  * @brief  反Park变换
  */
void Inverse_Park_Transform(float Vd, float Vq, float theta,
                            float* Valpha, float* Vbeta)
{
    float sin_theta, cos_theta;
    
    sin_theta = arm_sin_f32(theta);
    cos_theta = arm_cos_f32(theta);
    
    /* 反Park变换:
     * V_alpha = V_d * cosθ - V_q * sinθ
     * V_beta  = V_d * sinθ + V_q * cosθ
     */
    *Valpha = Vd * cos_theta - Vq * sin_theta;
    *Vbeta = Vd * sin_theta + Vq * cos_theta;
}

/**
  * @brief  三段式启动策略
  */
void Motor_Start_Sequence(FOC_Handle_t* hfoc)
{
    hfoc->startup_state = STARTUP_STAGE1;
    hfoc->startup_timer = 0;
    system_state = SYSTEM_STARTUP;
}

/**
  * @brief  启动状态机处理
  */
void Motor_Startup_Handler(FOC_Handle_t* hfoc)
{
    static float startup_angle = 0.0f;
    static float startup_freq = 1.0f;  // 起始频率
    
    switch (hfoc->startup_state)
    {
        case STARTUP_STAGE1:  // 转子预定位
            /* 固定角度,通入小电流 */
            hfoc->target_id = 0.0f;
            hfoc->target_iq = 2.0f;  // 2A定位电流
            hfoc->theta_elec = 0.0f;  // 固定0度
            
            if (hfoc->startup_timer > 100)  // 100ms预定位
            {
                hfoc->startup_state = STARTUP_STAGE2;
                hfoc->startup_timer = 0;
            }
            break;
            
        case STARTUP_STAGE2:  // 开环加速
            /* 递增角度和频率 */
            startup_freq += 0.1f;  // 频率递增
            startup_angle += startup_freq * 0.001f * 2 * PI;  // 积分得到角度
            
            /* 限幅 */
            if (startup_freq > 10.0f)  // 加速到10Hz
            {
                hfoc->startup_state = STARTUP_STAGE3;
                hfoc->startup_timer = 0;
            }
            
            /* 开环控制 */
            hfoc->theta_elec = startup_angle;
            hfoc->target_iq = 5.0f;  // 5A加速电流
            break;
            
        case STARTUP_STAGE3:  // 切闭环
            /* 切换到观测器估算的角度 */
            SMO_Estimate(&hfoc->I_alpha, &hfoc->I_beta,
                        &hfoc->V_alpha, &hfoc->V_beta,
                        &hfoc->theta_elec, &hfoc->speed_elec);
            
            /* 检查观测器是否收敛 */
            if (fabs(hfoc->speed_elec) > 1.0f && 
                hfoc->startup_timer > 50)
            {
                /* 成功切入闭环 */
                hfoc->startup_state = STARTUP_COMPLETE;
                system_state = SYSTEM_RUNNING;
            }
            break;
            
        case STARTUP_COMPLETE:
            /* 启动完成,进入正常运行 */
            break;
    }
    
    hfoc->startup_timer++;
}

3. SVPWM生成模块 svpwm.c

c 复制代码
/**
  * @file    svpwm.c
  * @brief   SVPWM空间矢量脉宽调制
  */

#include "svpwm.h"
#include "math.h"

/**
  * @brief  SVPWM生成
  */
void SVPWM_Generate(float Valpha, float Vbeta, float Vdc,
                    uint32_t* PWM_A, uint32_t* PWM_B, uint32_t* PWM_C)
{
    float Vref, angle, T1, T2, Ta, Tb, Tc;
    uint8_t sector;
    float Vmax, Vmin, Vmid;
    
    /* 1. 计算参考电压矢量幅值和角度 */
    Vref = sqrtf(Valpha * Valpha + Vbeta * Vbeta);
    angle = atan2f(Vbeta, Valpha);
    
    /* 2. 过调制处理 */
    if (Vref > Vdc * ONE_BY_SQRT3)
        Vref = Vdc * ONE_BY_SQRT3;
    
    /* 3. 判断扇区 */
    sector = SVPWM_Get_Sector(Valpha, Vbeta);
    
    /* 4. 计算基本矢量作用时间 */
    SVPWM_Calc_Times(sector, angle, Vref, Vdc, &T1, &T2);
    
    /* 5. 计算PWM占空比 */
    SVPWM_Calc_Duty(sector, T1, T2, &Ta, &Tb, &Tc);
    
    /* 6. 转换为定时器比较值 */
    *PWM_A = (uint32_t)(Ta * PWM_PERIOD);
    *PWM_B = (uint32_t)(Tb * PWM_PERIOD);
    *PWM_C = (uint32_t)(Tc * PWM_PERIOD);
}

/**
  * @brief  判断扇区
  */
uint8_t SVPWM_Get_Sector(float Valpha, float Vbeta)
{
    float V1, V2, V3;
    uint8_t sector = 0;
    
    /* 计算三个参考电压 */
    V1 = Vbeta;
    V2 = -0.5f * Vbeta + SQRT3_BY_2 * Valpha;
    V3 = -0.5f * Vbeta - SQRT3_BY_2 * Valpha;
    
    /* 判断扇区 */
    if (V1 > 0) sector |= 0x01;
    if (V2 > 0) sector |= 0x02;
    if (V3 > 0) sector |= 0x04;
    
    /* 映射到1-6扇区 */
    static const uint8_t sector_map[8] = {0, 2, 6, 1, 4, 3, 5, 0};
    return sector_map[sector];
}

/**
  * @brief  计算矢量作用时间
  */
void SVPWM_Calc_Times(uint8_t sector, float angle, float Vref, 
                      float Vdc, float* T1, float* T2)
{
    float alpha, beta;
    float X, Y, Z;
    
    /* 计算中间变量 */
    alpha = Vref * sinf(PI/3 - angle);
    beta = Vref * sinf(angle);
    X = SQRT3 * alpha / Vdc;
    Y = SQRT3 * beta / Vdc;
    Z = X + Y;
    
    switch (sector)
    {
        case 1:
            *T1 = Z;
            *T2 = Y;
            break;
        case 2:
            *T1 = Y;
            *T2 = -X;
            break;
        case 3:
            *T1 = -Z;
            *T2 = X;
            break;
        case 4:
            *T1 = -X;
            *T2 = Z;
            break;
        case 5:
            *T1 = X;
            *T2 = -Y;
            break;
        case 6:
            *T1 = -Y;
            *T2 = -Z;
            break;
        default:
            *T1 = 0;
            *T2 = 0;
            break;
    }
    
    /* 归一化到PWM周期 */
    *T1 = (*T1) * PWM_PERIOD / 2;
    *T2 = (*T2) * PWM_PERIOD / 2;
}

4. 滑模观测器 observer.c

c 复制代码
/**
  * @file    observer.c
  * @brief   滑模观测器位置估算
  */

#include "observer.h"
#include "math.h"

/* 观测器参数 */
static SMO_Params_t smo_params = {
    .gain = 100.0f,
    .filter_coeff = 0.01f,
    .emf_alpha = 0.0f,
    .emf_beta = 0.0f,
    .z_alpha = 0.0f,
    .z_beta = 0.0f,
    .err_alpha = 0.0f,
    .err_beta = 0.0f
};

/**
  * @brief  滑模观测器估算
  */
void SMO_Estimate(float* I_alpha, float* I_beta,
                  float* V_alpha, float* V_beta,
                  float* theta, float* speed)
{
    static float I_alpha_hat = 0.0f, I_beta_hat = 0.0f;
    float dt = 0.0001f;  // 100us控制周期
    float Rs = 0.05f, Ls = 0.0001f;
    float emf_alpha, emf_beta;
    float sign_alpha, sign_beta;
    
    /* 1. 计算电流误差 */
    smo_params.err_alpha = I_alpha_hat - *I_alpha;
    smo_params.err_beta = I_beta_hat - *I_beta;
    
    /* 2. 滑模控制函数(sign函数) */
    sign_alpha = (smo_params.err_alpha > 0) ? 1.0f : -1.0f;
    sign_beta = (smo_params.err_beta > 0) ? 1.0f : -1.0f;
    
    /* 3. 估算反电动势 */
    smo_params.emf_alpha = smo_params.gain * sign_alpha;
    smo_params.emf_beta = smo_params.gain * sign_beta;
    
    /* 4. 电流观测器模型 */
    I_alpha_hat += dt * (1/Ls) * (*V_alpha - Rs * I_alpha_hat - smo_params.emf_alpha);
    I_beta_hat += dt * (1/Ls) * (*V_beta - Rs * I_beta_hat - smo_params.emf_beta);
    
    /* 5. 低通滤波器 */
    smo_params.emf_alpha = smo_params.filter_coeff * smo_params.emf_alpha + 
                          (1 - smo_params.filter_coeff) * smo_params.z_alpha;
    smo_params.emf_beta = smo_params.filter_coeff * smo_params.emf_beta + 
                         (1 - smo_params.filter_coeff) * smo_params.z_beta;
    
    smo_params.z_alpha = smo_params.emf_alpha;
    smo_params.z_beta = smo_params.emf_beta;
    
    /* 6. 估算角度和速度 */
    *theta = atan2f(-smo_params.emf_alpha, smo_params.emf_beta);
    
    /* 7. 速度估算(角度差分) */
    static float theta_prev = 0.0f;
    float delta_theta = *theta - theta_prev;
    
    /* 角度补偿 */
    if (delta_theta > PI) delta_theta -= 2 * PI;
    if (delta_theta < -PI) delta_theta += 2 * PI;
    
    *speed = delta_theta / dt;
    theta_prev = *theta;
}

5. ADC采样处理 adc_handler.c

c 复制代码
/**
  * @file    adc_handler.c
  * @brief   ADC同步采样处理
  */

#include "adc_handler.h"

/* ADC采样缓冲 */
volatile uint16_t adc_buffer[ADC_CHANNELS * ADC_SAMPLES];
volatile float phase_currents[3] = {0};

/**
  * @brief  ADC初始化(三路同步采样)
  */
void ADC_Init(void)
{
    ADC_HandleTypeDef hadc1, hadc2, hadc3;
    ADC_MultiModeTypeDef multimode;
    
    /* ADC1配置(通道1) */
    hadc1.Instance = ADC1;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc1.Init.DMAContinuousRequests = ENABLE;
    hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    HAL_ADC_Init(&hadc1);
    
    /* ADC2配置(通道2) */
    hadc2.Instance = ADC2;
    hadc2.Init.Resolution = ADC_RESOLUTION_12B;
    hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc2.Init.ContinuousConvMode = ENABLE;
    hadc2.Init.DiscontinuousConvMode = DISABLE;
    hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO;
    hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc2.Init.DMAContinuousRequests = ENABLE;
    hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    HAL_ADC_Init(&hadc2);
    
    /* ADC3配置(通道3) */
    hadc3.Instance = ADC3;
    hadc3.Init.Resolution = ADC_RESOLUTION_12B;
    hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc3.Init.ContinuousConvMode = ENABLE;
    hadc3.Init.DiscontinuousConvMode = DISABLE;
    hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO;
    hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc3.Init.DMAContinuousRequests = ENABLE;
    hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    HAL_ADC_Init(&hadc3);
    
    /* 多ADC模式配置 */
    multimode.Mode = ADC_TRIPLEMODE_REGSIMULT;
    multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
    multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
    HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);
    
    /* 配置采样通道 */
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_2;
    HAL_ADC_ConfigChannel(&hadc2, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_3;
    HAL_ADC_ConfigChannel(&hadc3, &sConfig);
}

/**
  * @brief  启动ADC DMA采样
  */
void ADC_Start_DMA(void)
{
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 
                      ADC_CHANNELS * ADC_SAMPLES);
}

/**
  * @brief  获取三相电流值
  */
void ADC_Get_Currents(float* Iu, float* Iv, float* Iw)
{
    static uint32_t sample_count = 0;
    float offset_u = CURRENT_OFFSET_U;
    float offset_v = CURRENT_OFFSET_V;
    float offset_w = CURRENT_OFFSET_W;
    
    /* 读取最新采样值 */
    uint16_t adc_val_u = adc_buffer[sample_count * ADC_CHANNELS];
    uint16_t adc_val_v = adc_buffer[sample_count * ADC_CHANNELS + 1];
    uint16_t adc_val_w = adc_buffer[sample_count * ADC_CHANNELS + 2];
    
    /* ADC值转换为电流值 */
    *Iu = ((float)adc_val_u * ADC_TO_VOLTAGE - offset_u) / CURRENT_SENSE_GAIN;
    *Iv = ((float)adc_val_v * ADC_TO_VOLTAGE - offset_v) / CURRENT_SENSE_GAIN;
    *Iw = ((float)adc_val_w * ADC_TO_VOLTAGE - offset_w) / CURRENT_SENSE_GAIN;
    
    /* 更新采样计数 */
    sample_count = (sample_count + 1) % ADC_SAMPLES;
}

6. PI控制器 pid_controller.c

c 复制代码
/**
  * @file    pid_controller.c
  * @brief   PI控制器实现
  */

#include "pid_controller.h"

/**
  * @brief  PI控制器初始化
  */
void PID_Init(PID_Handle_t* pid, float Kp, float Ki, float Kd, float limit)
{
    pid->Kp = Kp;
    pid->Ki = Ki;
    pid->Kd = Kd;
    pid->integral = 0.0f;
    pid->prev_error = 0.0f;
    pid->output_limit = limit;
    pid->integral_limit = limit * 0.5f;
}

/**
  * @brief  PI控制器计算
  */
float PID_Calculate(PID_Handle_t* pid, float target, float feedback)
{
    float error, derivative, output;
    
    /* 计算误差 */
    error = target - feedback;
    
    /* 比例项 */
    output = pid->Kp * error;
    
    /* 积分项 */
    pid->integral += pid->Ki * error;
    
    /* 积分限幅 */
    if (pid->integral > pid->integral_limit)
        pid->integral = pid->integral_limit;
    else if (pid->integral < -pid->integral_limit)
        pid->integral = -pid->integral_limit;
    
    output += pid->integral;
    
    /* 微分项 */
    derivative = pid->Kd * (error - pid->prev_error);
    output += derivative;
    pid->prev_error = error;
    
    /* 输出限幅 */
    if (output > pid->output_limit)
        output = pid->output_limit;
    else if (output < -pid->output_limit)
        output = -pid->output_limit;
    
    return output;
}

/**
  * @brief  重置PI控制器
  */
void PID_Reset(PID_Handle_t* pid)
{
    pid->integral = 0.0f;
    pid->prev_error = 0.0f;
}

7. 安全保护模块 safety.c

c 复制代码
/**
  * @file    safety.c
  * @brief   安全保护功能
  */

#include "safety.h"

/* 故障标志 */
static uint32_t fault_flags = 0;

/**
  * @brief  安全监测
  */
void Safety_Monitor(FOC_Handle_t* hfoc)
{
    /* 过流保护 */
    if (fabs(hfoc->I_q) > hfoc->motor->max_current)
    {
        fault_flags |= FAULT_OVER_CURRENT;
    }
    
    /* 过压保护 */
    if (hfoc->dc_bus_voltage > hfoc->motor->max_voltage)
    {
        fault_flags |= FAULT_OVER_VOLTAGE;
    }
    
    /* 欠压保护 */
    if (hfoc->dc_bus_voltage < UNDERVOLTAGE_THRESHOLD)
    {
        fault_flags |= FAULT_UNDER_VOLTAGE;
    }
    
    /* 过温保护 */
    if (Read_Temperature() > TEMPERATURE_LIMIT)
    {
        fault_flags |= FAULT_OVER_TEMP;
    }
    
    /* 位置估算异常 */
    if (hfoc->speed_elec > MAX_SPEED)
    {
        fault_flags |= FAULT_SPEED_SENSOR;
    }
    
    /* 如果有故障,执行保护动作 */
    if (fault_flags != 0)
    {
        Safety_Shutdown(hfoc);
    }
}

/**
  * @brief  安全停机
  */
void Safety_Shutdown(FOC_Handle_t* hfoc)
{
    /* 关闭PWM输出 */
    TIM1->CCR1 = 0;
    TIM1->CCR2 = 0;
    TIM1->CCR3 = 0;
    
    /* 设置故障状态 */
    system_state = SYSTEM_FAULT;
    
    /* 保存故障信息 */
    Save_Fault_Info(fault_flags);
    
    /* 触发故障指示灯 */
    HAL_GPIO_WritePin(LED_FAULT_GPIO_Port, LED_FAULT_Pin, GPIO_PIN_SET);
}

8. 通信接口 uart_comm.c

c 复制代码
/**
  * @file    uart_comm.c
  * @brief   上位机通信接口
  */

#include "uart_comm.h"

/* 通信协议定义 */
typedef struct {
    uint8_t header[2];
    uint8_t cmd;
    uint8_t length;
    uint8_t data[64];
    uint8_t checksum;
} Comm_Packet_t;

/**
  * @brief  UART通信处理
  */
void UART_Comm_Handler(void)
{
    static uint8_t rx_buffer[128];
    static uint8_t rx_index = 0;
    
    /* 接收数据 */
    if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_RXNE))
    {
        rx_buffer[rx_index++] = huart4.Instance->RDR;
        
        /* 检测数据包结束 */
        if (rx_index >= sizeof(Comm_Packet_t))
        {
            Process_Command(rx_buffer);
            rx_index = 0;
        }
    }
}

/**
  * @brief  处理上位机命令
  */
void Process_Command(uint8_t* buffer)
{
    Comm_Packet_t* packet = (Comm_Packet_t*)buffer;
    
    switch (packet->cmd)
    {
        case CMD_SET_SPEED:
            /* 设置目标速度 */
            memcpy(&hfoc.target_speed, packet->data, 4);
            break;
            
        case CMD_SET_CURRENT:
            /* 设置电流限制 */
            memcpy(&motor_params.max_current, packet->data, 4);
            break;
            
        case CMD_GET_STATUS:
            /* 发送系统状态 */
            Send_System_Status();
            break;
            
        case CMD_SAVE_PARAMS:
            /* 保存参数到Flash */
            Save_Params_To_Flash();
            break;
            
        case CMD_RESET:
            /* 系统复位 */
            NVIC_SystemReset();
            break;
    }
}

/**
  * @brief  发送系统状态
  */
void Send_System_Status(void)
{
    uint8_t tx_buffer[128];
    Status_Packet_t status;
    
    /* 填充状态数据 */
    status.speed = hfoc.speed_mech;
    status.current_iq = hfoc.I_q;
    status.current_id = hfoc.I_d;
    status.voltage = hfoc.dc_bus_voltage;
    status.temperature = Read_Temperature();
    status.fault_flags = fault_flags;
    
    /* 发送数据 */
    memcpy(tx_buffer, &status, sizeof(status));
    HAL_UART_Transmit(&huart4, tx_buffer, sizeof(status), 100);
}

9. 头文件定义 foc_control.h

c 复制代码
/**
  * @file    foc_control.h
  * @brief   FOC控制头文件
  */

#ifndef __FOC_CONTROL_H
#define __FOC_CONTROL_H

#include <stdint.h>
#include <stdbool.h>

/* 数学常量 */
#define PI                      3.14159265358979f
#define TWO_PI                  6.28318530717959f
#define SQRT3                   1.73205080756888f
#define ONE_BY_SQRT3            0.57735026918963f
#define SQRT3_BY_2              0.86602540378444f

/* 系统参数 */
#define PWM_FREQUENCY           20000   // 20kHz
#define PWM_PERIOD              4200    // 170MHz/20kHz
#define DEAD_TIME_NS            500     // 死区时间500ns
#define CONTROL_FREQ            10000   // 10kHz控制频率

/* 电机启动状态 */
typedef enum {
    STARTUP_STAGE1,     // 预定位
    STARTUP_STAGE2,     // 开环加速
    STARTUP_STAGE3,     // 切闭环
    STARTUP_COMPLETE    // 启动完成
} Startup_State_t;

/* 系统状态 */
typedef enum {
    SYSTEM_IDLE,
    SYSTEM_STARTUP,
    SYSTEM_RUNNING,
    SYSTEM_FAULT
} System_State_t;

/* 故障标志 */
typedef enum {
    FAULT_NONE = 0,
    FAULT_OVER_CURRENT = 0x01,
    FAULT_OVER_VOLTAGE = 0x02,
    FAULT_UNDER_VOLTAGE = 0x04,
    FAULT_OVER_TEMP = 0x08,
    FAULT_SPEED_SENSOR = 0x10
} Fault_Flags_t;

/* 电机参数结构体 */
typedef struct {
    uint8_t pole_pairs;         // 极对数
    float resistance;           // 相电阻 (Ω)
    float inductance;           // 相电感 (H)
    float flux_linkage;         // 永磁体磁链 (Wb)
    float rated_current;        // 额定电流 (A)
    float rated_speed;          // 额定转速 (RPM)
    float inertia;              // 转动惯量 (kg·m²)
    float max_current;          // 最大电流 (A)
    float max_voltage;          // 最大电压 (V)
} Motor_Params_t;

/* FOC控制句柄 */
typedef struct {
    /* 电机参数 */
    Motor_Params_t* motor;
    
    /* 电流采样值 */
    float I_u, I_v, I_w;
    float I_alpha, I_beta;
    float I_d, I_q;
    
    /* 电压值 */
    float V_alpha, V_beta;
    float V_d, V_q;
    
    /* 位置和速度 */
    float theta_elec;      // 电角度 (rad)
    float theta_mech;      // 机械角度 (rad)
    float speed_elec;      // 电速度 (rad/s)
    float speed_mech;      // 机械速度 (rad/s)
    
    /* 目标值 */
    float target_id;
    float target_iq;
    float target_speed;
    
    /* 母线电压 */
    float dc_bus_voltage;
    
    /* PWM占空比 */
    uint32_t PWM_A, PWM_B, PWM_C;
    
    /* 启动状态 */
    Startup_State_t startup_state;
    uint32_t startup_timer;
    
} FOC_Handle_t;

/* PI控制器结构体 */
typedef struct {
    float Kp, Ki, Kd;
    float integral;
    float prev_error;
    float output_limit;
    float integral_limit;
} PID_Handle_t;

/* 通信命令 */
typedef enum {
    CMD_SET_SPEED = 0x01,
    CMD_SET_CURRENT = 0x02,
    CMD_GET_STATUS = 0x03,
    CMD_SAVE_PARAMS = 0x04,
    CMD_RESET = 0x05
} Command_t;

/* 函数声明 */
void FOC_Init(FOC_Handle_t* hfoc, Motor_Params_t* motor);
void FOC_Loop(FOC_Handle_t* hfoc);
void Clarke_Transform(float Iu, float Iv, float Iw, 
                      float* Ialpha, float* Ibeta);
void Park_Transform(float Ialpha, float Ibeta, float theta,
                    float* Id, float* Iq);
void Inverse_Park_Transform(float Vd, float Vq, float theta,
                           float* Valpha, float* Vbeta);
void Motor_Start_Sequence(FOC_Handle_t* hfoc);
void Motor_Startup_Handler(FOC_Handle_t* hfoc);

/* PID控制器函数 */
void PID_Init(PID_Handle_t* pid, float Kp, float Ki, float Kd, float limit);
float PID_Calculate(PID_Handle_t* pid, float target, float feedback);
void PID_Reset(PID_Handle_t* pid);

#endif /* __FOC_CONTROL_H */

关键特性说明

1. 无传感器FOC算法

  • 实现完整的FOC控制环:电流采样 → Clark变换 → Park变换 → PI控制 → 反Park变换 → SVPWM
  • 集成滑模观测器(SMO)进行位置和速度估算
  • 支持三段式启动策略

2. 硬件优化

  • 使用STM32G474的高级定时器生成互补PWM
  • 三路ADC同步采样相电流
  • 内置运放用于电流信号调理
  • 硬件死区插入保护

3. 安全保护

  • 过流保护(硬件比较器+软件检测)
  • 过压/欠压保护
  • 过温保护
  • 位置估算异常检测

4. 通信接口

  • UART接口用于参数调试
  • CAN接口用于无人机通信
  • 支持实时参数调整和状态监控

5. 启动策略

  • 三段式启动:预定位 → 开环加速 → 切闭环
  • 可配置的启动参数
  • 启动失败检测和恢复

使用说明

  1. 硬件连接

    • 连接三相逆变器到TIM1的PWM输出
    • 连接电流采样电阻到ADC输入
    • 连接编码器接口(可选)
    • 连接CAN/UART调试接口
  2. 参数配置

    • motor_params中设置电机参数
    • 调整PI控制器参数
    • 配置保护阈值
  3. 调试

    • 通过UART发送调试命令
    • 监控系统状态和故障信息
    • 使用示波器观察PWM波形和电流波形

注意事项

  1. 确保死区时间设置足够防止桥臂直通
  2. 电流采样需要良好滤波和校准
  3. 启动参数需要根据具体电机调整
  4. 确保散热良好,避免过温
相关推荐
iYun在学C2 小时前
驱动程序开发(字符设备驱动框架实验)
linux·c语言·嵌入式硬件
悠哉悠哉愿意3 小时前
【嵌入式学习笔记】OLED 显示驱动 (SSD1306)
笔记·单片机·嵌入式硬件·学习
萧技电创EIIA3 小时前
如何使用嘉立创EDA绘制元件
嵌入式硬件·学习·硬件工程·pcb工艺
梁洪飞3 小时前
使用uboot学习I2C
嵌入式硬件·arm
_She0013 小时前
滤波器 变压器 功分器 的笔记
嵌入式硬件
大神与小汪4 小时前
STM32WB55串口蓝牙模块
stm32·单片机·嵌入式硬件
蝎蟹居4 小时前
GBT 4706.1-2024逐句解读系列(25) 第7.5条款:不同电压功率需清晰明确
人工智能·单片机·嵌入式硬件·物联网·安全
独处东汉5 小时前
AI辅助Stm32l031项目开发调试板子之按键跟adc
stm32·单片机·嵌入式硬件
【 STM32开发 】5 小时前
【STM32 CubeMX】DAC 输出正弦波
stm32·信号·dac·正弦波·数模转换