Implementação de software do filtro IIR no canal de medição de informações

Informações sobre o estado do ambiente ou, por exemplo, um determinado objeto de controle podem ser obtidas medindo os valores atuais dos parâmetros que caracterizam certas propriedades do ambiente ou objeto. Para receber, processar e transmitir essas informações por meios técnicos, o valor do parâmetro medido deve ser convertido por dispositivos de medição automáticos em um sinal de informações de medição. Para fazer isso, implemente o canal de medição de informações ( CII ), como uma combinação de meios técnicos, cada um dos quais cumprirá sua função específica, começando na percepção do valor medido e terminando com o recebimento das informações de medição de uma forma conveniente para a percepção humana ou para seu processamento posterior. E tudo ficaria bem, mas ao longo do caminho da informação, a interferência e (t) é sobreposta ao sinal útil y (t) da informação de medição - uma função aleatória do tempo que pode simular o erro aleatório do transdutor de medição, captadores elétricos nos fios de conexão e ondulações aleatórias parâmetro medido e outros fatores.

Com base nisso, surge o problema do processamento primário de informações na CII - filtrando o sinal y (t) das informações de medição da interferência aleatória e (t). Basicamente, os métodos de filtragem são baseados na diferença nos espectros de frequência das funções y (t) ee (t), e a interferência é considerada mais alta frequência.

A síntese do filtro ideal implementado é uma tarefa complexa, cuja solução requer a especificação exata das características do sinal e da interferência úteis. Portanto, na prática, a função de transferência do filtro é geralmente especificada e limitada à síntese paramétrica usando algoritmos de filtragem simples.

Os métodos de filtragem são realizados no nível do software e no nível do hardware. Por exemplo, no sensor BMP280 (BOSCH), é possível conectar um filtro IIR no nível do hardware, alterando o coeficiente do filtro k, se necessário, [1].

Filtro IIR


Os filtros com resposta de impulso infinito são filtros recursivos e calculam o sinal de saída com base nos valores das amostras anteriores de entrada e saída. Teoricamente, a resposta de impulso de um filtro IIR nunca chega a zero; portanto, a saída é infinita em duração.

Em geral, escrevemos o algoritmo para filtrar um filtro digital escalar unidimensional como [2]:

(1)
onde T é uma função escalar de uma variável.

A função T depende do sinal de entrada atual x [n] e anterior: M amostras do sinal de entrada e N amostras do sinal de saída

A saída do filtro IIR é descrita por uma equação de diferença da forma:

2)
onde x [n], y [n] é a entrada e a saída do filtro, respectivamente, { } É o conjunto de coeficientes diretos, M é o número de coeficientes diretos, { } É um conjunto de coeficientes inversos, N é o número de coeficientes inversos.

Aplicando a transformação z em ambos os lados da equação (2), obtemos:

(3)

Em seguida, a função de transferência do filtro ficará assim:

4)

Algoritmo para filtrar um filtro IIR unidimensional


Em termos gerais, o algoritmo de filtragem para um filtro recursivo estacionário escalar unidimensional se parece com:

. (5)

Agora, escrevemos a equação da diferença para o filtro IIR no formato [1]:

(6)
onde k é o coeficiente de filtro;
ou
(7)
onde São os coeficientes de filtro inverso e direto, respectivamente.

A partir de (7), é óbvio que em k = 1 o sinal de saída do filtro repetirá a entrada e, à medida que o coeficiente de filtro k aumenta, o peso do sinal filtrado anterior tende a 1 e o peso do valor medido tende a 0.

O algoritmo (6) é implementado como um exemplo do canal de medição de informações de pressão atmosférica absoluta para o sensor BMP280, no nível do software no ambiente de desenvolvimento do Software Arduino (IDE), lista 1. O diagrama de conexão elétrica dos componentes da CII é mostrado na Fig. 1. A vista geral do protótipo da pressão atmosférica absoluta da CII é apresentada na Fig. 2. O protótipo fornece a capacidade de alterar o coeficiente do filtro na faixa de 1 a 50 em incrementos de 1, girando o botão do potenciômetro. O sinal do visor de cristal líquido mostra o valor da pressão medida (para k = 1) ou o valor filtrado (para k = 2 ... 50) e o coeficiente do filtro k.

Listagem 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 - Diagrama de fiação dos componentes do protótipo CII


Fig. 2 - Visão geral do protótipo CII

Script Python para pesquisar filtros IIR


A Listagem 2 mostra um script Python para examinar os filtros IIR. O coeficiente de filtro k está escrito no script. Os valores de pressão medidos são lidos sequencialmente na porta COM virtual e filtrados. Os valores medidos e filtrados do parâmetro medido em tempo real são exibidos na janela gráfica e no console. Os resultados do experimento são registrados pela tabela em um arquivo e as linhas do tempo dos valores medidos e filtrados são exibidas na janela de desenho.

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


Resultados da Experiência


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





Conclusões


O algoritmo de filtragem acima é muito simples na implementação de software e, na prática, pode ser usado em IICs semelhantes às discutidas neste artigo.
Losikhin D.A., s.v. café CITYM .

Fontes de informação


  1. Sensor de pressão digital BMP280
  2. Filtro de resposta ao impulso infinito

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


All Articles