分享

SimpleFOC-多路PWM驱动,相电流监测

 云深无际 2023-03-24 发布于内蒙古

三天助力一个不知死活的本科生毕业论文,开搞!

3PWM

6PWM

在BLDC电机控制上,6路PWM 控制模式比3路PWM更自由,因为6个半桥式晶体管的每一个都可以单独控制。

死区时间

开关元器件的和严格意义并不是相同的。IGBT,MOS并不是理想开关器件,其开通时间和关断时间不是严格一致的,如果两端有电压,将导致直流电源短路,损坏桥臂功率器件,称之为“桥臂直通”。所以在驱动开关元器件门极的时候需要增加一段延时,确保另一个开关管完全关断之后再去打开这个开关元器件,通常存在两种情况;
上半桥关断后,延迟一段时间再打开下半桥;
下半桥关断后,延迟一段时间再打开上半桥;
这样就不会同时导通,从而避免功率元件烧毁。
相对于PWM来说,死区时间是在PWM输出的这个时间,上下管都不会有输出,当然会使波形输出中断,死区时间一般只占百分之几的周期。但是当PWM波本身占空比小时,空出的部分要比死区还大,所以死区会影响输出的纹波,但应该不是起到决定性作用的。
另外如果死区设置过小,但是仍然出现上下管同时导通,因为导通时间非常非常短,电流没有变得很大,不足以烧毁系统,那此时会导致开关元器件发热严重,所以选择合适的死区时间尤为重要,过大过小都不行。
因为门极上升和下降时间通常比延迟时间小很多,所以这里可以不用考虑它们。则死区时间满足;
:最大的关断延迟时间;
:最小的开通延迟时间;
:最大的驱动信号传递延迟时间;
:最小的驱动信号传递延迟时间;

上面就是三种基本的转子获得的方式,第一个是正交的光栅,第二个是电磁,最后一个是霍尔原件。

采样电阻是电流采样和对电压采样。对电流采样则串联一个阻值较小的电阻,对电压采样则并联一个阻值较大的电阻。

采样电阻的工作原理是欧姆定律,即I=U/R,通过IC检测电阻两端的电压,用电压除以电阻标称值即得到通过电阻的电流值。因此采样电阻的精度直接影响到电流采样的准确性。

老传统的采样电路了

采样电阻的采样原理:采样电阻将一个阻值较小的电阻,串联在电路中用于把电流转换为电压信号进行测量。采样电阻是一种限流元件,导体对电流的阻碍作用大,我们便说其采样电阻大,反之,称其采样电阻小。但是采样电阻并不会因为导体上没有电流通过而消失,采样电阻是一个导体的固有属性,即便导体上没有电流流过,其采样电阻也是存在的。采样电阻只是一个统称,对其深入了解之后会知道采样电阻多种多样,采样电阻连接采样电阻的阻值会选在1欧姆以下,属于毫欧级电阻,但是部分电阻,有个采样电压等要求,必须选择大阻值电阻,但是这样电阻基数大,产生的误差大。

电流检测结构要求高精度双向放大器具有比常规低侧或高侧放大器更好的PWM抑制。

这个是在线测量相电流的方式

我认为的PWM抑制是,这个地方测量到的相电流的大小,其实是在一个PWM的信号源里面知道电流的大小,所以就是要压制PWM。这就像是在飓风期间测量海上漂浮的杯子中的液体一样。

在这样的情况下测量电流的大小

SimpleFOC直接使用的是在线测量,而且还是双向测量

原理图

INA240的原理框图

大多数低端无刷电机驱动器没有电流测量功能,SimpleFOC提供了一种通过设置电机电压而不是电流来控制电机扭矩的方法。这使无刷直流电机有效地成为直流电机。

也叫直列式测量

电机的驱动电路可生成脉宽调制 (PWM) 信号来控制电机的运行。这些调制信号使得位置与各电机相位一致的测量电路进行共模电压 (VCM) 转换,在转换过程中,电压将在极短时间内在不同高电压电平之间进行切换。

完美的放大器产品能够完全抑制测量的 VCM 分量,仅放大与流经分流电阻器 的电流相对应的差分电压。不幸的是,实际的放大器产品并不理想,会受到大 PWM 驱动输入电压阶跃的影响。由于实际的放大器产品无法进行无限的抑制共模,因此放大器输出端可能会出现与每个输入电压阶跃相对应的大幅度意外干扰。

此类测量的常用方法是选择带宽较高的电流检测放大器。为了保持在可听频率范围之上,典型的调制频率 范围为 20kHz 至 30kHz。用于在这些 PWM 驱动应用 中进行直列式电流测量的放大器选择以信号带宽在 200kHz 至 500kHz 范围内的放大器为目标。以往选择放大器时并不基于显著低于 PWM 信号带宽的实际信号带宽。选择更高的放大器带宽可以使输出干扰在输入电压转换后快速稳定下来。

抑制过后得到的样子

消除噪声后表示的每个相位的输出电压信号。红色波形表示信号,表明经过电子换向的功率晶体管将正弦波形尽可能准确地复制到电机。电流感应放大器将经受从电源轨(例如 V BATT = 48V)到接地端的输入共模电压信号。

低侧相位检测可以更轻松地确定电动机的相电流,但这不是一种精确的方法。它可能会引入与相电流有关的误差。
主要挑战在于,共模电压是PWM信号,除非启用了适当的PWM抑制电路,否则会导致输出信号中断。这导致对电流感测放大器的要求更加严格,该电流感测放大器必须具有出色的DC和AC共模抑制比(CMRR)以及高DC精度(低输入失调电压)。一些设备测量在一个方向上流动的电流。
下面给出一个Arduino控制的FOC电流在线测量实例

