0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在FPGA上快速构建PID算法

jf_78858299 来源:OpenFPGA 作者:碎碎思 2023-05-11 15:36 次阅读

作为一名工程师,在项目实施阶段多多少少会遇到需要使用控制理论的应用程序。

一种非常常用的算法是比例积分微分控制器(proportional-integral-derivative control)或 PID 控制器。PID 算法用于控制各种应用中温度、压力、电机位置和流量等变量。我经常看到的一个地方是高端图像处理系统(制冷型红外),为了减少图像中的噪点。它使用热电冷却器或其他冷却系统来冷却图像传感器。对于高端成像,较低的噪声可以带来更好的图像。

介绍

PID 控制算法实现起来并不难,因为它只需要加法、乘法、除法和减法(dog)。但是,一旦算法实施,确保 PID 回路稳定的三个系数可能需要一点额外的时间来获取。

PID 主要使用三个术语。

  • 比例(Proportional) -测量期望值和测量值之间的差异。比例值是当前位置的量度。
  • 积分(Integral) -会随着时间的推移对误差进行积分。积分项是误差的历史累积值。随着误差的消除,积分项停止增长。
  • 导数(Derivative) -计算变化率并预测误差的未来趋势。

每个术语还具有相关的增益 KI、KP 或 KD,可以帮助我们调整 PID 控制器算法的行为。D 项不是必须的,而且简单的情况下我们基本不使用,使用 PI 控制器也很常见。

PID经常使用浮点数来实现。因此,我们可以使用诸如 VHDL Fixed/Float 之类的库在 RTL 中实现。或者,我们可以使用HLS来实现 PID,因为国内应用VHDL较少,所以我们今天的实例是使用HLS构建我们的PID算法。使用HLS能够使用浮点或任意精度的定点数。HLS还能通过#pragma 快速的为IP添加通用控制接口(AXI)。

在纯 FPGA 实现类似系统时候,我们需要添加软核来控制IP。在较小的 Zynq-7000 SoC FPGA(7007、7010、7020 等)中则可以通过硬核控制IP。或者,如果我们设计中不想使用处理器,那我们可以设计传统的矢量接口即可。

源码设计

PID 的实际源代码非常简单,如下所示。

#include "pid.h"

static data_type error_prev =0;
static data_type i_prev=0;

data_type PID (data_type set_point, data_type KP, data_type KI, data_type KD, data_type sample, data_type ts, data_type pmax)
{
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=s_axilite port=sample
#pragma HLS INTERFACE mode=s_axilite port=KD
#pragma HLS INTERFACE mode=s_axilite port=KI
#pragma HLS INTERFACE mode=s_axilite port=KP
#pragma HLS INTERFACE mode=s_axilite port=set_point
#pragma HLS INTERFACE mode=s_axilite port=ts
#pragma HLS INTERFACE mode=s_axilite port=pmax
 data_type error, i, d, p;
 data_type temp;
 data_type op;

 error = set_point - sample;

 p = error * KP;
 i = i_prev + (error  * ts * KI);
 d = KD * ((error - error_prev) / ts);

 op = p+i+d;
 error_prev = error;
 if (op > pmax)  {
  i_prev = i_prev;
  op = pmax;
 }else{
  i_prev = i;
 }
 return op;
}

已将previous error和previous integral声明为全局静态变量,以确保它们在迭代时候其值保持不变。

在算法方面,用户可以在应用程序运行时动态加载 KP、KI、KID、Ts 和 Pmax。我们可以轻松地添加积分值或使用附加寄存器重新启动控制器。这将使 PID 可以用于多个实现。

为了测试和配置 PID,测试文件罗列了一系列温度值,这些温度都远高于预期的目标设定点,并确保达到设定点。此示例中的 PID 设计用于提供功率(以瓦特为单位)维持光学床的温度。在这种情况下,我们需要加热而不是降低温度。

