Last active
August 26, 2023 21:37
-
-
Save Alexivia/432b14eac5c17ff57127b27b49db76bc to your computer and use it in GitHub Desktop.
Calculate and Plot Reading of a Water Well Sensor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Calculate and Plot Reading of a Water Well Sensor | |
Simple software made for aiding in calculating the values that an analog voltage sensor will read from a series resistor | |
in a water column height sensor with a constant current output. The analog sensor happened to provide its output value | |
in percentage to the web API. | |
Used for a particular setup where a Shelly 2PM + AddOn Plus was reading the voltage of the resistor. | |
Author: Alexandre Vieira, 2023 | |
""" | |
import numpy as np | |
from matplotlib import pyplot as plt | |
from scipy import interpolate | |
if __name__ == "__main__": | |
RESISTOR = 510 # Ohm | |
RESISTOR_MAX_POWER = 0.25 # Watt | |
PROBE_CURRENT_MIN = 4e-3 # Ampere | |
PROBE_CURRENT_MAX = 20e-3 # Ampere | |
PROBE_HEIGHT_MIN = 0 # mH2O | |
PROBE_HEIGHT_MAX = 4 # mH2O | |
PROBE_HEIGHT_OFFSET = 20e-2 # meter | |
SENSOR_VOLTAGE_MIN = 0 # Volt | |
SENSOR_VOLTAGE_MAX = 10 # Volt | |
WELL_DIAMETER = 1.5 # meter | |
calc_curr = lambda height: np.interp( | |
height, | |
[ | |
PROBE_HEIGHT_MIN + PROBE_HEIGHT_OFFSET, | |
PROBE_HEIGHT_MAX + PROBE_HEIGHT_OFFSET, | |
], | |
[PROBE_CURRENT_MIN, PROBE_CURRENT_MAX], | |
left=PROBE_CURRENT_MIN, | |
right=PROBE_CURRENT_MAX, | |
) | |
calc_volt = lambda curr: RESISTOR * curr | |
calc_pow = lambda curr: RESISTOR * curr * curr | |
calc_perc_1 = lambda volt: np.interp( | |
volt, [SENSOR_VOLTAGE_MIN, SENSOR_VOLTAGE_MAX], [0, 100] | |
) | |
calc_perc_2 = interpolate.interp1d( | |
[SENSOR_VOLTAGE_MIN, SENSOR_VOLTAGE_MAX], [0, 100], fill_value="extrapolate" | |
) | |
calc_perc = calc_perc_2 # using second method to allow extrapolation | |
calc_vol = ( | |
lambda height: np.pi * (WELL_DIAMETER / 2) ** 2 * height | |
) # assumes meters as input, thus result in cubic meters | |
test_heights = np.linspace(0, 2.5, 100) | |
current_values = calc_curr(test_heights) | |
voltage_values = calc_volt(current_values) | |
power_values = calc_pow(current_values) | |
perc_values = calc_perc(voltage_values) | |
vol_values = calc_vol(test_heights) | |
def plot_in_subplots(): | |
fig, axs = plt.subplots(3, 1) | |
axs[0].plot(test_heights, perc_values) | |
axs[0].set_xlabel("Altura Água [m]") | |
axs[0].set_ylabel("Medida Shelly [%]") | |
axs[0].grid(True) | |
axs[1].plot(test_heights, power_values) | |
axs[1].set_xlabel("Altura Água [m]") | |
axs[1].set_ylabel("Potência Resistência [W]") | |
axs[1].hlines( | |
y=[RESISTOR_MAX_POWER, RESISTOR_MAX_POWER / 2], | |
xmin=test_heights.min(), | |
xmax=test_heights.max(), | |
linewidth=2, | |
color=["r", "orange"], | |
linestyle="--", | |
) | |
axs[1].grid(True) | |
axs[2].plot(test_heights, vol_values * 1e3) # m3 to l | |
axs[2].set_xlabel("Altura Água [m]") | |
axs[2].set_ylabel("Volume [l]") | |
axs[2].grid(True) | |
fig.tight_layout() | |
plt.show() | |
def plot_splines(): | |
fig, ax1 = plt.subplots() | |
ax2 = ax1.twinx() | |
ax3 = ax1.twinx() | |
fig.subplots_adjust(right=0.85) | |
ax3.spines.right.set_position(("axes", 1.1)) | |
fig.set_figwidth(12) | |
fig.set_figheight(7) | |
(h1,) = ax1.plot(test_heights, perc_values, "b-", label="Medida Shelly") | |
ax1.set_ylabel("Medida Shelly [%]") | |
(h2,) = ax2.plot(test_heights, power_values, "g-", label="Potência Resistência") | |
ax2.set_ylabel("Potência Resistência [W]") | |
h2_e1 = ax2.hlines( | |
y=RESISTOR_MAX_POWER / 2, | |
xmin=test_heights.min(), | |
xmax=test_heights.max(), | |
linewidth=2, | |
color="orange", | |
linestyle="--", | |
label="Potência Tolerável", | |
) | |
h2_e2 = ax2.hlines( | |
y=RESISTOR_MAX_POWER, | |
xmin=test_heights.min(), | |
xmax=test_heights.max(), | |
linewidth=2, | |
color="r", | |
linestyle="--", | |
label="Potência Máxima", | |
) | |
(h3,) = ax3.plot( | |
test_heights, vol_values * 1e3, "c-", label="Volume" | |
) # m3 to l | |
ax3.set_ylabel("Volume [l]") | |
ax1.set_xlabel("Altura Água [m]") | |
ax1.grid(visible=True, which="major", linestyle="-") | |
ax1.minorticks_on() | |
ax1.grid(visible=True, which="minor", linestyle=":") | |
ax1.legend(handles=[h1, h2, h3, h2_e1, h2_e2], loc=(0.1, 0.6)) | |
plt.show() | |
plot_splines() # select which plotting method works best for you |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment