电机和FOC 算法

1、电机

1、异步电机(感应电机)

1、工作原理

感应电机的定子绕组通入三相交流电,产生旋转磁场。这个旋转磁场在转子上感应出电流(类似变压器的原理),再通过电磁力推动转子旋转。

转子转速 nr总是低于定子旋转磁场速度 ns,这就是“异步”的由来。


定子产生旋转磁场 → 转子感应电流 → 形成电磁力推动转子转动,但转速始终稍低于同步速度(有转差)

  • 感应电机(异步电机)\的转子是\短路绕组,转子磁场是感应出来的**。

  • 由于电磁感应原理,转子转速总是比定子旋转磁场慢一点,即有转差,否则不会产生感应电流。

  • 但永磁同步电机没有感应电流,直接由永磁体提供磁场,因此不会有转差,转子和定子磁场严格同步。

交流感应电机(异步电机)

2、永磁同步电机

永磁同步电机分为正弦波永磁同步电机方波驱动的永磁同步电机,其作用主要为车辆行驶提供驱动力,是电动汽车的动力装置。

1、组成

永磁同步电机主要由定子和转子、端盖、轴承、旋转变压器等部件组成。

  • 定子:电动机发电机中静止不动的部分,其主要作用是产生旋转磁场。‌在电动机中,定子通过通电的绕组产生旋转磁场,这个磁场驱动转子旋转,从而将电能转换为机械能。在发电机中,定子则用于产生电能,供应负载使用。‌

  • 转子:指由轴承支撑的旋转体。光盘等自身没有旋转轴的物体,当它采用刚性连接或附加轴时,可视为一个转子。

  • 轴承:它的主要功能是支撑机械旋转体,降低其运动过程中的摩擦系数(friction coefficient),并保证其回转精度(accuracy)。

  • 旋转变压器:是一种电磁式传感器,又称同步分解器。它是一种测量角度用的小型交流电动机,用来测量旋转物体的转轴角位移和角速度,由定子和转子组成。其中定子绕组作为变压器的原边,接受励磁电压,励磁频率通常用400、3000及5000HZ等。转子绕组作为变压器的副边,通过电磁耦合得到感应电压。

  • 电机的温度传感器(热敏电阻):热敏电阻是缠绕在定子绕组里面,监测电机的温度。

    2、工作原理

永磁同步电机中的永磁是指电机的转子是永磁铁(永磁体),同步是指转子频率与定子频率是一样的也就是没有转差。,电机是指将电能转化为机械能的装置

1、定子频率

  • 定子绕组通入三相交流电,产生一个旋转磁场

  • 这个旋转磁场的转速称为同步转速 Ns,由电源频率 f 决定(该公式使用所有的三相交流电电机):

    2、转子频率

  • 永磁同步电机的转子是永磁体,它不会自己产生感应电流,而是被定子磁场带动

  • 由于转子上的磁极被定子磁场吸引,转子和定子磁场同步旋转,所以转子机械转速等于定子的同步转速

换句话说,定子磁场的旋转频率(电角速度)和转子机械转速是一样的,所以叫“同步”电机!

3、步进电机

  • 按固定步长一步步旋转(每次给一个脉冲就转动一个固定角度)
  • 多相绕组,控制器逐步切换通电相序

4、伺服电机

原理:

  • 可以是 永磁同步电机 或 有刷/无刷直流电机
  • 关键是闭环控制:位置、速度、力矩由编码器反馈调节

5、无刷电机

原理:

  • 使用电子换向器代替碳刷(霍尔传感器检测位置)
  • 实质上是直流控制的三相永磁同步电机

6、有刷直流电机

原理:

  • 通过碳刷+换向器机械换向
  • 施加直流电压即可转动,简单易用

7、直流电机

是统称,包含:

  • 有刷直流电机(Brushed DC)
  • 无刷直流电机(BLDC)

原理:
电压直接控制电流 → 产生磁场 → 产生力矩
不需要三相交流系统

8、异步电机和永磁同步电机区别