#include "pid.h"
#include 
#define iterations 40
int main(void)
{

data_type set_point = -80.0;
data_type sample[iterations] = {-90.000,-88.988,-87.977,-86.966,-85.955,-84.946,-83.936,-82.928,-81.920,-80.912,-80.283,-79.926,-79.784,-79.774,-79.829,-79.898,-79.955,-79.993,-80.011,-80.017,-80.016,-80.010,-80.005,-80.002,-80.000,-79.999,-79.999,-79.999,-79.999,-80.000,-80.000,-80.000,-80.000,-80.000,-80.000,-80.000,-79.999,-80.000,-80.001,-80.000};

data_type kp = 19.6827; // w/k
data_type ki = 0.7420; // w/k/s
data_type kd = 0.0;
data_type op;

printf("testing cpp\\r\\n");

for (int i =0; i

在 Vitis HLS 中针对该 PID 算法进行C 仿真和协同仿真,结果完全符合预期。

图片

算法按照预期运行,下一步是综合和导出 IP,最后就是添加到我们的 Vivado 项目中。这次我们使用的是ZYNQ FPGA。

图片

延迟性能和资源消耗下面的完整框图反映了添加到Vivado项目中情况。

图片

框图图片

总设计资源图片

PID 资源构建完成上面的Vivado项目,接下来就是导出硬件(XSA)到 Vitis 中开发驱动。

在 Vitis 中开发驱动时候,我重用了 HLS 仿真文件中的几个元素。

由于我们使用的是 AXI 接口,Vitis HLS 在导出IP时候地为我们提供了一个可以在 Vitis 中用于驱动 IP 核的驱动程序。但是,当在 IP 内核中使用浮点输入时,驱动程序则期望它们为 U32。如果我们在开发驱动时候从浮点数转换为 U32,我们将失去准确性。因此,解决这个问题的方法是使用指针(pointers)和强制转换。

图片

本质上,我们将变量声明为浮点数,然后在函数中调用设置一个指向浮点变量地址的 U32 指针,并使用间接运算符读取该值。

XPid_Set_set_point ( & pid ,  * ( ( u32 * ) & set_point ) ) ;

整个应用程序是

#include 
#include "platform.h"
#include "xil_printf.h"
#include "xpid.h"
#define iterations 40

typedef float data_type;
data_type set_point = -80.0;
data_type sample[iterations] = {-90.000,-88.988,-87.977,-86.966,-85.955,-84.946,-83.936,-82.928,-81.920,-80.912,-80.283,-79.926,-79.784,-79.774,-79.829,-79.898,-79.955,-79.993,-80.011,-80.017,-80.016,-80.010,-80.005,-80.002,-80.000,-79.999,-79.999,-79.999,-79.999,-80.000,-80.000,-80.000,-80.000,-80.000,-80.000,-80.000,-79.999,-80.000,-80.001,-80.000};

data_type kp = 19.6827; // w/k
data_type ki = 0.7420; // w/k/s
data_type kd = 0.0;
data_type ts = 12.5;
data_type pmax = 40;
u32 op;

XPid pid;

int main()
{
    float result;
    init_platform();
    disable_caches();
    print("Adiuvo PID Example\\n\\r");
    XPid_Initialize(&pid,XPAR_XPID_0_DEVICE_ID);
    XPid_Set_set_point(&pid, *((u32*)&set_point ));
    XPid_Set_KP(&pid,  *((u32*)&kp));
    XPid_Set_KI(&pid,  *((u32*)&ki));
    XPid_Set_KD(&pid,  *((u32*)&kd));
    XPid_Set_ts(&pid,  *((u32*)&ts));
    XPid_Set_pmax(&pid,  *((u32*)&pmax));
    u32 tst = XPid_Get_set_point(&pid);
    for (int i =0; i

运行,得到以下结果。

图片

正如预期的那样,硬件中的实现与软件的工作方式相同。

当然,对于不同的应用程序,我们需要重新确定可用于应用程序的 KP、KI 和 KD 变量。

这样做的真正美妙之处在于,因为它是用 C 实现的,可维护性高,可以快速构建一个我们需要的PID算法。

完整项目在下面链接里。

参考

https://www.cnki.com.cn/Article/CJFDTOTAL-CAIZ201316188.htm

https://www.adiuvoengineering.com/

总结

虽然上面的流程很简单,但是HLS在调整资源和速度方面还是需要一些时间,并且浪费的资源还是比纯HDL多。

最后在说一下该方式的缺点,PID需要进行浮点运算,而FPGA则不能进行浮点运算,如果想把上面的算法在逻辑中运行,则需要自己进行量化,但是如果像上面例程的方式在内核(硬核)中运行算法,则该方式简单且优雅~

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    112

    文章

    15214

    浏览量

    171138
  • 噪声
    +关注

    关注

    13

    文章

    1070

    浏览量

    47060
  • PID
    PID
    +关注

    关注

    35

    文章

    1446

    浏览量

    83792
  • 图像处理器
    +关注

    关注

    1

    文章

    95

    浏览量

    15320
收藏 人收藏

    评论

    相关推荐

    基于FPGA的模糊PID控制算法的研究及实现

    基于FPGA的模糊PID控制算法的研究及实现
    发表于 03-18 14:25

    FPGA中实现PID算法

    本帖最后由 发烧友LV 于 2014-12-29 20:13 编辑 在FPGA中实现PID算法,面临着小数的计算,请问大家一般是怎么处理的?
    发表于 12-03 21:59

    PID算法之模糊PID 精选资料推荐

    是专家系统或模糊算法PID 控制算法的简单加和,他是专家系统或者模糊算法PID 控制器参数整定
    发表于 07-19 06:29

    掌握PID算法

    掌握PID算法?要深刻理解反馈机构和执行机构PID算法,不管是原理上,还是代码都比较简单。主要运用在电机控制、开关电源、电源管理芯片等领域
    发表于 09-13 06:20

    PID算法增量式算法

    这里的PID是指控制类的比例-积分-微分算法,而不是进程ID号。PID算法,不管是原理上,还是代码都比较简单。主要运用在电机控制、开关电源
    发表于 09-13 06:06

    PID算法的应用

    这里的PID是指控制类的比例-积分-微分算法,而不是进程ID号。PID算法,不管是原理上,还是代码都比较简单。主要运用在电机控制、开关电源
    发表于 09-13 06:01

    何在嵌入式系统或快速原型构建实现即交即用式部署?

    何在嵌入式系统或快速原型构建实现即交即用式部署?
    发表于 11-22 07:25

    FPGA开发板快速构建一种PID算法

    的实例是使用HLS构建我们的PID算法。使用HLS能够使用浮点或任意精度的定点数。HLS还能通过#pragma 快速的为IP添加通用控制接口(AXI)。在纯
    发表于 10-31 15:53

    pid算法_什么是pid算法

    PID控制器是一种最优控制。本文讲述了增量式PID算法原理与数字PID算法原理与数字PID
    发表于 01-01 11:58 1.1w次阅读
    <b class='flag-5'>pid</b><b class='flag-5'>算法</b>_什么是<b class='flag-5'>pid</b><b class='flag-5'>算法</b>

    基于FPGA的模糊PID控制算法的研究及实现

    基于FPGA的模糊PID控制算法的研究及实现-2009。
    发表于 04-05 10:39 20次下载

    快速浮_定点PID控制器FPGA的研究与实现

    快速浮_定点PID控制器FPGA的研究与实现
    发表于 05-11 11:30 20次下载

    基于模糊自适应PID算法快速充电系统设计_孙莉莉

    基于模糊自适应PID算法快速充电系统设计_孙莉莉
    发表于 01-13 21:36 1次下载

    一种基于FPGA的直扩系统快速捕获算法_杨峰

    一种基于FPGA的直扩系统快速捕获算法_杨峰
    发表于 03-19 11:46 0次下载

    何在MATLAB中开发基于像素的视频和图像处理算法

    此讲座将结合新产品的特性,重点介绍如何在MATLAB®中开发基于像素流的视频和图像处理的算法,并通过HDL代码产生的技术快速FPGA上实现。你将了解到:如
    的头像 发表于 08-29 06:08 2622次阅读
    如<b class='flag-5'>何在</b>MATLAB中开发基于像素的视频和图像处理<b class='flag-5'>算法</b>

    FPGA实现PID控制算法

    相信大家对于PID控制算法,都不感到陌生了,平衡车就是靠它平衡起来的,还有飞控的平衡算法也是它,以及FOC中的闭环控制中也是用的它,它不仅简单,而且易于理解。那么本篇文章将简要介绍一下算法
    的头像 发表于 05-19 16:40 1210次阅读
    <b class='flag-5'>FPGA</b>实现<b class='flag-5'>PID</b>控制<b class='flag-5'>算法</b>