单片机学习小组
直播中

山中老虎

8年用户 921经验值
擅长:制造/封装
私信 关注

如何实现FOC算法?

如何实现FOC算法?

回帖(1)

李琳

2022-2-23 10:42:35
Arduino Simple FOC库的目标是通过(至少)三种最标准的电流感应类型来支持 FOC 实现:



到目前为止(检查发布),Arduino Simple FOC库仅支持在线电流感应。

当前的每一种传感类都将实现所有必要的功能,以实现 FOC 算法的简单而稳健的实现:



  • 硬件配置


    • ADC 分辨率和频率
    • 自动零偏移查找


  • 驱动同步


    • ADC 采集事件触发
    • 与驱动程序阶段的自适应对齐


  • 读取相电流



    • 电流矢量幅度的计算
    • FOC d 和 q 电流的计算



每个实现的类都可以用作独立的类,它们可用于读取 Arduino Simple FOC库范围之外的 BLDC 驱动器输出上的当前值,请参见 中的示例代码utils > current_sense_test。为了使 FOC 算法工作,电流检测类链接到BLDCMotor使用驱动器读取 FOC 电流的类。

在线电流检测


在线电流检测技术是最简单的一种,也是最精确的一种。分流电阻器与电机相位对齐,在这些分流电阻器上测得的电流将是电机相电流,而与 PWM 占空比的状态无关。因此,这种实现非常适合 Arduino 设备,因为可以随时对 adc 进行采样以读取电流,并且 adc 采集持续时间与其他电流感应方法一样重要。这种方法的缺点是硬件,这种电流检测架构需要高精度双向放大器,其 PWM 抑制比常规低端或高端放大器要好得多。





1. 硬件配置


// InlineCurrentSensor constructor
//  - shunt_resistor  - shunt resistor value
//  - gain  - current-sense op-amp gain
//  - phA   - A phase adc pin
//  - phB   - B phase adc pin
//  - phC   - C phase adc pin (optional)
InlineCurrentSense current_sense  = InlineCurrentSense(0.01, 20, A0, A1, A2);
要使用Simple FOC库实例化内联电流传感器,只需创建该类的实例InlineCurrentSense。此类将分流电阻值shunt_resistor、放大增益gain和两个或三个 ADC 通道引脚作为参数,具体取决于您可能拥有的可用测量硬件。为正确的驱动器/电机相位指定正确的 adc 通道很重要。因此,如果您的引脚A0测量相电流A并且引脚A1测量相电流,请B确保按该顺序将它们提供给构造函数。



InlineCurrentSense current_sense  = InlineCurrentSense(0.01, 20, A0, A2);
磁场定向控制算法可以与 2 相或 3 相电流测量一起运行。

InlineCurrentSense该类的构造函数只允许您指定一个分流电阻值和一个放大增益。如果您的硬件配置对不同的相位有不同的分流器/放大器值,您可以通过更改gain_x属性来指定它们:

// default values of per phase gains
current_sense.gain_a = 1.0 / shunt_resistor / gain;
current_sense.gain_b = 1.0 / shunt_resistor / gain;
current_sense.gain_c = 1.0 / shunt_resistor / gain;
例如,Arduino Simple FOC Shield v2 的 B 相电流感应反转。因此,在这种情况下,您可以指定:

// inverse current sensing gain on phase b
current_sense.gain_b *= -1;
一旦创建了当前的感测,就可以对其进行初始化。此init()函数配置 ADC 硬件以进行读取,并为每个通道查找 ADC 的零偏移量。

// init current sense
current_sense.init();
一旦您的电流感应被初始化和校准,您就可以开始测量电流!

使用 FOC 算法的电流检测


要InlineCurrentSense与 FOC 算法一起使用,您需要做的就添加他,与BLDCMotor链接:

// link motor and current sense
motor.linkCurrentSense(¤t_sense);
对齐所有传感器,BLDCMotor的initFOC()函数中的类,将InlineCurrentSense与BLDCDriver链接到电机的对齐。

