Skip to content

Instantly share code, notes, and snippets.

@Alexivia
Last active August 26, 2023 21:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Alexivia/432b14eac5c17ff57127b27b49db76bc to your computer and use it in GitHub Desktop.
Save Alexivia/432b14eac5c17ff57127b27b49db76bc to your computer and use it in GitHub Desktop.
Calculate and Plot Reading of a Water Well Sensor
"""
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