
1 总体软件架构 MC SDK5.x 包含有芯片外设库,电机库和电机应用层三个主要部分,其中: 芯片外设库使用 ST HAL/LL 库,可被各个层级调用; 电机库则是主要的电机 FOC 控制层;最上层为电机应用层,供客户直接使用电机库,而不去关心底层如何实现的,加快用户程序开发;另外 MC SDK5.x 还提供 UI 库,用于界面调试通讯使用,比如和 Workbench 之间的交互就是通过 UI 库实现; 这里强调的一点是电机库是综合体,包含 FOC 算法,单片机外设配置,中断机制等各个环节,简单控制可能只需要关心电机应用层即可,如果复杂控制将涉及到整体操作。 1 V9 ]- A% \5 g. A/ T; b2 u: ~ ![]() 在 SDK 使用过程中,电机本体、电机控制硬件板、控制管脚、控制策略在 MC workbench 中配置完成,顺序为 MC Workbench -> CubeMx 工程 -> 电机库代码(芯片外设库 + 电机控制库 + 电机驾驶舱 + 用户界面库 + 系统初始化),该生成代码加入简单 API 后(比如 MC_StartMotor1)可以直接运行对应电机,当需要细化控制或者复杂控制时才有可能涉及到修改电机驾驶舱或者电机控制库中的代码。 % l5 I/ R5 q j+ A. c+ P ![]() 2 Z6 E6 I6 e; f( O$ x2 H( f; X 1.1 芯片外设库 针对芯片的每种外设都有对应的库函数提供,需要结合 Cube 使用说明调用这些库函数; 电机库必须掌握的外设有 TIMER,ADC,GPIO。 ![]() 4 w& K/ {' v) y# U+ q 1.2 电机控制库文件及其说明 一般来说,普通应用这个部分不会涉及到,如果是在 API 层已经无法满足电机控制的需求时才会考虑修改这个部分,需要对电机运行框架非常熟悉的前提下去进行修改。 ![]() $ E7 P; ~ ]! |( _ 1.3 电机驾驶舱 这个部分就是为客户直接使用电机库而准备的,各种 API 函数供用户调用;可以说简单应用或直接使用这些 API 函数足够达成电机控制应用,客户不需要关心底层如何操作,只需要关注自身需要实现哪些必要的功能,使得项目开发更加快速有效。 这里以一个马达控制函数为例:如果双马达控制的第二个马达则将后缀变为 Motor2,比如启动第二个电机的函数名为 MC_StartMotor2(),此处所涉及的除非特别说明,速度即为机械速度。 ![]() ![]() ' v; U# ?. S! f 2 软件主要环路 包含有三个主要环路:FOC 环路,安全环路,电机控制环路;虚线方框部分为可选择组件,实现部分为主要组件,可以看到整个控制围绕了电机控制系统的方方面面。 ![]() 整体软件框图 可以看到上面的电机控制框图三个环路构成了底层驱动部分,对于整体程序流程上,电机库控制过程都发生在中断中,区别于普通顺序控制流程,也无任务调度;这样做可以将电机控制做到实时控制,因此整个 STM32 产品都可以用于 FOC 控制。
![]() % c) l4 A3 @$ k# M& D2 R/ I! E 3.1 Main函数 在 main.c 中主要是系统的初始化函数,main 函数更是条理清晰。 ![]() 3.2 两个重要的中断 3.2.1 ADC 转换完成中断 3.2.1 ADC 转换完成中断 高频任务执行于 ADC 采样转换完成中断,ADC 采样开始由 TIM1 硬件触发,转换完成后进入中断,在这个中断中执行 FOC 坐标变换以及 SVPWM 的执行,最终控制 TIM1 的 PWM 占空比输出。 ![]() 注:XXX代表不同的芯片,不同采样策略对应的不同函数名称,比如STM32F302R8的三电阻采样方式xxx为r3_1_f30x,对应的文件名即为r3_1_f30x_pwm_curr_fdbk.c,对应的函数名称为R3_1_F30X_WriteTIMRegisters() 3.2.2 Systick中断 这个中断默认为 500us 的定时中断,安全任务执行在这个中断中,并且以 500us 为基础,中频任务也执行在这个中断中,比如我们设定的速度环执行为 2ms,实际是 500us*4,也就是四次 systick 中断后执行一次中频任务。 " d0 A5 s$ L. _! |5 l" O6 Z ![]() 三大任务流程 1 W" @7 ?1 @; t2 g# o/ P, L 4.1 高频任务 高频任务函数位于 mc_task.c 的 TSK_HighFrequencyTask()函数中,执行的是核心 FOC 算法。 5 |' c% @) N8 j! F& |( X 2 C @( k: \. [! ]![]() 4.2 安全任务 所说的安全任务,字面意义已经很明确。这个部分对于过温、过流、欠压、过压保护进行判断,如果触发了上述保护,则会关闭 PWM 输出,复位电机控制参数,同时这个部分也是温度 ADC 采样,母线电压采样,用户 ADC 采样的执行地方。 ![]() 1 u- c K2 Y, H; W4 ^ 4.3 中频任务 中频任务执行于 systick 中断中,实际为速度环以及状态机执行地方,同时包含有功率计算,如需要增加个人状态机,这个地方为添加点,同时注意根据传感器不同,平均速度获取函数也不同。 ![]() ![]() ![]() * r$ S/ ^0 ~/ \: N' Y+ H 附录 下面内容是就用户比较关心的电流,电压问题做必要说明。 7 V/ P2 B" \# V: a2 D8 R8 a 5.1 三相电流获取 电流的采样在电机培训中提及,为硬件触发机制,TIM1 或者辅助 TIMER 触发 ADC 转换,转换结束后进入到 ADC 中断中,关于采样点选择,触发点请参看电机培训文档,这边不做过多描述;如果用户需要使用得到三相电流值,则可以通过几种方式获取,这边使用了基尔霍夫定理 Ia+Ib+Ic=0,因此取得 Ia,Ib 电流即可。 ; S0 o- V( N/ K' w$ U 5.1.1 API 函数读取电流值 使用 API 函数 MC_GetIabMotor1(),返回值为 Curr_Components 这个结构体。 ![]() ![]() 5 p; g5 ?" c j$ i7 L: @! D 如果定义一个变量,则 Ia,Ib 分别是结构体变量的两个 int16 数据,如下所示: ![]() 5.1.2 利用已有的全局变量获取 我们看到在 mc_task.c 中有全局变量 FOCVars 这个变量,而这个结构体变量的其中一员即我们需要得到的 Ia,Ib 数据。% O$ Q# f1 a$ |& e: D ![]() ![]() 4 X B+ P* [. V% _7 x 可以有下面的读取方式: ![]() & E3 v4 x+ W0 p1 |7 x! D' ^ 值得说明的是有些关注于底层 ADC 采样的用户很可能想到的是直接从 ADC 外设获取,很遗憾,在 ST 的电机库中 Ia,Ib 的数据得到非固定方式存在,即使使用了 Inject 注入通道进行采样,因为算法的灵活性 JDR1,JDR2 寄存器中存入的数据的意义是根据控制在变动的,比如 JDR1 可能 Ia,也可能是 Ib,因此该方式无法直接获取电流数据。 0 a& d, P3 B' C2 T4 k& g* L R. c K 5.2 母线电压的获取 在 API 函数中这个部分没有涉及获取函数,因此有必要在此做些说明。母线电压的读取部分在 TSK_SafetyTask()函数中执行,这边会得到一个平均值电压数据,这边简单介绍下获取过程,如果对这个部分不关心,可以忽略。 ![]() 5.2.1 函数获取方式 在 bus_voltage_sensor.c 中给出了两种电压格式函数,VBS_GetAvBusVoltage_d()返回的是母线电压的数字量,VBS_GetAvBusVoltage_V()返回的是以伏特(V)为单位的母线电压。 ![]() 这边需要使用的是 MCT 这个结构体组件,定义在 mc_task.c 中。 2 v4 X3 ^5 L, C9 p ![]() ( |- f y( j- q( } 具体使用如下操作: ![]() 5.2.2 全局变量取得母线电压 注意到在母线电压结构体定义过程,有直接的全局变量 RDivider_Handle_t,该结构体成员之一即为BusVoltageSensor_Handle_t _Super;这个我们所要的结构体。 ![]() ![]() ]( F$ f7 K' N4 B* a; W5 \7 E 因此使用全局变量得到母线电压的操作如下,这边得到的是数字量的母线电压,如果需要转换为伏特则根据参数进行计算得到即可: ![]() : {: w g, `9 c( R6 _7 P) s6 m* @ 5.3 状态机操作 一般操作中不需要另外增加状态,如果需要在中频任务中增加自己的状态,假定添加的状态需要位于 START RUN 和 RUN 中间则需要有以下操作: 在 state_machine.h 的 State_t 结构体变量中增加状态,比如 USER_DEFINE_STATE = 21。 ![]() 修改 mc_task.c 中频任务函数 TSK_MediumFrequencyTaskM1()中的状态跳转,START RUN -> USER_DEFINE_STATE -> RUN 同时增加一个新的状态 USER_DEFINE_STATE 分支语句。 ![]() 8 j6 g9 M* l7 I4 h5 G9 n; C* H 因为涉及到状态跳转是否正确问题,还需要在 state_machine.c 中修改状态跳转的判断,做到承上启下的状态跳转,比如下面的判断修改: ![]() 上述为添加状态操作,删除操作或者是改变状态转移同样需要注意上下状态的切换,可以使用 STM_NextState()函数以及修改 state_machine.c 中修改状态跳转的判断灵活操作。 : I* K; H) S: P2 U k# J 6 总结 ▼简单概括 MC SDK 整体框图,大家可以很清晰的看到三重架构,从下往上分别是外设层,电机库层,电机应用层;一般应用用户只需要熟练掌握电机应用层的 API 即可使用,用户可以从 ST 电机控制培训文档进行详细了解; " e* U2 P6 s, I' Q! m' d; w ▼软件框架角度,因为主体控制位于中断服务程序中,需要关注 ADC 采样完成中断以及 Systick 中断; ▼再深入研究,三大任务需要注意,高频任务,安全任务,中频任务; ▼高级应用则需要深入到电机底层库,详细掌握各个组件,进行相应的修改或者调用。 |
Bus_Voltage_V = VBS_GetAvBusVoltage_d(MCT[M1].pBusVoltageSensor);
然后就报错,说没有定义MCT,可是他在task.c文件里边不是已经定义了么,
è¿æ¯å¨ä¸»å½æ°çwhileä¸è¾¹å ç