Software implementation of the IIR filter in the information-measuring channel

Information about the state of the environment or, for example, a certain control object can be obtained by measuring the current values ​​of parameters characterizing certain properties of the environment or object. To receive, process and transmit such information by technical means, the value of the measured parameter must be converted by automatic measuring devices into a signal of measuring information. To do this, they implement the information-measuring channel ( IIC ) as a set of technical means, each of which will perform its specific function, ranging from the perception of the measured value to the receipt of measuring information in a form that is convenient for human perception or for further processing. And everything is good, but here along the path of the information to the useful signal y (t) of the measuring information, the interference e (t) is superimposed - a random function of time that can simulate both the random error of the measuring transducer and electrical pickups in the connecting wires and random pulsations measured parameter, and other factors.

On this basis, there arises the problem of primary information processing in the SEC - filtering the signal y (t) of the measurement information from random interference e (t). In general, filtering methods are based on the difference in the frequency spectra of the functions y (t) and e (t), and the interference is considered to be more high-frequency.

Synthesis of the optimal implemented filter is a difficult task, which requires the precise specification of the characteristics of the useful signal and interference. Therefore, in practice, the transfer function of the filter is usually specified and limited to parametric synthesis using simple filtering algorithms.

Filtering methods are carried out both at the software level and at the hardware level. For example, in the BMP280 sensor (BOSCH) it is possible to connect an IIR filter at the hardware level, changing the filter coefficient k, [1], as necessary.

IIR filter


Filters with infinite impulse response refer to recursive filters and calculate the output signal based on the values ​​of the previous input and output samples. Theoretically, the impulse response of an IIR filter never reaches zero, so the output is infinite in duration.

In general, the filtering algorithm for a one-dimensional scalar digital filter is written as [2]:

y[n]=T(x[n],x[n1],...,x[nM],y[n1],...,y[nN],n), (one),
where T is a scalar function of one variable.

The function T depends on the current input signal x [n], and previous: M samples of the input signal and N samples of the output signal

The output of the IIR filter is described by a difference equation of the form:

(2)
where x [n], y [n] is the input and output of the filter, respectively, { ak} - a set of direct coefficients, M - the number of direct coefficients, { bk} Is the set of inverse coefficients, N is the number of inverse coefficients.

Applying a z-transform to both sides of equation (2), we get:

(3).

Then the transfer function of the filter will look like this:

(four)

Algorithm for filtering one-dimensional IIR filter


In general, the filtering algorithm for a one-dimensional scalar stationary recursive filter looks like this:

y[n]=T(x[n],y[n1]). (five)

We now write the difference equation for the IIR filter in the form [1]:

(6),
where k is the filter coefficient;
or
y[n]=ay[n1]+bx[n](7),
Where - inverse and direct filter coefficients, respectively.

From (7) it is obvious that when k = 1, the output signal of the filter will repeat the input signal, and as the filter coefficient k increases, the weight of the previous filtered signal goes to 1, and the weight of the measured value goes to 0.

Algorithm (6) is implemented using the example of an absolute atmospheric pressure information channel for the BMP280 sensor, at the software level in the Arduino Software development environment (IDE), Listing 1. The electrical circuitry of the IIC components connections is shown in Fig. 1. A general view of the prototype of the IIC of absolute atmospheric pressure is presented in Fig. 2. The prototype provides the ability to change the filtration coefficient in the range of 1 ... 50 in increments of 1, by rotating the potentiometer knob. On the sign LCD screen, the measured pressure value is displayed (with k = 1) or the filtered value (with k = 2 ... 50), and the value of the filter coefficient k.

Listing 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); } 



Fig. 1 - Electrical wiring diagram of the components of the prototype IIC


Fig. 2 - General view of the prototype of the IIC

Python script for IIR filter research


Listing 2 shows a Python script for examining IIR filters. The filter coefficient k is prescribed in the script. The measured pressure values ​​are sequentially read from the virtual COM port and filtered. The graphical window and the console display the measured and filtered values ​​of the measured parameter in real time. The results of the experiment are recorded by the table in a file, and time graphs of the measured and filtered values ​​are displayed in the graphic window.

Listing 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,   ") 


Experimental results


   : 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,   





findings


The filtering algorithm is very simple in software implementation and, in practice, can be used in the IIC, similar to that considered in this article.
The work was attended by Losikhin DA, s.v. kaf KITiM .

Information sources


  1. BMP280 Digital Pressure Sensor
  2. Infinite impulse response filter

Source: https://habr.com/ru/post/414943/


All Articles