比较项 感应电机(异步电机) 永磁同步电机(PMSM)
工作原理 通过定子旋转磁场在转子中感应电流,形成电磁力推动转子旋转(有转差) 通过定子旋转磁场直接驱动转子,转子由永磁体产生磁场(无转差)
转子类型 鼠笼式或绕线式转子 由永磁体(如钕铁硼)构成的转子
转速关系 转子转速 ( n_r ) 总是小于定子同步转速 ( n_s )(有转差) 转子转速 ( n_r ) 与同步转速 ( n_s ) 完全相同(无转差)
效率 相对较低(因为有转差导致额外损耗) 相对较高(无转差,损耗较少)
控制难度 直接接电网可运行,无需复杂控制 需要驱动器控制,才能正常启动和运行
启动方式 直接启动(DOL)、星三角启动、变频启动 需要变频器(FOC/矢量控制)进行启动
结构 结构简单、耐用,转子无磁体,制造成本较低 需要永磁体,制造成本较高
维护成本 低,因无永磁体,无励磁绕组,维护简单 略高,永磁体可能受高温或电磁干扰影响
适用场景 风机、水泵、压缩机、普通电机 电动汽车、机器人、伺服电机、高性能工业设备
调速能力 变频调速(V/F 控制)或矢量控制 需要矢量控制(FOC),响应更快,控制精确
扭矩特性 低速时扭矩较弱,需要额外启动手段 低速时仍可输出较大扭矩
过载能力 允许短时过载 受永磁体限制,过载能力一般
典型应用 工业电机、家用电器(洗衣机、风扇、空调) 电动车、伺服系统、航天航空

2、FOC

1、简单介绍和总结

目的:能让 三相交流电机(如 PMSM(永磁同步电机)、BLDC(无刷直流电机))像 直流电机 一样精准控制扭矩和速度。

核心目标:

  • 定子磁场 始终和 转子磁场 正交(90°),保证最大扭矩输出。

  • 采用 坐标变换(Clarke、Park 变换),将 三相交流信号 变成 直流信号,简化控制。

    控制环架构

​ 位置环(外环)→ 速度环(中环)→ 电流环(内环)

  • 位置环:计算目标速度(仅在位置控制模式下使用)。
  • 速度环:计算目标力矩(在速度控制模式下使用)。
  • 电流环:计算目标 q 轴电流并控制 PWM。

2、FOC 详细计算流程

1、AD转换获取电流值Ia和Ib,
2、通过Clark变换得到Iα和Iβ ,
3、获取电机角度,通过Park变换得到Id和Iq,
4、Id、Iq不能突变,同时为减少干扰,做平滑滤波,
5、Id、Iq与设定值比较,通过PID运算得到Vd 和Vq,

Step 1:三相电流采样

float Ia = Read_Current_A();  
float Ib = Read_Current_B();  
float Ic = - (Ia + Ib);  // 计算第三相电流

Step 2:Clarke 变换(三相 → αβ 轴)

float I_alpha = Ia;
float I_beta = (Ia + 2 * Ib) / sqrt(3);

Step 3:Park 变换(αβ 轴 → dq 轴)


我们一通操作将转子磁链进行了解耦,分解为了转子旋转的径向和切向这两个方向的变量:

float I_d = I_alpha * cos(theta) + I_beta * sin(theta);   //不需要的,我们希望尽可能把它控制为0  
float I_q = -I_alpha * sin(theta) + I_beta * cos(theta);    //需要的,代表了期望的力矩输出

其中 θ是 电机转子角度,可以通过 编码器反电动势估算 获取。

Step 4:位置环 、速度环 、电流环控制

应该通过位置环控制计算出目标速度,然后目标速度通过PI计算出目标电流,通过电流环再计算出PWM提供足够的扭矩

