PLC的ST语言实现IIR butterworth低通滤波器

参考 Butterworth Filter Design in C++ – The Code Hound

matlab代码,创建一个fc=0.1的4阶butterworth低通滤波器。

format long

[b,a] = butter(4,0.1,'low')

input1 = [1,2,3,1,2,3,1,2,3,0,0];
output = filter(b,a,input1)

过滤input1的结果为

output =

 Columns 1 through 5:

   3.123897691708262e-05   2.995734755404623e-04   1.454902769105549e-03   4.766674939805153e-03   1.193910293101060e-02

 Columns 6 through 10:

   2.475774743364613e-02   4.492688281346330e-02   7.394998706258429e-02   1.129536864512947e-01   1.626442203690692e-01

 Column 11:

   2.231700886131495e-01

从c++移植到PLC代码。Polynomial最大阶数为10,所以最好是在9阶下使用IIR滤波器。当然8阶就已经够高了,很容易发散了。

TYPE Complex :
STRUCT
    re : LREAL;
    im : LREAL;
END_STRUCT
END_TYPE
//----------------------------
TYPE PolyConstant :
(
	PolyMaxN := 10
);
END_TYPE
//----------------------------
TYPE Polynomial :
STRUCT
    c : ARRAY [0..PolyMaxN-1] OF Complex;
    n : DINT;
END_STRUCT
END_TYPE
//----------------------------
FUNCTION C_Add : Complex
VAR_INPUT  
    a, b : Complex;  
END_VAR  
C_Add.re := a.re + b.re;
C_Add.im := a.im + b.im;
//-----------------------------
FUNCTION C_Div : Complex
VAR_INPUT
    a, b : Complex; // a/b
END_VAR
VAR
    denominator : LREAL; // 分母的模长的平方
END_VAR
// 计算分母的模长的平方
denominator := b.re * b.re + b.im * b.im;

// 计算结果
C_Div.re := (a.re * b.re + a.im * b.im) / denominator;
C_Div.im := (a.im * b.re - a.re * b.im) / denominator;

//-------------------------------
FUNCTION C_Mul : Complex
VAR_INPUT  
    a, b : Complex;  
END_VAR
C_Mul.re := a.re * b.re - a.im * b.im;
C_Mul.im := a.re * b.im + a.im * b.re;

//-------------------------------
FUNCTION P_Poly : Polynomial
VAR_INPUT
    roots : Polynomial;
END_VAR
VAR
    i : DINT;
    factor : Polynomial;
    temp : Polynomial;
END_VAR
temp.c[0].re:=1;
temp.c[0].im:=0;
temp.n := 1;

factor.n := 2;
FOR i:=0 TO (roots.n-1) DO
    factor.c[0].re := -roots.c[i].re;
    factor.c[0].im := -roots.c[i].im;
    factor.c[1].re := 1.0;
    factor.c[1].im := 0.0;
    temp := P_PolyMul(temp,factor);
END_FOR

P_Poly.n := temp.n;
FOR i:=0 TO (temp.n-1) DO
    P_Poly.c[i] := temp.c[temp.n-i-1];
END_FOR

//--------------------------------
FUNCTION P_PolyMul : Polynomial
VAR_INPUT  
    p, q : Polynomial;  
END_VAR  
VAR
    n,i,j : DINT;
END_VAR
n := p.n + q.n - 1;
P_PolyMul.n := n;
FOR i:=0 TO p.n-1 DO
    FOR j:=0 TO q.n-1 DO
        P_PolyMul.c[i+j] := C_Add(P_PolyMul.c[i+j],C_Mul(p.c[i],q.c[j]));
	END_FOR
END_FOR

//---------------------------------
FUNCTION P_Real : Polynomial
VAR_INPUT  
    a : Polynomial;  
END_VAR  
VAR
    i : DINT;
END_VAR
FOR i := 0 TO a.n-1 DO
    P_Real.c[i].re := a.c[i].re;
END_FOR
P_Real.n := a.n;

