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. 启动策略
- 三段式启动:预定位 → 开环加速 → 切闭环
- 可配置的启动参数
- 启动失败检测和恢复
使用说明
-
硬件连接:
- 连接三相逆变器到TIM1的PWM输出
- 连接电流采样电阻到ADC输入
- 连接编码器接口(可选)
- 连接CAN/UART调试接口
-
参数配置:
- 在
motor_params中设置电机参数 - 调整PI控制器参数
- 配置保护阈值
- 在
-
调试:
- 通过UART发送调试命令
- 监控系统状态和故障信息
- 使用示波器观察PWM波形和电流波形
注意事项
- 确保死区时间设置足够防止桥臂直通
- 电流采样需要良好滤波和校准
- 启动参数需要根据具体电机调整
- 确保散热良好,避免过温