IIR滤波器在信息测量通道中的软件实现

关于环境或例如某个控制对象的状态的信息可以通过测量表征环境或对象的某些特性的参数的当前值来获得。 为了通过技术手段接收,处理和传输此类信息,必须通过自动测量设备将测量参数的值转换为测量信息信号。 为此,将信息测量通道( IIC )作为技术手段的组合来实现,每种方法都将履行其特定的功能,从对测量值的感知开始,到最终以易于人类感知或对其进行进一步处理的形式接收测量信息为止。 一切都会好起来,但是沿着信息的路径,干扰e(t)会叠加在测量信息的有用信号y(t)上 -时间的随机函数,可以模拟测量传感器,连接线中的电拾取器和随机波动的随机误差测量参数和其他因素。

基于此,IIC中信息的主要处理会出现问题-从随机干扰e(t)中过滤测量信息的信号y(t)。 基本上,滤波方法基于函数y(t)和e(t)频谱的差异,并且干扰被认为是更高频率的。

所实现的最佳滤波器的综合是一项复杂的任务,其解决方案需要准确说明有用信号和干扰的特性。 因此,在实践中,通常指定滤波器的传递函数并将其限制为使用简单滤波算法的参数合成。

过滤方法在软件级别和硬件级别均执行。 例如,在BMP280(BOSCH)传感器中,可以在硬件级别连接IIR滤波器,并在必要时更改滤波器系数k [1]。

IIR滤波器


具有无限脉冲响应的滤波器是递归滤波器,并根据先前输入和输出采样的值来计算输出信号。 从理论上讲,IIR滤波器的脉冲响应永远不会达到零,因此输出的持续时间是无限的。

通常,我们将用于过滤一维标量数字滤波器的算法写为[2]:

y[n]=Tx[n]x[n1]...x[nM]y[n1]...y[nN]n,(1),
其中T是一个变量的标量函数。

函数T取决于当前输入信号x [n],以及前一个:输入信号的M个样本 和N个输出信号样本

IIR滤波器的输出由以下形式的差分方程描述:

(2)
其中x [n],y [n]分别是滤波器的输入和输出,{ ak}是一组直接系数,M是一组直接系数,{ bk}是一组反系数,N是反系数的数量。

将z变换应用于方程式(2)的两边,我们获得:

(3)。

然后,过滤器的传递函数将如下所示:

(4)

一维IIR滤波器的滤波算法


一般而言,一维标量固定递归滤波器的滤波算法如下所示:

y[n]=Tx[n]y[n1]。 (5)

现在,我们以[1]的形式编写IIR滤波器的差分方程:

(6)
其中k是滤波器系数;

y[n]=ay[n1]+bx[n](7)
在哪里 分别是逆滤波器系数和正滤波器系数。

从(7)可以明显看出,在k = 1时,滤波器的输出信号将重复输入,并且随着滤波器系数k的增加,前一个滤波信号的权重趋于1,而测量值的权重趋于0。

算法(6)在Arduino软件(IDE)开发环境中的软件级别上作为BMP280传感器的绝对大气压力信息测量通道的示例实现,清单1。IIC组件的电气连接图如图2所示。 图1给出了IIC原型绝对大气压的总体视图。 2.原型可以通过旋转电位计的旋钮在1 ... 50范围内以1为增量更改滤波器系数。 液晶显示屏的符号显示测得的压力值(对于k = 1)或滤波后的值(对于k = 2 ... 50),以及滤波系数k。

清单1
//    () // -  - //https://github.com/orgua/iLib/blob/master/src/i2c.h #include "i2c.h" //https://github.com/orgua/iLib/blob/master/src/i2c_BMP280.h #include "i2c_BMP280.h" //https://github.com/arduino-libraries/LiquidCrystal #include <LiquidCrystal.h> //https://github.com/orgua/iLib/tree/master/examples/i2c_BMP280 BMP280 bmp280; const int rs = 12, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3; //const int rs = PB4, en = PB3, d4 = PD6, d5 = PD5, d6 = PD4, d7 = PD3; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); float pascal_f = 100500; float filter_K = 1; const int analogInPin = A0; //    int sensorValue = 0; //   int outputValue = 0; void setup() { Serial.begin(9600); //Serial.print("Probe BMP280: "); if (bmp280.initialize()) { //Serial.println("Sensor found"); ; } else { Serial.println("Sensor missing"); while (1) {} } bmp280.setEnabled(0); bmp280.triggerMeasurement(); bmp280.setFilterRatio(0); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("measure"); lcd.setCursor(7, 1); lcd.print("Pa"); lcd.setCursor(10, 0); lcd.print("filter"); } void loop() { float temperature; float pascal, hpascal; sensorValue = analogRead(analogInPin); outputValue = map(sensorValue, 0, 1023, 1, 50); filter_K = outputValue; bmp280.awaitMeasurement(); bmp280.getTemperature(temperature); temperature -= 1.7; // bmp280.getPressure(pascal); pascal -= 50;// hpascal = pascal/100.; bmp280.triggerMeasurement(); pascal_f = (pascal_f * (filter_K - 1) + pascal) / filter_K; //(6) Serial.println(pascal_f,0); if(pascal_f < 100000) lcd.setCursor(6, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(pascal_f,0); if(filter_K < 10) lcd.setCursor(13, 1); lcd.print(" "); lcd.setCursor(10, 1); lcd.print(filter_K,1); delay(300); } 



