From 1983f31af9fc00b95fff8113d883f0be87917348 Mon Sep 17 00:00:00 2001 From: rbaron Date: Sun, 19 Mar 2023 09:44:58 +0100 Subject: [PATCH] Store calibration polynomial in devicetree This will enable us to transparently use different calibration for different board revisions. The 2.0.0 revision changes the sensing circuitry and will need its own coeffs. In this commit, both models are run in parallel for debugging. --- .../bparasite_nrf52840/bparasite_nrf52840.dts | 6 ++++ .../prstlib/dts/bindings/pwm-fixed.yaml | 1 - .../dts/bindings/soil-calibration-coeffs.yaml | 25 +++++++++++++++ code/nrf-connect/prstlib/src/adc.c | 32 ++++++++++++++++--- .../samples/ble/ble.code-workspace | 4 ++- 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 code/nrf-connect/prstlib/dts/bindings/soil-calibration-coeffs.yaml diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840.dts b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840.dts index 578a023..8dd7eb2 100644 --- a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840.dts +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840.dts @@ -40,6 +40,12 @@ pulse = ; }; + soil_calibration_coeffs: soil_calibration_coeffs { + compatible = "soil-calibration-coeffs"; + dry = <306000 101000 (-11700)>; + wet = <19000 (-4980) 3420>; + }; + ctrl { compatible = "gpio-keys"; fast_disch: fast_disch { diff --git a/code/nrf-connect/prstlib/dts/bindings/pwm-fixed.yaml b/code/nrf-connect/prstlib/dts/bindings/pwm-fixed.yaml index 7b111df..c9dee3c 100644 --- a/code/nrf-connect/prstlib/dts/bindings/pwm-fixed.yaml +++ b/code/nrf-connect/prstlib/dts/bindings/pwm-fixed.yaml @@ -1,4 +1,3 @@ -# Hello description: A fixed frequency & pulse PWM. diff --git a/code/nrf-connect/prstlib/dts/bindings/soil-calibration-coeffs.yaml b/code/nrf-connect/prstlib/dts/bindings/soil-calibration-coeffs.yaml new file mode 100644 index 0000000..5ff7c5b --- /dev/null +++ b/code/nrf-connect/prstlib/dts/bindings/soil-calibration-coeffs.yaml @@ -0,0 +1,25 @@ + +description: > + Calibration coefficients for the soil sensing circuit. We have two polynomials whose input variable + is the battery voltage in Volts. The evaluated polynomial corresponds to the estimated ADC value, + assumed to be 10 bits, so in [0, 1024). The two polynomials are: + dry: For estimation of the fully dry state, given the battery voltage + wet: For estimation of the fully dry state, given the battery voltage + + Note that each poly coefficient is specified as 1000 times its real values. This is because we can't + directly represent floating points in devicetree. The final evaludated value should be divided by + 1000.0f in code. + +compatible: soil-calibration-coeffe + +include: base.yaml + +properties: + dry: + type: array + required: true + description: The coefficients * 1000, as integers. 0th degree first, then 1st and 2nd last. + wet: + type: array + required: true + description: The coefficients * 1000, as integers. 0th degree first, then 1st and 2nd last. diff --git a/code/nrf-connect/prstlib/src/adc.c b/code/nrf-connect/prstlib/src/adc.c index f13232d..ef64200 100644 --- a/code/nrf-connect/prstlib/src/adc.c +++ b/code/nrf-connect/prstlib/src/adc.c @@ -1,6 +1,7 @@ #include "prstlib/adc.h" #include +#include #include #include #include @@ -16,6 +17,10 @@ static const struct pwm_dt_spec soil_pwm_dt = PWM_DT_SPEC_GET(DT_NODELABEL(soil_pwm)); static const uint32_t pulse = DT_PROP(DT_NODELABEL(soil_pwm), pulse); +// Calibration coefficients for the soil sensing circuit. +static const int dry_coeffs[3] = DT_PROP(DT_NODELABEL(soil_calibration_coeffs), dry); +static const int wet_coeffs[3] = DT_PROP(DT_NODELABEL(soil_calibration_coeffs), wet); + struct gpio_dt_spec fast_disch_dt = GPIO_DT_SPEC_GET(DT_NODELABEL(fast_disch), gpios); @@ -79,14 +84,27 @@ static void set_battery_percent(const prst_adc_read_t* read, prst_batt_t* out) { return; } +static inline float eval_poly(const int coeffs[3], float x) { + // The coefficients are specified times 1000, as a workaround the lack of support for floating + // points in devicetree bindings. + return (coeffs[0] + coeffs[1] * x + coeffs[2] * x * x) / 1000.0f; +} + static inline float get_soil_moisture_percent(float battery_voltage, int16_t raw_adc_output) { - const double x = battery_voltage; - const double dry = -11.7f * x * x + 101.0f * x + 306.0f; - const double wet = 3.42f * x * x - 4.98f * x + 19.0f; + const float x = battery_voltage; + const float dry = -11.7f * x * x + 101.0f * x + 306.0f; + const float wet = 3.42f * x * x - 4.98f * x + 19.0f; const float percent = (raw_adc_output - dry) / (wet - dry); - LOG_DBG("Read soil moisture: %.2f | Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f", + LOG_INF("Read soil moisture: %.2f | Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f", 100.0f * percent, raw_adc_output, x, dry, wet); + + const float dry2 = eval_poly(dry_coeffs, x); + const float wet2 = eval_poly(wet_coeffs, x); + const float percent2 = (raw_adc_output - dry) / (wet - dry); + LOG_INF("Read soil moisture 2: %.2f | Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f", + 100.0f * percent2, raw_adc_output, x, dry2, wet2); + return percent; } @@ -121,6 +139,12 @@ int prst_adc_init() { RET_IF_ERR(gpio_pin_configure_dt(&ldr_enable_dt, GPIO_OUTPUT)); #endif + for (size_t idx = 0; idx < ARRAY_SIZE(dry_coeffs); idx++) { + LOG_INF("Dry coeff %d: %d\n", idx, dry_coeffs[idx]); + } + for (size_t idx = 0; idx < ARRAY_SIZE(wet_coeffs); idx++) { + LOG_INF("Wet coeff %d: %d\n", idx, wet_coeffs[idx]); + } return 0; } diff --git a/code/nrf-connect/samples/ble/ble.code-workspace b/code/nrf-connect/samples/ble/ble.code-workspace index 44c0e47..4e759b6 100644 --- a/code/nrf-connect/samples/ble/ble.code-workspace +++ b/code/nrf-connect/samples/ble/ble.code-workspace @@ -11,6 +11,8 @@ "C_Cpp.autoAddFileAssociations": false, "nrf-connect.applications": [ "${workspaceFolder}" - ] + ], + "nrf-connect.toolchain.path": "${nrf-connect.toolchain:2.2.0}", + "nrf-connect.topdir": "${nrf-connect.sdk:2.2.0}" } } \ No newline at end of file