场景:

  • 位置控制时采用 位置环+电流环 控制(原因:但是在位置控制模式的时候,电机的转速会很慢,这时候用平均测速法会存在非常大的误差(转子不动或者动地很慢,编码器就没有输出或者只输出1、2个脉冲))

  • 位置环(外环)PI 控制器:根据目标位置和当前电机位置之间的误差,计算出目标速度。目标位置是最终的期望值,位置环的任务是将其转化为目标速度。

    // 位置环 PI 控制
    float Position_PI_Controller(float angle_ref, float angle, PI_Controller *pos_pi) {
      float error = angle_ref - angle;  // 计算位置误差
      pos_pi->integral += error * pos_pi->Ki;  // 计算积分项
      return pos_pi->Kp * error + pos_pi->integral;  // 计算目标速度 speed_ref
    }
    
    // 运行位置环
    void PositionControlLoop() {
      float angle = ReadEncoderTheta();  // 读取当前编码器位置(角度)
      speed_ref = Position_PI_Controller(angle_ref, angle, &Position_PI);  // 计算目标速度
    }
    
    • angle_ref:目标位置(角度)
    • angle:当前电机位置
    • 输出 speed_ref:目标速度(传给速度环)
  • 速度环(中环):根据目标速度和电机实际速度之间的误差,计算出目标电流。目标速度决定了电机旋转的快慢,速度环的任务是确保电机以期望速度运行。

    // 速度环 PI 控制
    float Speed_PI_Controller(float speed_ref, float speed, PI_Controller *speed_pi) {
      float error = speed_ref - speed;  // 计算速度误差
      speed_pi->integral += error * speed_pi->Ki;  // 计算积分项
      return speed_pi->Kp * error + speed_pi->integral;  // 输出 Iq_ref
    }
    
    // 运行速度环
    void SpeedControlLoop() {
      float speed = ComputeMotorSpeed();  // 计算当前速度
      Iq_ref = Speed_PI_Controller(speed_ref, speed, &Speed_PI);  // 计算目标 Iq
    }
    • speed_ref:目标速度(从位置环来的)
    • speed:当前电机速度
    • 输出 Iq_ref:目标转矩电流(传给电流环)
  • 电流环(内环):电流环计算出所需的电流来产生足够的扭矩以实现目标速度。电流环是FOC算法中的最后一个环节,它的目标是调整电流,使电机以所需的速度运行。

    // 电流环 PI 控制
    float Current_PI_Controller(float ref, float feedback, PI_Controller *current_pi) {
      float error = ref - feedback;  // 计算电流误差
      current_pi->integral += error * current_pi->Ki;  // 计算积分项
      return current_pi->Kp * error + current_pi->integral;  // 输出 Vq 或 Vd
    }
    
    // 运行电流环
    void CurrentControlLoop() {
      // Clarke 变换(Ia, Ib, Ic → I_alpha, I_beta)
      ClarkeTransform(Ia, Ib, Ic, &I_alpha, &I_beta);
    
      // Park 变换(I_alpha, I_beta → I_d, I_q)
      ParkTransform(I_alpha, I_beta, theta, &I_d, &I_q);
    
      // 计算 Vd, Vq
      V_d = Current_PI_Controller(Id_ref, I_d, &Id_PI);  // 磁场电流控制
      V_q = Current_PI_Controller(Iq_ref, I_q, &Iq_PI);  // 转矩电流控制
    
      // 逆 Park 变换(V_d, V_q → V_alpha, V_beta)
      InverseParkTransform(V_d, V_q, theta, &V_alpha, &V_beta);
    
      // SVPWM 计算 & 设置 PWM
      SVPWM(V_alpha, V_beta);
    }
    

float PI_Controller(float ref, float feedback, float Kp, float Ki, float *integral)
{
    float error = ref - feedback;
    *integral += error * Ki;
    return Kp * error + *integral;
}

// 计算 Vd 和 Vq
float Vd = PI_Controller(Id_ref, I_d, Kp_d, Ki_d, &integral_d);
float Vq = PI_Controller(Iq_ref, I_q, Kp_q, Ki_q, &integral_q)
  • ref(目标值):希望达到的电流值(设定值)。
  • feedback(反馈值):当前测量的电流值(电流采样得到的)。
  • Kp(比例系数):PI 控制器的比例参数。
  • Ki(积分系数):PI 控制器的积分参数。
  • integral(积分项):用于累积误差,实现积分控制。

Step 5:逆 Park 变换(dq 轴 → αβ 轴)

float V_alpha = Vd * cos(theta) - Vq * sin(theta);
float V_beta = Vd * sin(theta) + Vq * cos(theta);

Step 6:SVPWM(空间矢量脉宽调制)

void SVPWM(float V_alpha, float V_beta) {
    int sector = ComputeSector(V_alpha, V_beta);
    ComputeDutyCycles(sector, V_alpha, V_beta);
    SetPWM(T1, T2, T0);
}

这可以通过 现成的库(比如 ST 代码库TI FOC 库),也可以直接写

总体示例代码

// ==============================  利用实时的电机三相电流精准控制电机性能 ========================================
I_a, I_b, I_c  是实时的三相电流
// ==============================   保持电机在目标位置 ==================================================
#include "stm32f4xx_hal.h"
#include <math.h>

// 电机参数
#define MOTOR_POLE_PAIR 7
#define PI 3.14159265359

// 控制器参数
#define Kp_Position 10.0fc
#define Ki_Position 1.0f
#define Kp_Iq 1.0f
#define Ki_Iq 0.1f

// 假设获取电机位置的函数
extern float GetMotorPosition();  // 获取电机位置(通过编码器等)

// Clark 变换:三相电流 -> αβ 坐标系
void ClarkTransform(float I_a, float I_b, float I_c, float* I_alpha, float* I_beta) {
    *I_alpha = I_a;
    *I_beta = (I_a + 2 * I_b) / sqrt(3.0f);
}

