Determinação da densidade do gás a partir dos resultados da medição de pressão e temperatura com sensores Arduino

1. Introdução


A tarefa de medir os parâmetros de uma mistura de gás é generalizada na indústria e no comércio. O problema de obter informações confiáveis ​​ao medir os parâmetros do estado do meio gasoso e suas características usando meios técnicos é resolvido pelos procedimentos de medição adotados nas normas (MVI), por exemplo, ao medir a vazão e a quantidade de gases usando dispositivos de restrição padrão [1] ou turbina, contadores e contadores de rotações e vórtices [2].

A análise periódica de gases nos permite estabelecer uma correspondência entre a mistura real analisada e seu modelo, segundo o qual os parâmetros físico-químicos do gás são levados em consideração no MVI: a composição da mistura de gases e a densidade do gás em condições padrão.
Além disso, o MVI leva em consideração as características termofísicas do gás: densidade sob condições operacionais (pressão e temperatura do gás em que sua vazão ou volume é medido), viscosidade, fator e fator de compressibilidade.

Os parâmetros do estado do gás medidos em tempo real incluem: pressão (pressão diferencial), temperatura, densidade. Para medir esses parâmetros, respectivamente, são utilizados meios de medição: manômetros (manômetros diferenciais), termômetros, densitômetros. A medição da densidade do meio gasoso pode ser medida por métodos de medição diretos ou indiretos. Os resultados dos métodos de medição direta e indireta dependem do erro dos instrumentos de medição e do erro metodológico. Sob condições de operação, os sinais de informações de medição podem ser afetados por ruído significativo, cujo desvio quadrado médio pode exceder o erro instrumental. Nesse caso, uma tarefa urgente é a filtragem eficaz dos sinais de informações de medição.

Este artigo discute o método de medição indireta da densidade do gás em condições operacionais e padrão usando um filtro Kalman.

Modelo matemático para determinar a densidade do gás


Vamos nos voltar aos clássicos e relembrar a equação de estado de um gás ideal [3]. Nós temos:

1. A equação de Mendeleev-Clapeyron:

(1)

onde:

- pressão de gás;

- volume molar;

R é a constante universal de gás,

;

T é a temperatura absoluta, T = 273,16 K.

2. Dois parâmetros medidos:

p - pressão do gás, Pa
t é a temperatura do gás, ° C.

Sabe-se que o volume molar depende do volume de gás V e do número de mols de gás neste volume:

2)

Sabe-se também que

(3)

onde: m é a massa de gás, M é a massa molar de gás.

Dado (2) e (3), reescrevemos (1) na forma:

(4)

Como é sabido, a densidade de uma substância

é igual a:

(5)

De (4) e (5) derivamos a equação para a densidade do gás

:

(6)

e introduza a notação para o parâmetro

, que depende da massa molar da mistura gasosa:

(7)

Se a composição da mistura gasosa não mudar, o parâmetro k é constante.
Portanto, para calcular a densidade do gás, é necessário calcular a massa molar da mistura de gases.

A massa molar de uma mistura de substâncias é definida como a média aritmética da massa molar das frações de massa incluídas na mistura de substâncias individuais.

Tomamos a composição conhecida de substâncias em uma mistura gasosa - no ar, que consiste em:

  • 23% em peso de moléculas de oxigênio
  • 76% em peso de moléculas de nitrogênio
  • 1% em peso de átomos de argônio

As massas molares dessas substâncias atmosféricas serão respectivamente iguais a:

, g / mol.

Calculamos a massa molar do ar como a média aritmética ponderada:



Agora, sabendo o valor da constante

, podemos calcular a densidade do ar de acordo com a fórmula (7), levando em consideração os valores medidos

e t :



Trazendo a densidade do gás para condições normais e padrão


Na prática, as medições das propriedades dos gases são realizadas em diferentes condições físicas e, para garantir a comparação entre diferentes conjuntos de dados, devem ser estabelecidos conjuntos padrão de condições [4].

Condições padrão de temperatura e pressão são as condições físicas estabelecidas pelo padrão, com as quais as propriedades das substâncias que dependem dessas condições são correlacionadas.