对于放大器给出的电流就是直接使用ADC采集就行

让我们来过滤一下这个电流,因为频率的原因,就低通滤波就好

使用操作符重载一下

我们直接使用这个函数就行

相电流的变化,代码在文后

低侧电流测试

低侧电流检测可能是最常见的电流检测技术。主要原因是它既不需要高性能PWM抑制电流检测放大器(如在线检测放大器),也不需要支持高压的放大器(如高侧放大器)。

采样电阻始终置于低侧MOSFET和地之间,确保放大器的端子上始终具有非常低的电压。这种方法的主要缺点是,由于只有相应的低侧mosfet开启时,通过采样电阻的电流才是相电流,而我们只能在这些时刻测量到相电流。PWM频率通常为20至50 kHz,这意味着低侧MOSFET每秒开关20000至50000次,因此PWM设置和ADC采集之间的同步非常重要。

目前这个在开发中。

这个是高测测量一般也不用

https://www.ti.com.cn/product/cn/INA240
https://www.elecfans.com/analog/202007151246626.html
https://zhuanlan.zhihu.com/p/401573207
https://www.sohu.com/a/439655421_468638
https://baijiahao.baidu.com/s?id=1753450617334241521&wfr=spider&for=pc
https://m.elecfans.com/article/1107269.html
https://www.elecfans.com/d/1412716.html

// IN1 pwm1 9 27// IN2 pwm2 6 26// IN3 pwm3 5 25// INH1 enable1 8 12// INH2 enable2 7 13// INH3 enable3 4 14// in-line current sense - phase 1/A 35// in-line current sense - phase 1/C 34
#include <SimpleFOC.h>
class LowPassFilte{public: LowPassFilte(float Tf); // 低通滤波器时间常量 ~LowPassFilte() = default; float operator()(float x); float Tf; //!< 低通滤波器时间常量protected: unsigned long timestamp_prev; //!< 上次执行时间戳 float y_prev; //!< 经过上次执行后过滤到的值};
LowPassFilte::LowPassFilte(float time_constant) : Tf(time_constant), y_prev(0.0f){ timestamp_prev = micros();}
float LowPassFilte::operator()(float x){ unsigned long timestamp = micros(); float dt = (timestamp - timestamp_prev) * 1e-6f;
if (dt < 0.0f || dt > 0.5f) dt = 1e-3f;
float alpha = Tf / (Tf + dt); float y = alpha * y_prev + (1.0f - alpha) * x;
y_prev = y; timestamp_prev = timestamp; return y;}
LowPassFilte LF_a(0.01); // 原始数据滤波器LowPassFilte LF_b(0.01); // A相电流滤波器LowPassFilte LF_c(0.01); // C相电流滤波器
// AS5600编码器支持spi,iic和模拟量三种数据传输方式,这里用iic(同时也是最常用的方式)// magnetic sensor instance - I2CMagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);TwoWire I2Cone = TwoWire(0);
// BLDC motor & driver instanceBLDCMotor motor = BLDCMotor(11);BLDCDriver3PWM driver = BLDCDriver3PWM(27, 26, 25, 12, 13, 14);
InlineCurrentSense Cs_motor(0.001, 50.0, 35, 36, 34);
// voltage set point variablefloat target_voltage = 5.0;// instantiate the commanderCommander command = Commander(Serial);void doTarget(char *cmd){ command.scalar(&target_voltage, cmd);}
void setup(){ // initialise magnetic sensor hardware I2Cone.begin(18, 5, 400000); sensor.init(&I2Cone); // link the motor to the sensor motor.linkSensor(&sensor);
// power supply voltage driver.voltage_power_supply = 12; driver.init(); motor.linkDriver(&driver);
// aligning voltage motor.voltage_sensor_align = 5; // choose FOC modulation (optional) motor.foc_modulation = FOCModulationType::SpaceVectorPWM; // set motion control loop to be used motor.controller = MotionControlType::torque;
// use monitoring with serial Serial.begin(115200); // comment out if not needed motor.useMonitoring(Serial);
// initialize motor motor.init(); // align sensor and start FOC motor.initFOC();
// add target command T command.add('T', doTarget, "target voltage");
Serial.println(F("Motor ready.")); Serial.println(F("Set the target voltage using serial terminal:")); _delay(1000);
Cs_motor.init();}
void loop(){
// main FOC algorithm function // the faster you run this function the better // Arduino UNO loop ~1kHz // Bluepill loop ~10kHz motor.loopFOC(); // Motion control function // velocity, position or voltage (defined in motor.controller) // this function can be run at much lower frequency than loopFOC() function // You can also use motor.move() and set the motor.target in the code motor.move(target_voltage);
// Cs_motor.getPhaseCurrents(); Serial.print(LF_b((Cs_motor.getPhaseCurrents()).a)); Serial.print(","); Serial.println(LF_c((Cs_motor.getPhaseCurrents()).c));
// Serial.print(LF_a(analogRead(35))); // Serial.print(","); // Serial.print(LF_b((3.3 * ((float)analogRead(35) - 1930) / 4096.0) * 20.0)); // Serial.print(","); // Serial.println(LF_c((-3.3 * ((float)analogRead(34) - 1930) / 4096.0) * 20.0));
// user communication command.run();}

相电流的检测函数

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多