//---------------------------------
FUNCTION P_RealSum : LREAL
VAR_INPUT  
    a : Polynomial;  
END_VAR  
VAR
    i : DINT;
END_VAR
FOR i := 0 TO a.n-1 DO
    P_RealSum := P_RealSum+ a.c[i].re;
END_FOR


//---------------------------------
FUNCTION_BLOCK IIR_Filter
VAR_INPUT
	inputVal : LREAL;
END_VAR
VAR_OUTPUT
	outputVal : LREAL;
END_VAR
VAR
	b : ARRAY [0..PolyMaxN-1] OF LREAL;
	a : ARRAY[0..PolyMaxN-1] OF LREAL;
    z : ARRAY[0..PolyMaxN-1] OF LREAL;
    ord : DINT;
	i : DINT;
END_VAR
z[0] := inputVal*a[0];
FOR i := 1 TO ord DO
    z[0] := z[0] - z[i]*a[i];
END_FOR
outputVal := z[0]*b[0];
FOR i := 1 TO ord DO
    outputVal := outputVal + z[i]*b[i];
END_FOR
FOR i := 0 TO ord -1 DO
    z[ord-i] := z[ord-(i+1)];
END_FOR

//----IIR_Filter.reset--------
METHOD reset
VAR_INPUT
	inputVal : LREAL := 0;
END_VAR
VAR
	i : DINT;
END_VAR
FOR i := 0 TO ord DO
	z[i] := inputVal;
END_FOR
outputVal := inputVal;

//------IIR_Filter.butter_low_init--------
METHOD butter_low_init
VAR_INPUT
    N : DINT := 4;
    fc : LREAL := 0.1;
    fs : LREAL := 2;
END_VAR
VAR
    i,k : DINT;
    theta : LREAL;
    pa : Polynomial;
    p : Polynomial;
    q : Polynomial;
    nume : Complex;
    deno : Complex;
    _fc : LREAL;
    Gain : LREAL;
    a : Polynomial;
    b : Polynomial;
END_VAR
VAR CONSTANT
    PI : LREAL := 3.141592653589793;
END_VAR
//0.init
pa.n := N;
p.n := N;
q.n := N;
FOR i:= 0 TO N-1 DO
    q.c[i].re := -1;
END_FOR

//1.Find poles of analog filter
FOR i := 0 TO N-1 DO
    k := i+1;
    theta := (2*k-1)*PI/(2*N);
    pa.c[i].re := -SIN(theta);
    pa.c[i].im :=  COS(theta);
END_FOR

//2.Scale Poles in frequency
_fc := fs/PI * TAN(PI*fc/fs);
FOR i:=0 TO pa.n-1 DO
    pa.c[i].re := pa.c[i].re*2*PI*_fc;
    pa.c[i].im := pa.c[i].im*2*PI*_fc;
END_FOR

//3. Find coeffs of digital filter poles and zeros in the z plane
FOR i:=0 TO N-1 DO
    nume.re := 1.0 + pa.c[i].re/(2*fs);
    nume.im :=       pa.c[i].im/(2*fs);
    deno.re := 1.0 - pa.c[i].re/(2*fs);
    deno.im :=     - pa.c[i].im/(2*fs);
    p.c[i] := C_Div(nume,deno);
END_FOR

a := P_Poly(p);
a := P_Real(a);

b := P_Poly(q);

Gain := P_RealSum(a) / P_RealSum(b);

FOR i:= 0 TO b.n-1 DO
    b.c[i].re := b.c[i].re*Gain;
END_FOR

//output
ord := a.n;
FOR i:= 0 TO a.n-1 DO
    THIS^.a[i] := a.c[i].re;
    THIS^.b[i] := b.c[i].re;
END_FOR



//----------------------------
PROGRAM main
VAR
    filter : IIR_Filter;
    init : BOOL;
    i : DINT;
    N : DINT := 4;
    fc : LREAL := 0.1;
