Determination of gas density from the results of measuring pressure and temperature with Arduino sensors

Introduction


The task of measuring the parameters of a gas mixture is widespread in industry and commerce. The problem of obtaining reliable information when measuring the parameters of the state of the gas environment and its characteristics with the help of technical means is resolved by standard measurement techniques (MVI), for example, when measuring the flow and amount of gases using standard narrowing devices [1], or using turbine, rotary and vortex flowmeters and counters [2].

Periodic gas analysis allows to establish the correspondence between the actual mixture being analyzed and its model, according to which the physicochemical parameters of the gas are taken into account in the MVI: the composition of the gas mixture and the density of the gas under standard conditions.
MVI also takes into account the thermophysical characteristics of the gas: the density at the operating conditions (pressure and temperature of the gas at which measurement of its flow or volume is performed), viscosity, factor and compressibility factor.

The parameters of gas state measured in real time include pressure (pressure differential), temperature, density. Means of measuring equipment are used to measure these parameters: manometers (differential pressure gauges), thermometers, and density meters. Measurement of the density of the gas medium can be measured directly or indirectly by measurement methods. The results of both direct and indirect measurement methods depend on the error of the measuring instrument and the methodical error. Under operating conditions, the measurement information signals may be subject to significant noise, the standard deviation of which may exceed the instrumental error. In this case, the actual task is the effective filtering of measurement information signals.

This article discusses the method of indirect measurement of gas density under operating and standard conditions using the Kalman filter.

Mathematical model for determining gas density


Let us turn to the classics and recall the equation of state of an ideal gas [3]. We have:

1. The Mendeleev-Clapeyron equation:

(one),

Where:

- gas pressure;

- molar volume;

R is the universal gas constant,

;

T is the absolute temperature, T = 273.16 K.

2. Two measured parameters:

p - gas pressure, Pa
t is the gas temperature, ° .

It is known that the molar volume depends on the volume of gas V and the number of moles of gas in this volume:

(2)

It is also known that

(3)

where: m is the mass of a gas, M is the molar mass of a gas.

Given (2) and (3), we rewrite (1) in the form:

(four).

As is known, the density of matter

equals:

(five).

From (4) and (5) we derive the equation for the gas density

:

(6)

and enter the parameter designation

which depends on the molar mass of the gas mixture:

(7).

If the composition of the gas mixture does not change, then the parameter k is constant.
So, to calculate the gas density, it is necessary to calculate the molar mass of the gas mixture.

The molar mass of the mixture of substances is determined as the arithmetic average weighted molar mass of the mass fractions included in the mixture of individual substances.

We take the known composition of substances in the gas mixture - in the air, which consists of:


The molar masses of these air substances will be respectively equal to:

g / mol.

Calculate the molar mass of air, as the weighted average:



Now, knowing the value of a constant

, we can calculate the air density by the formula (7) taking into account the measured values

and t :



Reducing gas density to normal, standard conditions


In practice, measurements of the properties of gases are carried out in different physical conditions, and standard sets of conditions should be established to provide a comparison between different data sets [4].

Standard conditions for temperature and pressure are the physical conditions established by the standard to which properties of substances are correlated, depending on these conditions.

Various organizations set their standard conditions, for example: the International Union of Pure and Applied Chemistry (IUPAC), established the definition of standard temperature and pressure (STP) in the field of chemistry: temperature 0 ° C (273.15 K), absolute pressure 1 bar (Pa); The National Institute of Standards and Technology (NIST) sets a temperature of 20 ° C (293.15 K) and an absolute pressure of 1 atm (101.325 kPa), and this standard is called the normal temperature and pressure (NTP); The International Organization for Standardization (ISO) establishes standard conditions for natural gas (ISO 13443: 1996, confirmed in 2013): a temperature of 15.00 ° C and an absolute pressure of 101.325 kPa.

Therefore, in industry and commerce it is necessary to specify the standard conditions for temperature and pressure, relative to which and to carry out the necessary calculations.