// prepare sensors for FOC
motor.initFOC();
函数initFOC()将调用两个重要的电流检测类函数:



  • current_sense.driverSync(...)
  • current_sense.driverAlign(...)
  • 驱动同步 driverSync(...)




由于内联电流检测技术不需要触发特定事件以进行 ADC 采集,因此该driverSync()功能实际上什么也不做。如上图所示,此功能对于低侧和高侧电流检测非常重要。

与电机相位对齐 driverAlign(...)


对齐是通过调用函数完成的:

current_sense.driverAlign(&driver, voltage_sensor_align);
此功能适用于使用驱动程序实例向每一相施加电压并检查测量的电流是否与施加电压的方向相对应。此对齐程序能够纠正:



  • adc 引脚顺序不正确
  • 错误的增益符号


如果在监控期间对电机启用initFOC了监控,则监控器将显示对中状态:



  • 0 - 失败
  • 1 - 成功,没有任何改变
  • 2 - 成功但引脚重新配置
  • 3 - 成功但收益倒转
  • 4 - 成功,但引脚重新配置并获得反转


如果您确定您的配置并且如果您希望跳过对齐过程,您可以在调用 motor.initFOC() 之前指定设置 skip_align 标志:

// skip alignment procedure
current_sense.skip_align = true;
例如 Arduino Simple FOC Shield v2,您将拥有与此类似的代码:

// invert phase b gain
current_sense.gain_b *=-1;
// skip alignment
current_sense.skip_align = true;
...
// align all sensors
motor.initFOC();
独立电流检测


要在配置硬件并校准后将您的在线电流传感器用作独立传感器,您可以通过调用读取相电流:

PhaseCurrent_s  current = current_sense.getPhaseCurrents();
该函数返回PhaseCurrent_s的是其中有三个变量结构a,b和c。例如,您可以将它们打印出来;

Serial.println(current.a);
Serial.println(current.b);
Serial.println(current.c); // 0 if only two currents mode
如果您在 中仅使用两相电流测量InlineCurrentSense,它将返回current.c等于 0的第三个电流。

有时相电流很难解释,因此此电流检测类使您能够读取转换后的电流矢量幅度。电机消耗的绝对直流电流。

float current_mag = current_sense.getDCCurrent();
此外,如果您可以访问连接到驱动器的电机的位置传感器,您可以通过将其提供给getDCCurrent方法来获得电机正在汲取的直流电流的有符号值。

float current = current_sense.getDCCurrent(motor_electrical_angle);
最后,如果您可以访问电机位置传感器,您的电流感应类将能够告诉您电机正在绘制的 FOC 电流 D 和 Q。

DQCurrent_s current = current_sense.getFOCCurrents(motor_electrical_angle);
此函数返回DQCurrent_s具有两个变量的结构体,d和q。您可以将它们打印出来,例如:

Serial.println(current.d);
Serial.println(current.q);
示例代码


以下是使用Simple FOC库Simple FOC Shield v2作为独立传感器的在线电流检测的简单示例。

#include

// current sensor
// shunt resistor value
// gain value
// pins phase A,B
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2);

void setup() {
  // initialise the current sensing
  current_sense.init();

  // for SimpleFOCShield v2.01/v2.0.2
  current_sense.gain_b *= -1;
  
  Serial.begin(115200);
  Serial.println("Current sense ready.");
}

void loop() {

    PhaseCurrent_s currents = current_sense.getPhaseCurrents();
    float current_magnitude = current_sense.getCurrent();

    Serial.print(currents.a*1000); // milli Amps
    Serial.print("t");
    Serial.print(currents.b*1000); // milli Amps
    Serial.print("t");
    Serial.print(currents.c*1000); // milli Amps
    Serial.print("t");
    Serial.println(current_magnitude*1000); // milli Amps
}










举报

更多回帖

发帖
×
20
完善资料,
赚取积分