Open Tomberer opened 2 years ago
It is certainly possible, but I'm not very familiar with the software calibration to create a new Input with an additional calibration point. If you look at the Atlas Scientific (AS) or Anyleaf code, you will see the AS calibration is stored and calculated on the chip itself, and the Anyleaf calibration is performed with the Anyleaf Python library (which could very well also store/calculate it on the chip, I haven't looked). You're welcome to create a new module with 3 pt calibration for inclusion in the builtin set.
Thanks for the quick response, I'm rather illiterate when it comes to programming so I think I'll stick to just 2 calibration points.
Thanks for all the effort you've put into building this software by the way, I really can't properly express how grateful I am for your work.
I'll take a look at the ADS pH inputs (I didn't create those) and see if a 3 pt could be easily imemented. No guarantees, but if I can get it to work, I'll let you know.
I've created some test code that implements a 3-pt calibration. The 2-pt calibration is from ads1115_analog_ph_ec.py and the 3-pt code I pulled from anyleaf/init.py#L555, referenced by https://www.anyleaf.org/blog/how-to-calibrate-ph-sensors.
def nernst_correction(volt, temp):
"""Apply temperature correction for pH. This provides the voltage as if it were measured at 25C.
Based on the Nernst equation: E = E0 - ln(10) * RT/nF * pH; this gives E = E0 - 0.198 * T * pH.
The correction is a simple ratio of absolute temperature."""
volt_25C = volt * 298 / (temp + 273)
return volt_25C
def lg(pt0: (float, float), pt1: (float, float), pt2: (float, float), v: float) -> float:
"""Compute the result of a Lagrange polynomial of order 3.
Algorithm created from the `P(x)` eq
[here](https://mathworld.wolfram.com/LagrangeInterpolatingPolynomial.html)."""
result = 0.0
x = [pt0[0], pt1[0], pt2[0]]
y = [pt0[1], pt1[1], pt2[1]]
for j in range(3):
c = 1.0
for i in range(3):
if j == i:
continue
c *= (v - x[i]) / (x[j] - x[i])
result += y[j] * c
return result
def convert_volt_to_ph(volt, temp, ph_cal_ph1, ph_cal_v1, ph_cal_t1, ph_cal_ph2, ph_cal_v2, ph_cal_t2, ph_cal_ph3, ph_cal_v3, ph_cal_t3):
"""Convert voltage to pH."""
if ph_cal_ph3:
# 3-Pt calibration
ph = lg(
(nernst_correction(ph_cal_v1, ph_cal_t1), ph_cal_ph1),
(nernst_correction(ph_cal_v2, ph_cal_t2), ph_cal_ph2),
(nernst_correction(ph_cal_v3, ph_cal_t3), ph_cal_ph3),
nernst_correction(volt, temp)
)
else:
# 2-Pt calibration: Calculate slope and intercept from calibration points.
slope = (
(ph_cal_ph1 - ph_cal_ph2) /
(nernst_correction(ph_cal_v1, ph_cal_t1) -
nernst_correction(ph_cal_v2, ph_cal_t2))
)
intercept = (ph_cal_ph1 -
slope *
nernst_correction(ph_cal_v1, ph_cal_t1))
if temp is not None:
# Perform temperature corrections
ph = slope * nernst_correction(volt, temp) + intercept
else:
# Don't perform temperature corrections
ph = slope * volt + intercept
return ph
test_2_pt = [
(10.0, 1, 27.0),
(4.0, 3, 14.0)
]
test_3_pt = [
(10.0, 1, 27.0),
(7.0, 2.7, 30.0),
(4.0, 3, 14.0)
]
print(convert_volt_to_ph(3, 20.0, test_2_pt[0][0], test_2_pt[0][1], test_2_pt[0][2], test_2_pt[1][0], test_2_pt[1][1], test_2_pt[1][2], None, None, None))
print()
print(convert_volt_to_ph(3, 20.0, test_3_pt[0][0], test_3_pt[0][1], test_3_pt[0][2], test_3_pt[1][0], test_3_pt[1][1], test_3_pt[1][2], test_3_pt[2][0], test_3_pt[2][1], test_3_pt[2][2]))
Output:
pi@rpi:~/Mycodo/test $ ../env/bin/python ./test_2_3_pt_cal_01.py
4.18039185118786
4.472628297516382
I'm not completely confident that this is correct, so I'll try to do some more testing to determine if it is indeed working as expected and accurate.
Here is test module v01 that incorporates the 3-pt pH calibration. You'll need to change the extension from .txt to .py, then import on the Input Import page. If you do test, let me know how it goes.
This issue has been mentioned on Radical DIY Forum. There might be relevant details there:
Checking to see if anyone has tested this new input.
Hi, I see that Anyleaf and Atlas Scientific pH sensors allow 3 pH calibration points, would it be possible for the 'ADS1115 pH/EC' input to have this option as well (it only seems to have 2 as of now).
Many thanks,