END_VAR
VAR
    input : ARRAY [0..10] OF LREAL := [1,2,3,1,2,3,1,2,3];
    output : ARRAY[0..10] OF LREAL;
END_VAR
IF NOT init THEN
    init := TRUE;
    filter.butter_low_init(N,fc,2);
    filter.reset(0);
    FOR i:=0 TO 10 DO
        filter(inputVal:=input[i],outputVal=>output[i]);    
    END_FOR
END_IF

得出结果

比较matlab的结果,正确,误差不大。欢迎修改N和fc参数进行测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/627919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式基础课程配套电机FOC伺服电机开发板AT32F403磁编码IMU姿态

嵌入式基础课程配套电机FOC伺服电机开发板AT32F403磁编码IMU姿态 带你入门嵌入式有二十多年开发经验的老技骨做技术支持整个开发包硬件包括电机2205,支持12V到24V宽输入,配套12V2A电源。包装原理图和PCB嵌入式软件嵌入式基础课程 带你入门嵌入式 电机FO…

免费SSL证书怎么签发

大家都知道SSL证书好,作用大,安全性高,能加权重,等保必须的参考值。但是如何选择合适且正确的证书也是至关重要的,网站更适合单域名证书、多域名证书、泛域名证书、还是多域名通配符证书。 首先大家要清楚&#xff0c…

MATLAB车辆动力学建模 ——《控制系统现代开发技术》

引言 在上这门课之前,我已经用过CasADi 去做过最优化的相关实践,其中每一步迭代主要就是由:对象系统优化求解两部分组成的。这里我们重点介绍 “对象系统”如何去描述 ,因为它是每一步迭代中重要的一环——“优化求解”会获得控制…

Java逐层解析JSON的内存占用分析

哈喽,大家好,我是木头左! 在当今的软件开发世界中,JSON(JavaScript Object Notation)已经成为了数据传输和存储的事实标准。由于其轻量级且易于人类阅读的特点,JSON被广泛用于Web服务、移动应用…