Várias organizações estabelecem suas condições padrão, por exemplo: a União Internacional de Química Pura e Aplicada (IUPAC), estabeleceu a definição de temperatura e pressão padrão (STP) no campo da química: temperatura 0 ° C (273,15 K), pressão absoluta 1 bar (Pa); O Instituto Nacional de Padrões e Tecnologia (NIST) define uma temperatura de 20 ° C (293,15 K) e uma pressão absoluta de 1 atm (101,325 kPa), e esse padrão é chamado temperatura e pressão normais (NTP); A Organização Internacional de Padronização (ISO) estabelece condições padrão para o gás natural (ISO 13443: 1996, confirmado em 2013): temperatura 15,00 ° C e pressão absoluta 101,325 kPa.

Portanto, na indústria e no comércio é necessário indicar condições padrão para temperatura e pressão, com relação às quais os cálculos necessários são feitos.

Calculamos a densidade do ar de acordo com a equação (8) sob condições operacionais de temperatura e pressão. De acordo com (6), escrevemos a equação para a densidade do ar em condições padrão: temperatura e pressão absoluta :

(9)

Fazemos o cálculo da densidade do ar reduzida para condições padrão. Dividimos a equação (9) pela equação (6) e escrevemos essa relação para :

(10)

Da mesma forma, obtemos uma equação para calcular a densidade do ar reduzida a condições normais: temperatura e pressão absoluta

:

(11)

Nas equações (10) e (11) usamos os valores dos parâmetros do ar , T e P da equação (8) obtida em condições operacionais.

A implementação da pressão e temperatura do canal de medição


Para resolver muitas tarefas de obtenção de informações, dependendo de sua complexidade, é conveniente criar um protótipo de um sistema futuro baseado em uma das plataformas de microcontroladores, como Arduino, Nucleo, Teensy, etc.

O que poderia ser mais fácil? Vamos criar uma plataforma de microcontrolador para resolver um problema específico - criar um sistema para medir pressão e temperatura, gastar menos, possivelmente, fundos e usar todas as vantagens do desenvolvimento de software no ambiente do Arduino Software (IDE).

Para isso, no nível do hardware, precisaremos de componentes:

  1. Arduino (Uno, ...) - use como programador;
  2. microcontrolador ATmega328P-PU - microcontrolador da futura plataforma;
  3. um ressonador de quartzo de 16 MHz e um par de capacitores de cerâmica de 12 a 22 pF cada (de acordo com as recomendações do fabricante);
  4. um botão de relógio para redefinir o microcontrolador e um pull-up plus power no pino RESET do resistor de 1 kOhm do microcontrolador;
  5. BMP180 - transmissor de temperatura e pressão com interface I2C;
  6. conversor de interface TTL / USB;
  7. consumíveis - fios, solda, placa de circuito, etc.

Um diagrama esquemático da plataforma, levando em consideração as interfaces necessárias: uma interface serial padrão, I2C, e nada mais, é apresentada na Fig. 1


Fig. 1 - Diagrama esquemático de uma plataforma de microcontrolador para a implementação de um sistema de medição de pressão e temperatura

Agora vamos considerar os estágios da implementação de nossa tarefa.

1. Primeiro, precisamos de um programador. Conectamos o Arduino (Uno, ...) ao computador. No ambiente do Arduno Software, no menu, vá para Arquivo-> Exemplos-> 11. No ArdunoISP , chegamos ao programador ArduinoISP, que costuramos no Arduino. Primeiro, no menu Ferramentas, selecione respectivamente Placa, Processador, Carregador, Porta. Depois de baixar o programa ArduinoISP na placa, o nosso Arduino se transforma em programador e está pronto para uso para a finalidade a que se destina. Para fazer isso, no ambiente do Arduno Software, no menu Ferramentas , selecione o item Programador: “Arduino como ISP ”.

2. Conecte o microcontrolador escravo ATmega328P via interface SPI ao programador mestre do Arduino (Uno, ...), Fig. 2. Deve-se notar que anteriormente os bits do registro Low Fuse Byte do microcontrolador ATmega328P estavam em um estado não programado. Vá para o ambiente do Arduno Software e, no menu Ferramentas , selecione o item Burn Loader . Piscando o microcontrolador ATmega328P.


Fig. 2 - Esquema de conexão do microcontrolador ao programador

3. Após o firmware bem-sucedido, o microcontrolador ATmega328P está pronto para instalação na plataforma de microcontroladores desenvolvida (Fig. 3), que é programável e também no Arduino completo (Uno, ...). O programa de polling para o transmissor de pressão e temperatura é mostrado na Listagem 1.