We calculate the air density by equation (8) under the working conditions of temperature and pressure. In accordance with (6), we write the equation for air density under standard conditions: temperature and absolute pressure :

(9).

We calculate the air density, reduced to standard conditions. We divide equation (9) into equation (6) and write this ratio for :

(ten).

In a similar way, we obtain the equation for calculating the density of air, reduced to normal conditions: temperature and absolute pressure

:

(eleven).

In equations (10) and (11) we use the values ​​of air parameters , T and P from equation (8), obtained under operating conditions.

The implementation of the measuring channel pressure and temperature


To solve many problems of obtaining information, depending on their complexity, it is convenient to create a prototype of a future system based on one of the microcontroller platforms such as Arduino, Nucleo, Teensy, and others.

What could be easier? Let's make a microcontroller platform for solving a specific task - creating a system for measuring pressure and temperature, spending less, possibly, means, and using all the advantages of developing software in the Arduino Software (IDE) environment.

For this, at the hardware level, we need the components:

  1. Arduino (Uno, ...) - use as a programmer;
  2. ATmega328P-PU microcontroller - a microcontroller of the future platform;
  3. a 16 MHz crystal oscillator and a pair of ceramic capacitors of 12-22 pF each (as recommended by the manufacturer);
  4. clock button to reset the microcontroller and pull-up plus power to the RESET pin of the microcontroller 1 kΩ resistor;
  5. BMP180 - temperature and pressure measuring transducer with I2C interface;
  6. TTL / USB interface converter;
  7. consumables - wires, solder, circuit board, etc.

A schematic diagram of the platform, taking into account the necessary interfaces: standard serial interface, I2C, and nothing more, is presented in Fig. one.


Fig. 1 - Schematic diagram of the microcontroller platform for the implementation of a system for measuring pressure and temperature

Now consider the stages of our task.

1. First, we need a programmer. We connect Arduino (Uno, ...) to the computer. In the Arduno Software environment, from the menu along File-> Examples-> 11. ArdunoISP get to the programmer programmer ArduinoISP, which we sew in Arduino. Previously, from the Tools menu, select, respectively, the board, processor, bootloader, port. After loading the ArduinoISP program into the board, our Arduino turns into a programmer and is ready for use as intended. To do this, in the Arduno Software environment, in the Tools menu, select the Programmer item : “Arduino as ISP ”.

2. We connect via the SPI interface the slave microcontroller ATmega328P to the Arduino master programmer (Uno, ...), fig. 2. It should be noted that the pre-bits of the ATmega328P microcontroller's Low Fuse Byte register were set to the unprogrammed state. Go to the Arduno Software environment and from the Tools menu, select the Write Loader item. We are flashing the ATmega328P microcontroller.


Fig. 2 - Wiring diagram of the microcontroller to the programmer

3. After successful firmware, the ATmega328P microcontroller is ready for installation on the developed microcontroller platform (Fig. 3), which we program as well as the full Arduino (Uno, ...). A survey program for a pressure and temperature transmitter is shown in Listing 1.


Fig. 3 Pressure and temperature measurement system

Listing 1 - Interrogator of the pressure and temperature transmitter
#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); } } } } } 


Python program for filtering by temperature and pressure channels, and getting results


The Python program for determining gas density from pressure and temperature measurements is shown in Listing 2. Information from the measurement system is displayed in real time.

Listing 2 - Determination of gas density from pressure and temperature measurements
 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() 


The calculation results are presented in listing and fig. 4, 5, 6.

User interface and calculation results table
   : 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 - measurement results (red) and filtration (blue) pressure


Fig. 5 - measurement results (red) and filtration (blue) temperature


Fig. 6 - results of calculation of air density, reduced to standard conditions (temperature 273.15 K; absolute pressure 101.325 kPa)

findings


A method has been developed for determining the density of a gas from the results of pressure and temperature measurements using Arduino sensors and Python software.

References to sources of information


  1. GOST 8.586.5-2005. URL
  2. GOST R 8.740 - 2011. URL
  3. Ideal gas law. URL
  4. Standard conditions for temperature and pressure. URL

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


All Articles