// Park 变换:αβ -> dq 坐标系
void ParkTransform(float I_alpha, float I_beta, float theta, float* I_d, float* I_q) {
    *I_d = I_alpha * cos(theta) + I_beta * sin(theta);
    *I_q = -I_alpha * sin(theta) + I_beta * cos(theta);
}

// 位置环 PI 控制
float PositionPIController(float target_position, float current_position, float* integral) {
    float error = target_position - current_position;
    *integral += error;
    return Kp_Position * error + Ki_Position * (*integral);
}

// 控制电机的函数
void MotorControl() {
    // 获取电机当前位置
    float current_position = GetMotorPosition();  // 电机当前位置(通过编码器)

    // 设置目标位置
    float target_position = 1.0f;  // 目标位置(假设目标位置为 1.0 位置单位)

    // 使用位置环控制计算电压
    static float integral_position = 0.0f;
    float voltage = PositionPIController(target_position, current_position, &integral_position);

    // 控制电流(使用位置环计算的电压,进行电流调节等)
    float I_d = 0.0f;  // 假设磁场控制电流保持为 0
    float I_q = voltage;  // 转矩控制电流根据电压变化

    // Clark 变换和 Park 变换的电流控制
    float I_alpha, I_beta;
    ClarkTransform(I_a, I_b, I_c, &I_alpha, &I_beta);

    float motor_angle = current_position;  // 当前位置的电机角度
    float V_d, V_q;
    ParkTransform(I_alpha, I_beta, motor_angle, &V_d, &V_q);

    // 逆 Park 变换:计算最终电压(V_d, V_q)
    float V_alpha, V_beta;
    InverseParkTransform(V_d, V_q, motor_angle, &V_alpha, &V_beta);

    // PWM 输出
    GeneratePWM(V_alpha, V_beta);
}

// 主程序
int main(void) {
    HAL_Init();  // 初始化 HAL 库

    // 进行其他初始化,设置时钟,GPIO,PWM 输出等

    while (1) {
        // 进行电机控制
        MotorControl();

        // 延时
        HAL_Delay(10);  // 模拟实时控制
    }
}

// ==========================  保持电机在目标转速 ===================================================
// 速度环 PI 控制
float SpeedPIController(float target_speed, float current_speed, float* integral) {
    float error = target_speed - current_speed;
    *integral += error;
    return Kp_Speed * error + Ki_Speed * (*integral);
}

// 控制电机的函数
void MotorControl() {
    // 获取电机的速度(假设通过编码器获取速度)
    float current_speed = GetMotorSpeed();  // 电机当前速度

    // 设置目标速度
    float target_speed = 1000.0f;  // 假设目标速度为 1000 rpm

    // 使用速度环控制计算电压
    static float integral_speed = 0.0f;
    float voltage = SpeedPIController(target_speed, current_speed, &integral_speed);

    // 控制电流(通过速度控制调整电流)
    float I_d = 0.0f;  // 磁场电流
    float I_q = voltage;  // 转矩电流

    // Clark 变换和 Park 变换的电流控制
    float I_alpha, I_beta;
    ClarkTransform(I_a, I_b, I_c, &I_alpha, &I_beta);

    float motor_angle = GetMotorPosition();  // 获取电机角度
    float V_d, V_q;
    ParkTransform(I_alpha, I_beta, motor_angle, &V_d, &V_q);

    // 逆 Park 变换:计算最终电压(V_d, V_q)
    float V_alpha, V_beta;
    InverseParkTransform(V_d, V_q, motor_angle, &V_alpha, &V_beta);

    // PWM 输出
    GeneratePWM(V_alpha, V_beta);
}

// 主程序
int main(void) {
    HAL_Init();  // 初始化 HAL 库

    // 进行其他初始化,设置时钟,GPIO,PWM 输出等

    while (1) {
        // 进行电机控制
        MotorControl();

        // 延时
        HAL_Delay(10);  // 模拟实时控制
    }
}

// ========================== 给定目标速度,和目标位置 稳定到固定位置的示例 ===========================================
#include "stm32f4xx_hal.h"
#include <math.h>

// 定义常量
#define PI 3.14159265358979
#define MAX_VOLTAGE 24.0

// 电流目标(由上层控制给定)
float target_current_q = 0.0;  // 转矩控制
float target_current_d = 0.0;  // 磁场控制