【制作100个unity游戏之26】unity2d横版卷轴动作类游戏5(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言三段攻击攻击设置只对敌人造成伤害限制可以移动攻击问题 角色连续按四下攻击,最后会多a一下问题:站在原地连续攻击野猪,只有第一下攻击野猪才掉血,后面的攻击野猪不掉血源码完结 …

一图流解释Java中线程状态的转换

目录 一.Java中的几大线程状态 二.线程之间的相互转换 ▐ NEW --> RUNNABLE ▐ RUNNABLE <--> WAITING ▐ RUNNABLE <--> Timed Waiting ▐ RUNNABLE<--> BLOCKED ▐ RUNNABLE<-->TERMINATED 一.Java中的几大线程状态 简单来说线程可以处于…

美团小程序mtgsig1.2逆向

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章未…

网络安全等级保护在工业控制系统中的应用

工业控制系统(Industrial Control Systems,ICS)&#xff0c;是由各种自动化控制组件和实时数据采集、监测的过程控制组件共同构成。其组件包括数据采集与监控系统(SCADA)、分布式控制系统(DCS)、可编程逻辑控制器(PLC)、远程终端(RTU)、智能电子设备(IED)&#xff0c;以及确保各…

C语言单向链表、双向链表和循环链表有什么区别?

一、问题 链表分为单向链表、双向链表和循环链表&#xff0c;它们的不同之处是什么呢&#xff1f; 二、解答 &#xff08;1&#xff09;单向链表。 所谓单向链表&#xff0c;就是指数据结点是单向排列的。⼀个单向链表结点由两个域组成&#xff0c;存储在结构体类型中。⼀个域…

从零开始:利用美颜API打造属于你的直播美颜功能

当下&#xff0c;如何在直播中呈现最好的自己&#xff0c;成为了许多主播关心的问题。美颜功能应运而生&#xff0c;帮助主播们在镜头前展现更好的形象。本文将详细介绍如何从零开始&#xff0c;利用美颜API打造属于你的直播美颜功能。 一、认识美颜API 1、什么是美颜API 美…

用wxPython和PyMuPDF将PNG图像合并为PDF文件

在日常工作中,我们经常需要将多个图像文件合并到一个PDF文档中,以便于查看、共享或存档。虽然现有的一些工具可以实现这一功能,但开发一个自定义的GUI工具可以更好地满足特定需求,并提供更好的用户体验。 在本文中,我将介绍如何使用Python、wxPython和PyMuPDF库创建一个简单的…

【java】异常与错误

Throwable包括Error和Expected。 Error Error错误是程序无法处理的&#xff0c;由JVM产生并抛出的。 举例&#xff1a;StackOverflowError \ ThreadDeath Expected Expected异常包括两类&#xff0c;即受检异常(非运行时异常)和非受检异常(运行时异常)&#xff0c;异常往往…

两大DRAM巨头20%产能转给HBM

随着人工智能(AI)需求的激增&#xff0c;全球领先的内存芯片制造商三星(Samsung)和SK海力士(SK Hynix)预计&#xff0c;由于高性能芯片需求不断增长&#xff0c;今年DRAM和高带宽内存(HBM)的价格将保持强劲。据《韩国经济日报》报道&#xff0c;三星和SK海力士已将其超过20%的D…

BUUCTF靶场[MISC]荷兰宽带数据泄露、九连环

[MISC]荷兰宽带数据泄露 考点&#xff1a;查看路由器恢复丢失密码的文件 工具&#xff1a;RouterPassView——路由器密码查看工具 工具链接&#xff1a;https://routerpassview.en.lo4d.com/windows RouterPassView是一款老牌的路由器密码查看器&#xff0c;可以一键获取路…

网络安全从业者“行话”

目录 ​编辑 一、攻击篇 1&#xff0e;攻击工具 2&#xff0e;攻击方法 3&#xff0e;攻击者 二、防守篇 1&#xff0e;软硬件 2&#xff0e;技术与服务 网络安全学习资源分享: 特别声明 一、攻击篇 1&#xff0e;攻击工具 肉鸡 所谓“肉鸡”是一种很形象的比喻&…

JavaScript循环结构

JS循环结构 1 while结构2 for循环3 foreach循环 1 while结构 几乎和JAVA一致 代码 /* 打印99 乘法表 */var i 1;while(i < 9){var j 1;while(j < i){document.write(j"*"i""i*j" ");j;}document.write("<hr/>");i…

win11此电脑右键“属性“选项,无法打开怎么解决?

方法如下&#xff1a; 1. 按【 Win X 】组合键&#xff0c;或【 右键】点击任务栏上的【 Windows开始菜单】&#xff0c;在打开的隐藏菜单项中&#xff0c;选择【 终端管理员】&#xff1b; 2. 用户账户控制窗口&#xff0c;你要允许此应用对你的设备进行更改吗&#xff1f;点…

IT Tools

ChatGpt chatGpt chatgpt vs & vscode工具 Vs Extensions & Remote Development Vs Extensions Remote-SSH VSCode远程连接到Linux并实现免密码登录 Git Graph C cppreference.com cplusplus 镜像站点 用于下载 QT, Ubuntu, 清华镜像站点 CMake Downlo…

【面试必看】MyBatis部分

MyBatis 必读 Mybatis系列全解 MyBatis最全使用指南 MyBatis最全使用指南 1. JDBC java 操作数据库的原始方式就是 JDBC。 但是存在以下问题&#xff1a; 每次操作我们都要创建 connection、Statement 等一些对象&#xff0c;操作完还要关闭、销毁这些对象。 ResultSet …

TSINGSEE青犀智慧校园视频综合管理系统建设方案及平台功能

一、方案背景 智慧校园视频综合管理系统以物联网、云计算、大数据分析等新技术为核心&#xff0c;将基于计算机网络的信息服务融入学校的各个应用与服务领域&#xff0c;实现互联和协作。通过“云边缘计算”构架&#xff0c;在各应用子系统的基础数据层面上&#xff0c;打通上…