# Getting Vario (m/s) from a bmp180

I am building a variometer as a hobbie, this could be a duplicate from an existing question: How to use Kalman filter for altitude prediction based on barometer data? .

Details follow:

I have a https://es.wikipedia.org/wiki/NodeMCU running http://www.micropython.org/ , it works nice and I have attached a BMP180 barometric pressure sensor, so I can retrieve: temperature, pressure and altitude, however, while the sensor is fixed in my desk and if I read from three seconds I can get values that range from (982.409 to 983.956 ) in terms of altitude, see the log: https://pastebin.com/C3RbuyDn . So there is an error margin of more than 1 meter .

I would like to use it as a variometer for paragliding, and I only have the pressure sensor, I read it is better to combile with a magnetic sensor, however I want to keep it simple, so it is possible to have an accurate variometer with just the pressure sensor and some algorithms behind and off course with no lag ( no more than 1 second ) ?

Is there any existent algorithm for getting the variation (m/s) with just one variable (altitute) and also considering this chip report the altitude ?

Please look at the data referenced in pastebin .

If you add an accelerometer to the project, a Kalman filter can give a good estimation of vertical speed.

With only a barometric sensor, I don't think it's possible to reduce the lag below 1 second.

import numpy as np
import matplotlib.pyplot as plt
import random

from filterpy.kalman import KalmanFilter
from filterpy.common import Q_discrete_white_noise

random.seed(65537)

# Standard deviation of simulated sensor data
std_a = 0.075
std_h = 0.42

# Earth gravity
g_n = 9.80665

# Sensor sample period, s
dt = 0.05

kf1 = KalmanFilter(dim_x=2, dim_z=1)
kf1.H = np.array([[1, 0]])
kf1.F = np.array([[1, dt], [0, 1]])

kf2 = KalmanFilter(dim_x=3, dim_z=2)
kf2.H = np.array([[1, 0, 0], [0, 0, 1]])
kf2.F = np.array([[1, dt, dt * dt * 0.5], [0, 1, dt], [0, 0, 1]])

# initial process covariance
kf1.P = np.array([[1, 0], [0, 0.01]])
kf2.P = np.array([[std_h * std_h, 0, 0], [0, 0.0001, 0], [0, 0, std_a * std_a]])

# Process noise matrix
std = 0.0039
var = std * std
kf1.Q = Q_discrete_white_noise(dim=2, dt=dt, var=0.0625)
kf2.Q = Q_discrete_white_noise(dim=3, dt=dt, var=var)

# Measurement covariance
kf1.R *= np.array([[std_h * std_h]])
kf2.R *= np.array([[std_h * std_h, 0], [0, std_a * std_a]])

n = 300
r_n = 1.0 / n

t = np.zeros(n)
h_sim = np.zeros(n)
v_sim = np.zeros(n)
a_sim = np.zeros(n)
measured_h = np.zeros(n)
measured_a = np.zeros(n)
v_est_kf1 = np.zeros(n)
v_est_kf2 = np.zeros(n)

v0 = 0
v = v0
h = 0

for i in range(n):
t[i] = (i * dt)
a = 1.0 / 32 * g_n * np.sin(4 * np.pi * i * r_n)
a_sim[i] = (a)
v += a * dt
v_sim[i] = v
h += v * dt + (a * dt * dt) / 2
h_sim[i] = h
measured_a[i] = a + random.gauss(0, std_a)
measured_h[i] = h + random.gauss(0, std_h)

# Compute the speed estimations

for i in range(n):
kf1.predict()
kf1.update(np.array([measured_h[i]]))
v_est_kf1[i] = kf1.x[1]

kf2.predict()
kf2.update(np.array([[measured_h[i]], [measured_a[i]]]))
v_est_kf2[i] = kf2.x[1]

# Plot the results

plt.figure(1, figsize=(8, 12), dpi=80)

plt.subplot(311)
plt.axis([0, n * dt, -0.75, 0.75])
plt.plot(t, measured_a, 'y+')
plt.plot(t, a_sim, 'r')
plt.title('Vertical acceleration - gravity, m/s^2')
plt.legend(('Measured', 'True (simulation)'), loc='best')

plt.subplot(312)
plt.axis([0, n * dt, -1, 7])
plt.plot(t, measured_h, 'c+')
plt.plot(t, h_sim, 'b')
plt.title('Altitude, m')
plt.legend(('Measured', 'True (simulation)'), loc='best')

plt.subplot(313)
plt.axis([0, n * dt, -0.5, 1.0])
plt.plot(t, v_sim, 'b')
plt.plot(t, v_est_kf1, 'r')
plt.plot(t, v_est_kf2, 'c')
plt.title('Vertical speed, m/s')
plt.legend(('True (simulation)', 'Kalman filter (1 sensor)', 'Kalman filter (2 sensors)'), loc='best')

plt.savefig('kalman_vsi.svg')
plt.show()


After some experiments with simulated sensor data, I wrote an Android app that uses smartphone sensors. Source code on GitHub