wkhn
认证:优质创作者
所在专题目录 查看专题
通向数字电源之路——初学者入门(5)
通向数字电源之路--进阶(1)
通向数字电源之路--进阶(2)
通向数字电源之路--进阶(3)
通向数字电源之路--进阶(4)
通向数字电源之路--进阶(5)
作者动态 更多
一种采用CAN总线方式升级F28035芯片Flash的方法(三)
05-13 15:31
一种采用CAN总线方式升级F28035芯片Flash的方法(二)
05-13 15:31
一种采用CAN总线方式升级F28035芯片Flash的方法(一)
05-13 15:31
STM32G4系列MCU——数字电源入门(4)
2023-03-14 10:46
STM32G4系列MCU——数字电源入门(3)
2023-03-13 20:05

通向数字电源之路--进阶(4)

     libsmps_control_dspic33e-elf库函数的原代码是以汇编的形式给出的,需要有一定的汇编程序的编程基础,笔者以smps_pid_dspic_v2.s原代码为例,阐述一下PID算法的实现原理。分2部分:1.计算参数,2.代码分析。在附件中,有经过笔者修改的PID算法的代码,可以下载学习。

1)先计算PID函数中各个参数值:      

下图为PID算法的结构框图。

从上面的图可知,PID函数求解的差分方程为:

而PID的标准式为:

由此可知:

为了正确计算PID的差分方程的解,还要按照要求设置工作寄存器

以平均电流型控制电流内环环路的PI差分方程为例:

所以:KA=3.2116    KB=-3.125  代入前面的公式,可得:

在累加器中要做小数的乘法运算,且小数是大于1的,为了方便累加器的小数计算,应该把大于1的小数都化成小于1的小数,具体做法就是从KA、KB和KC中选出一个绝对值最大的数,然后每项都除以这个数。还有一点,这个除数应该比最大值还要再大一点,否则会出现1,也是无法用dsp的小数格式表示。上式中3.2116最大,可以选择3.2117做为除数,即

要注意,u[n-1]是上一次计算的结果,没有进行postShift和postScalar,所以不需要再除3.2117。

要将Ka和Kb、Kc做为系数填入到数组controllerPIDCoefficients[3]中,这一过程是在数组初始化时完成的。

controllerPIDCoefficients[0]=Ka;
controllerPIDCoefficients[1]=Kb;
controllerPIDCoefficients[2]=Kc;

并且在初始化工作寄存器时,还要将w9寄存器做为指针,指向controllerPIDCoefficientABC[3]数组的地址。

进行完一次差分方程的计算后,结果还要乘回3.2117这个数,才是差分方程解的最终值。因为1<3.2117<4(2^2),是无法用Q15格式表示的,所以

w6寄存器中的值为:

还要将ACCA寄存器的结果向左移2位,所以w7寄存器的值应填-2,负号表示向左移,因为都是向左移位,w7寄存器的值总是负值。

w11和w12寄存器是限制PID计算结果最小最大值的。

w10寄存器要做为指针指向controllerPIDErrorHistory[3]数组的地址,用来保存当前误差和前两次误差的结果。

w0是电流环路的参考值,也是PFC电压外环的PID输出值。

w1是ADC电感电流采样。w2是指向占空比寄存器的指针。

因为ADC采样是12位的,为了用满15位,所以要左移3位,w13要填3

2)分析PID算法的代码:

汇编程序以.text为程序的开头,以.end为程序的结尾。

.global _SMPS_ControllerPIDUpdate_HW_Accel

先将函数声明为全局函数,以供其它文件调用。然后是定义该函数,并编写函数的内容,注意函数名前都有下划线。

进入函数后,首先保存调用该函数前的CORCON寄存器,然后用w3、w14和w5三个寄存器将上次计算出的u[n-1]的值载入到ACCA累加器中,然后通过w4寄存器,设置本函数环境中需要用到的CORCON,主要是设置ACCA累加器的工作模式等参数。在这里,ACCA累加器被设置为普通饱和模式(1.31)且累加器ACCA是小数乘法运算。

接着计算误差e[n],并存储在w10指向的数组中。然后从w9和w10两个寄存器中获取两个数组的地址,然后是计算差分方程解的过程。在用mac指令进行乘法运算时,乘法的源操作数只能是w4、w5、w6和w7这4个寄存器,用其它的寄存器都会报错。另外,在mac指令预取操作时,x空间只能用w8和w9做指针;y空间只能用w10和w11做指针。也只有把两个不同的数定义在不同的x和y空间,才能做到在一个mac指令中预取2个数,所以要把controllerPIDCoefficients[3]和controllerPIDErrorHistory[3]分别定义在x空间和y空间。因为ACCA寄存器是40位的,所以用3个16位寄存器w3、w14和w5来保存,为了下一次计算PID差分方程时做为u[n-1]使用。

接下来的

sac.r a, w4

其实就是将ACCAH的内容保存在w4寄存器中。w4内容就是PID差分方程的解,但是在做PID算法之前,我们将系数KA、KB和KC都除了3.2117,因此在这个地方,要重新乘回来才是正确结果。w6和w7寄存器的值保存的就是3.2117这个数的dsp小数格式。

mpy w4*w6, a
sftac a, w7
sac.r a, w4

mpy是纯乘法指令,指明用ACCA累加器保存计算结果。如同前面文章中提到的,对于大于1的小数,先做乘法,再向左位移。然后再次将结果(ACCAH)保存在w4寄存器中。