// 当前电流(三相电流)
float I_a = 0.0, I_b = 0.0, I_c = 0.0;

// 当前电流在αβ坐标系下的分量
float I_alpha = 0.0, I_beta = 0.0;

// 当前电流在dq坐标系下的分量
float I_d = 0.0, I_q = 0.0;

// 转子角度(假设实时角度是通过编码器读取)
float theta = 0.0;

// PI 控制器的积分变量
float integral_d = 0.0, integral_q = 0.0;

// 电流环控制的 PI 参数
float Kp_d = 1.0, Ki_d = 0.1, Kp_q = 1.0, Ki_q = 0.1;

// 位置环控制的参数(用来根据目标位置控制目标速度)
float position_error = 0.0, target_position = 0.0, current_position = 0.0;
float target_velocity = 0.0;

// Clark 变换:三相电流 → αβ 坐标系
void clark_transform() {
    I_alpha = I_a;
    I_beta = (1.0 / sqrt(3)) * (I_a + 2.0 * I_b);  // Clark 变换公式
}

// Park 变换:αβ 坐标系 → dq 坐标系
void park_transform() {
    I_d = I_alpha * cos(theta) + I_beta * sin(theta);
    I_q = -I_alpha * sin(theta) + I_beta * cos(theta);
}

// PI 控制:调节 d 轴和 q 轴电流
void current_control() {
    // d 轴电流控制 (保持磁场)
    float error_d = target_current_d - I_d;
    integral_d += error_d;
    float V_d = Kp_d * error_d + Ki_d * integral_d;

    // q 轴电流控制 (控制转矩)
    float error_q = target_current_q - I_q;
    integral_q += error_q;
    float V_q = Kp_q * error_q + Ki_q * integral_q;

    // 逆 Park 变换:dq → αβ
    float V_alpha = V_d * cos(theta) - V_q * sin(theta);
    float V_beta = V_d * sin(theta) + V_q * cos(theta);

    // 计算SVPWM (根据V_alpha, V_beta计算PWM占空比)
    sv_pwm_calculation(V_alpha, V_beta);
}

// SVPWM 计算 (生成PWM信号)
void sv_pwm_calculation(float V_alpha, float V_beta) {
    // 使用空间矢量脉宽调制计算三相电压 (V_a, V_b, V_c)
    // 这里只是简单的伪代码,实际实现需要根据V_alpha, V_beta计算PWM占空比
    float V_max = sqrt(V_alpha * V_alpha + V_beta * V_beta);
    float V_a = V_max;  // 简化的计算
    float V_b = V_max;  // 简化的计算
    float V_c = V_max;  // 简化的计算

    // 通过 PWM 驱动电机
    drive_motor(V_a, V_b, V_c);
}

// 驱动电机 (PWM 输出)
void drive_motor(float V_a, float V_b, float V_c) {
    // 将电压信号转换为PWM信号输出到逆变器
    // 这里只是伪代码,实际中需要用PWM生成模块来驱动电机
    HAL_PWM_SetDutyCycle(TIM_CHANNEL_1, V_a);  // 假设TIM1作为PWM输出通道
    HAL_PWM_SetDutyCycle(TIM_CHANNEL_2, V_b);  // 假设TIM2作为PWM输出通道
    HAL_PWM_SetDutyCycle(TIM_CHANNEL_3, V_c);  // 假设TIM3作为PWM输出通道
}

// 位置环控制
void position_control() {
    // 目标位置与当前电机位置进行比较,计算出目标速度
    position_error = target_position - current_position;
    target_velocity = position_error * 0.1;  // 比例控制

    // 目标速度控制,调节目标电流
    velocity_control();
}

// 速度环控制
void velocity_control() {
    // 目标速度与当前电机速度进行比较
    float speed_error = target_velocity - current_velocity;
    target_current_q = speed_error * 0.1;  // 比例控制

    // 调用电流控制
    current_control();
}

int main(void) {
    // 初始化STM32硬件和外设...

    // 主循环
    while (1) {
        // 位置环控制
        position_control();

        // 获取当前电流值(I_a, I_b, I_c)并转换为 αβ 坐标系
        clark_transform();

        // 将 αβ 坐标系电流转换为 dq 坐标系
        park_transform();

        // 使用PI控制器调节电流并转换回 αβ 坐标系电压
        current_control();

        HAL_Delay(10);  // 10ms 控制周期
    }
}
博客内容均系原创,未经允许严禁转载!
您可以通过 RSS 订阅本站文章更新,订阅地址:https://blognas.hwb0307.com/feed/什么是 RSS ?
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