1-IIC原型组件的接线图


2-IIC原型的一般视图

用于研究IIR滤波器的Python脚本


清单2显示了用于检查IIR过滤器的Python脚本。 滤波器系数k写在脚本中。 从虚拟COM端口顺序读取测量的压力值并进行过滤。 实时在图形窗口和控制台上显示测量参数的测量值和滤波值。 实验结果由表格记录在文件中,测量和过滤后的值的时间轴显示在图形窗口中。

清单2
 import numpy as np import matplotlib.pyplot as plt import serial from drawnow import drawnow import datetime, time k = 6.0 #  + 1 filter_K = 1 + k #     def cur_graf(): plt.title("BMP280") plt.ylim( 100450, 100510 ) plt.plot(nw, lw1, "r.-", label='') plt.plot(nw, lw1f, "b.-", label='') plt.legend(loc='best') plt.ylabel(r'$, $') plt.xlabel(r'$ \ $') plt.grid(True) #      def all_graf(): plt.close() fig=plt.figure() ax = fig.add_subplot(111) fig.subplots_adjust(top=0.85) ax.set_title(" BMP280\n" + str(count_v) + "-  " + "(" + now.strftime("%d-%m-%Y %H:%M") + ")") ax.set_ylabel(r'$, $') ax.set_xlabel(r'$ \ $' + '; (  : {:.6f}, c)'.format(Ts)) ax.text(0.95, 0.03, " : " + str(filter_K) + "\n", verticalalignment='bottom', horizontalalignment='right', transform=ax.transAxes, color='black', fontsize=14) plt.plot( n, l1, "r-", label='') plt.plot( n, l1f, "b-", label='') plt.legend(loc='best') plt.grid(True) plt.show() #   #    str_m = input("  : ") m = eval(str_m) #    mw = 16 #    ser = serial.Serial() ser.baudrate = 9600 port_num = input("   : ") ser.port = 'COM' + port_num ser #   try: ser.open() ser.is_open print(" : " + ser.portstr) except serial.SerialException: print("   : " + ser.portstr) raise SystemExit(1) #  l1 = [] #    l1f = [] #     t1 = [] #     lw1 = [] #     lw1f= [] #      n = [] #     nw = [] #      #      filename = 'count.txt' in_file = open(filename,"r") count = in_file.read() count_v = eval(count) + 1 in_file.close() in_file = open(filename,"w") count = str(count_v) in_file.write(count) in_file.close() filename = count + '_' + filename out_file = open(filename,"w") #      print("\n:\n") print("n -  ;") print("P - , ;") print("\n   \n") print('{0}{1}\n'.format('n'.rjust(4),'P'.rjust(10))) #     #  #   #       i = 0 while i < m: n.append(i) nw.append(n[i]) if i >= mw: nw.pop(0) line1 = ser.readline().decode('utf-8')[:-2] t1.append(time.time()) if line1: l1.append(eval(line1)) lw1.append(l1[i]) if i : l1f.append( (l1f[i-1]*(filter_K - 1) + l1[i])/filter_K ) #(6) lw1f.append(l1f[i]) else : l1f.append(l1[i]) lw1f.append(l1f[i]) if i >= mw: lw1.pop(0) lw1f.pop(0) print('{0:4d} {1:10.2f} {2:10.2f}'.format(n[i],l1[i],l1f[i]) ) drawnow(cur_graf) i += 1 #   ser.close() ser.is_open time_tm = t1[m - 1] - t1[0] print("\n  : {0:.3f}, c".format(time_tm)) Ts = time_tm / (m - 1) print("\n  : {0:.6f}, c".format(Ts)) #    print("\n    {}\n".format(filename)) for i in np.arange(0,len(n),1): count = str(n[i]) + "\t" + str(l1[i]) + "\n" out_file.write(count) #    out_file.close() out_file.closed #    now = datetime.datetime.now() #     all_graf() end = input("\n Ctrl-C,   ") 


实验结果


   : 33    : 6  : COM6 : n -  ; P - , ;     n P 0 100490.00 100490.00 1 100488.00 100489.71 2 100487.00 100489.33 3 100488.00 100489.14 4 100488.00 100488.9730 100486.00 100488.14 31 100492.00 100488.70 32 100489.00 100488.74   : 16.028, c   : 0.500875, c     275_count.txt  Ctrl-C,   





结论


上面的过滤算法在软件实现中非常简单,并且在实践中可以与本文中讨论的类似在IIC中使用。
Losikhin D.A.,s.v. 咖啡厅 城市

信息来源


  1. BMP280数字压力传感器
  2. 无限冲激响应滤波器

Source: https://habr.com/ru/post/zh-CN414943/


All Articles