Fig. 3 Sistema de medição de pressão e temperatura

Listagem 1 - Programa de pesquisa de transdutores de pressão e temperatura
#include <SFE_BMP180.h> SFE_BMP180 pressure; double T,P; void setup() { Serial.begin(9600); pressure.begin(); } void loop() { P = getPressure(); Serial.println(P+0.5, 2); Serial.println(T+0.54, 2); delay(1000); } double getPressure(){ char status; status = pressure.startTemperature(); if (status != 0){ delay(status); //    status = pressure.getTemperature(T); if (status != 0){ status = pressure.startPressure(3); if (status != 0){ delay(status); //    status = pressure.getPressure(P,T); if (status != 0){ return(P); } } } } } 


Programa Python para filtrar por canais de temperatura e pressão e obter resultados


O programa Python para o método para determinar a densidade do gás a partir de medições de pressão e temperatura é mostrado na Lista 2. As informações do sistema de medição são exibidas em tempo real.

Listagem 2 - Determinando a densidade do gás a partir de medições de pressão e temperatura
 import numpy as np import matplotlib.pyplot as plt import serial from drawnow import drawnow import datetime, time from pykalman import KalmanFilter #      transition_matrix = [[1, 1, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]] observation_matrix = [[1, 0, 0, 0], [0, 0, 1, 0]] #     initial_state_mean = [101000, 0, 28, 0] #    : #   R, [/(*)] R = 8.314459848 #   M, [/] M = 29.04 # k = M/R, [/(*)] k = M / R # , [K] K = 273.16 # () , [] Pn = 101325 #   #    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 = [] #   1-  l2 = [] #   2-  t1 = [] #    lw1 = [] #    1-  lw2 = [] #    2-  n = [] #     nw = [] #      l1K = [] #    1-  l2K = [] #    2-  ro = [] #     #      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("Pf -   P, ;") print("T - , . ;") print("Tf -   T, . ;") print("ro -  , /^3;") print("\n   \n") print('{0}{1}{2}{3}{4}{5}\n'.format('n'.rjust(3),'P'.rjust(10),'Pf'.rjust(10), 'T'.rjust(10),'Tf'.rjust(10),'ro'.rjust(10))) #     #  #   i = 0 while i < m: n.append(i) nw.append(n[i]) if i >= mw: nw.pop(0) ser.flushInput() #flush input buffer, discarding all its contents line1 = ser.readline().decode('utf-8')[:-1] line2 = ser.readline().decode('utf-8')[:-1] t1.append(time.time()) if line1: l = eval(line1) #l = np.random.normal(l,100.0) l1.append(l) lw1.append(l1[i]) if i >= mw: lw1.pop(0) if line2: l = eval(line2) #l = np.random.normal(l,1.5) l2.append(l) lw2.append(l2[i]) if i >= mw: lw2.pop(0) #------------------------- initial_state_mean = [l1[i],0,l2[i],0] kf1 = KalmanFilter(transition_matrices = transition_matrix, observation_matrices = observation_matrix, initial_state_mean = initial_state_mean) if i == 0: measurements = np.array( [ [l1[i], l2[i]], [initial_state_mean[0], initial_state_mean[2]] ] ) measurements = np.array( [ [l1[i], l2[i]], [l1[i-1], l2[i-1]] ] ) kf1 = kf1.em(measurements, n_iter=2) (smoothed_state_means, smoothed_state_covariances) = kf1.smooth(measurements) l1K.append(smoothed_state_means[0, 0]) l2K.append(smoothed_state_means[0, 2]) #     #ro.append( k * l1K[i]/( l2K[i] + K) ) # ,     ro.append( (k * l1K[i]/( l2K[i] + K)) * (Pn*(l2K[i]+K)/K/l1K[i]) ) # ,     #ro.append( (k * l1K[i]/( l2K[i] + K)) * (Pn*(l2K[i]+K)/(K+20)/l1K[i]) ) print('{0:3d} {1:10.3f} {2:10.3f} {3:10.3f} {4:10.3f} {5:10.3f}'. format(n[i],l1[i],l1K[i],l2[i],l2K[i],ro[i])) i += 1 ser.close() 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): out_file.write('{0:3d} {1:10.3f} {2:10.3f} {3:10.3f} {4:10.3f} {5:10.3f}\n'. format(n[i],l1[i],l1K[i],l2[i],l2K[i],ro[i])) #    out_file.close() now = datetime.datetime.now() #    #  plt.figure('') plt.plot( n, l1, "b-", n, l1K, "r-") plt.ylabel(r'$, $') plt.xlabel(r'$ \ $' + '; (  : {:.6f}, c)'.format(Ts)) plt.title("BMP180\n(" + now.strftime("%d-%m-%Y %H:%M") + ")") plt.grid(True) plt.figure('') plt.plot( n, l2, "b-", n, l2K, "r-") plt.ylabel(r'$, \degree $') plt.xlabel(r'$ \ $' + '; (  : {:.6f}, c)'.format(Ts)) plt.title("BMP180\n(" + now.strftime("%d-%m-%Y %H:%M") + ")") plt.grid(True) plt.figure(' ') plt.plot( n, ro, "r-") plt.ylabel(r'$ , /^3$') plt.xlabel(r'$ \ $' + '; (  : {:.6f}, c)'.format(Ts)) plt.title("BMP180\n(" + now.strftime("%d-%m-%Y %H:%M") + ")") plt.grid(True) plt.show() 