接着做最大最小值的嵌位,最后把结果传送给PID算法的输出寄存器指针w2。对于本例来说就是PDC2。下面要把e[n]、e[n-1]和e[n-2]都保存起来,同时把w9和w10这两个指针复位,供下次PID计算时指向正确的地址。

这里上面一段官方原代码中,好像有点问题!此处不应该用w14寄存器,因为在前面的代码中,用到了w14来保存u[n-1],下图所示:

如果存储e[n]、e[n-1]和e[n-2]过程中,再用w14寄存器,w14原来的值会被覆盖!即u[n-1]的值会被覆盖,则下次计算PID时会出现错误。所以是不对的,笔者把w14改为w8,经过测试可以实现PID功能。

在原代码中,w8是指向结构体SMPS_Controller_Options_T的指针,这个结构体的成员triggerSelectFlag用来选择触发时间的计算方式,成员trigger是指向TRIG2寄存器的指针,成员period是指向PWM2周期寄存器的指针。在笔者的代码中,完全舍弃了这个结构体,将计算触发时间的代码以C语言的方式,写到本函数的外面。所以将下图中的263行至297行,全部删除。

然后提一下如何计算一下PWM2触发ADC的时间,即计算TRIG2寄存器的值。对于平均电流型控制模式,我们只要在达到占空比一半的时间点时触发ADC采样,采到的值就一定是被测量的平均值,这可以说是数字电源对比模拟电源的一个优点,因为模拟电源采集平均值需要进行低通滤波,会有一定的延时,而数字电源几乎是瞬时的。

TRIG2的计算方法:(其中Delay是指从PWM2发出波形到MOS管输出PWM波形的延时时间)

再说明一下,在本函数中,并没有进行触发时间的计算,而是在函数的外面以C语言的方式编写代码,在下一节中会有具体说明。

总结:

      PID差分方程的求解计算主要是应用累加器实现的,如何整定函数的参数,本文给出了详细的步骤,并指出了原代码中出现的错误,以及解决方法。里面涉及到了汇编代码的编程,需要对汇编指令有比较深入的了解,其中的一些细节更是无法一一提及,还需读者阅读相关的资料。推荐阅读《16位MCU和DSP程序员参考手册》(DS70157F_CN)。

      在下一节中,会以半无桥PFC为例,具体说说如何编写代码。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
本篇所含全部资料,点击此处留下邮箱我会发给你
资料明细:PID.rar
觉得内容不错的朋友,别忘了一键三连哦!
赞 5
收藏 6
关注 518
成为作者 赚取收益
全部留言
0/200
  • dy-Jqusb8PE 07-27 18:04
    老师,能不能发我一下资料,谢谢! 57****@****.com
    回复 1条回复
  • songxium 01-26 13:38
    老师,能不能发我一下资料,谢谢! so****@****.com
    回复 1条回复
  • power小白 01-21 13:08
    内容已删除 13****@****.com
    回复 1条回复
  • dy-iGugTBNk 01-05 19:32
    老师,能不能发我一下资料,谢谢! pe****@****.com
    回复 1条回复
  • dy-fr7bqalt 01-04 16:37
    老师,能不能发我一下资料,谢谢! da****@****.com
    回复 1条回复
  • anono 2023-09-11 14:15
    老师,能不能发我一下资料,谢谢! 10****@****.com
    回复 1条回复
  • dy-2DY7CWlG 2023-05-30 14:31
    老师,能不能发我一下资料,谢谢! 22****@****.com
    回复 1条回复
  • sdll825 2023-03-16 14:10
    老师,能不能发我一下资料,谢谢! sd****@****.com
    回复
  • yangwenlong 2023-02-28 22:17
    老师,能不能发我一下资料,谢谢! ya****@****.com
    回复 1条回复
  • yangwenlong 2023-02-28 22:15
    老师,能不能发我一下资料,谢谢! ya****@****.com
    回复
  • 熊紅 2022-11-27 11:24
    老师,能不能发我一下资料,谢谢! m1****@****.com
    回复 1条回复
  • hack100000 2022-09-14 12:54
    老师,能不能发我一下资料,谢谢! lo****@****.com
    回复 1条回复
  • hack100000 2022-09-14 12:48
    老师,能不能发我一下资料,谢谢! lo****@****.com
    回复
  • dy-beFnMfgk 2022-09-13 18:09
    老师,能不能发我一下资料,谢谢! 15****@****.com
    回复 1条回复
  • sgaqll1688 2022-07-23 10:52
    老师,能不能发我一下资料,谢谢! 24****@****.com
    回复 1条回复
  • 葫芦侠hlx 2022-06-30 20:12
    老师,能不能发我一下资料,谢谢! 70****@****.com
    回复 1条回复
  • dy-kDv6pyle 2022-06-16 16:14
    老师,能不能发我一下资料,谢谢! 86****@****.com
    回复 1条回复
  • xjj2215738 2021-12-26 18:59
    老师,能不能发我一下资料,谢谢! 44****@****.com
    回复 1条回复
  • zhoucwyh 2021-12-15 17:30
    老师,能不能发我一下资料,谢谢! zh****@****.com
    回复 1条回复
  • wbwb 2021-12-07 22:00
    老师,能不能发我一下资料,谢谢! wh****@****.com
    回复 1条回复