Os resultados do cálculo são apresentados listando e Fig. 4, 5, 6.

Interface do usuário e tabela de resultados de cálculo
   : 33    : 6  : COM6 : n -  , ; P - , ; Pf -   P, ; T - , . ; Tf -   T, . ; ro -  , /^3;     n P Pf T Tf ro 0 101141.000 101141.000 28.120 28.120 1295.574 1 101140.000 101140.099 28.190 28.183 1295.574 2 101140.000 101140.000 28.130 28.136 1295.574 3 101141.000 101140.901 28.100 28.103 1295.574 4 101140.000 101140.099 28.100 28.100 1295.574 5 101141.000 101140.901 28.110 28.109 1295.574 6 101141.000 101141.000 28.100 28.101 1295.574 7 101139.000 101139.217 28.100 28.100 1295.574 8 101138.000 101138.099 28.090 28.091 1295.574 9 101137.000 101137.099 28.100 28.099 1295.574 10 101151.000 101149.028 28.100 28.100 1295.574 11 101136.000 101138.117 28.110 28.109 1295.574 12 101143.000 101142.052 28.110 28.110 1295.574 13 101139.000 101139.500 28.100 28.101 1295.574 14 101150.000 101148.463 28.110 28.109 1295.574 15 101154.000 101153.500 28.120 28.119 1295.574 16 101151.000 101151.354 28.110 28.111 1295.574 17 101141.000 101142.391 28.130 28.127 1295.574 18 101141.000 101141.000 28.120 28.121 1295.574 19 101142.000 101141.901 28.110 28.111 1295.574 20 101141.000 101141.099 28.120 28.119 1295.574 21 101142.000 101141.901 28.110 28.111 1295.574 22 101146.000 101145.500 28.120 28.119 1295.574 23 101144.000 101144.217 28.130 28.129 1295.574 24 101142.000 101142.217 28.130 28.130 1295.574 25 101142.000 101142.000 28.140 28.139 1295.574 26 101142.000 101142.000 28.130 28.131 1295.574 27 101146.000 101145.500 28.150 28.147 1295.574 28 101142.000 101142.500 28.190 28.185 1295.574 29 101146.000 101145.500 28.230 28.225 1295.574 30 101146.000 101146.000 28.230 28.230 1295.574 31 101146.000 101146.000 28.220 28.221 1295.574 32 101150.000 101149.500 28.210 28.211 1295.574   : 6.464, c   : 0.201998, c     68_count.txt 



Fig. 4 - resultados da medição (vermelha) e filtração (azul) da pressão


Fig. 5 - resultados da medição (vermelho) e filtração (azul) da temperatura


Fig. 6 - resultados de cálculo da densidade do ar reduzida para condições padrão (temperatura 273,15 K; pressão absoluta 101,325 kPa)

Conclusões


Uma técnica foi desenvolvida para determinar a densidade do gás a partir de medições de pressão e temperatura usando sensores Arduino e software Python.

Links para fontes de informação


  1. GOST 8.586.5-2005. URL
  2. GOST R 8.740 - 2011. URL
  3. Lei do gás ideal. URL
  4. Condições padrão para temperatura e pressão. URL

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


All Articles