From dc88916823608b1e47e707fc69e75cd98357f670 Mon Sep 17 00:00:00 2001 From: rbaron Date: Sat, 3 Dec 2022 10:46:48 +0100 Subject: [PATCH] Add board 1.0.0, 1.1.0, 1.2.0 board revisions for nRF52840 variant --- .../bparasite_nrf52840/bparasite_nrf52840.dts | 13 +-- .../bparasite_nrf52840_1_0_0.conf | 1 + .../bparasite_nrf52840_1_0_0.overlay | 0 .../bparasite_nrf52840_1_1_0.conf | 1 + .../bparasite_nrf52840_1_1_0.overlay | 30 ++++++ .../bparasite_nrf52840_1_2_0.conf | 0 .../bparasite_nrf52840_1_2_0.overlay | 29 +++++ .../arm/bparasite_nrf52840/revision.cmake | 1 + code/nrf-connect/prstlib/src/adc.c | 100 ++++++++++++------ code/nrf-connect/samples/ble/prj.conf | 2 + 10 files changed, 135 insertions(+), 42 deletions(-) create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.conf create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.overlay create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.conf create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.overlay create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.conf create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.overlay create mode 100644 code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/revision.cmake 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 09e3754..f6c77f8 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 @@ -13,7 +13,7 @@ }; zephyr,user { - io-channels = <&adc 0>, <&adc 1>, <&adc 2>; + io-channels = <&adc 0>, <&adc 2>; }; leds { @@ -108,17 +108,6 @@ }; - // Photo. - channel@1 { - reg = <1>; - zephyr,gain = "ADC_GAIN_1_6"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - // P0.02. - zephyr,input-positive = ; - zephyr,resolution = <10>; - }; - // Battery. channel@2 { reg = <2>; diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.conf b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.conf new file mode 100644 index 0000000..520e011 --- /dev/null +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.conf @@ -0,0 +1 @@ +# Comment \ No newline at end of file diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.overlay b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_0_0.overlay new file mode 100644 index 0000000..e69de29 diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.conf b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.conf new file mode 100644 index 0000000..520e011 --- /dev/null +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.conf @@ -0,0 +1 @@ +# Comment \ No newline at end of file diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.overlay b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.overlay new file mode 100644 index 0000000..7c338af --- /dev/null +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_1_0.overlay @@ -0,0 +1,30 @@ + +/ { + // Light dependant resistor. + ldr: ldr { + compatible = "voltage-divider"; + output-ohms = <10000>; + io-channels = <&adc 1>; + }; + + ctrl { + compatible = "gpio-keys"; + ldr_enable: ldr_enable { + // P0.29. + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + label = "Fast discharge circuitry"; + }; + }; +}; + +&adc { + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + // P0.02. + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; +}; \ No newline at end of file diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.conf b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.conf new file mode 100644 index 0000000..e69de29 diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.overlay b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.overlay new file mode 100644 index 0000000..5c6191b --- /dev/null +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/bparasite_nrf52840_1_2_0.overlay @@ -0,0 +1,29 @@ + +/ { + photo_transistor: photo_transistor { + compatible = "voltage-divider"; + output-ohms = <470>; + io-channels = <&adc 1>; + }; + + ctrl { + compatible = "gpio-keys"; + photo_transistor_enable: photo_transistor_enable { + // P0.29. + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + label = "Fast discharge circuitry"; + }; + }; +}; + +&adc { + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + // P0.02. + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; +}; \ No newline at end of file diff --git a/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/revision.cmake b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/revision.cmake new file mode 100644 index 0000000..9b7df2d --- /dev/null +++ b/code/nrf-connect/prstlib/boards/arm/bparasite_nrf52840/revision.cmake @@ -0,0 +1 @@ +board_check_revision(FORMAT MAJOR.MINOR.PATCH) \ No newline at end of file diff --git a/code/nrf-connect/prstlib/src/adc.c b/code/nrf-connect/prstlib/src/adc.c index 285d3db..6cb9101 100644 --- a/code/nrf-connect/prstlib/src/adc.c +++ b/code/nrf-connect/prstlib/src/adc.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "prstlib/macros.h" @@ -28,21 +29,34 @@ static struct adc_sequence sequence = { static const struct adc_dt_spec adc_soil_spec = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0); -static const struct adc_dt_spec adc_lux_spec = +static const struct adc_dt_spec adc_batt_spec = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1); -static const struct adc_dt_spec adc_batt_spec = - ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 2); +#if DT_NODE_EXISTS(DT_NODELABEL(photo_transistor)) + +static const struct adc_dt_spec adc_photo_transistor_spec = + ADC_DT_SPEC_GET(DT_NODELABEL(photo_transistor)); +struct gpio_dt_spec photo_transistor_enable_dt = + GPIO_DT_SPEC_GET(DT_NODELABEL(photo_transistor_enable), gpios); + +#elif DT_NODE_EXISTS(DT_NODELABEL(ldr)) + +static const struct adc_dt_spec adc_ldr_spec = + ADC_DT_SPEC_GET(DT_NODELABEL(ldr)); +struct gpio_dt_spec ldr_enable_dt = + GPIO_DT_SPEC_GET(DT_NODELABEL(ldr_enable), gpios); + +#endif -// TODO: recalibrate with v2 hardware. 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; - LOG_DBG("Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f", raw_adc_output, x, dry, - wet); - return (raw_adc_output - dry) / (wet - dry); + const float percent = (raw_adc_output - dry) / (wet - dry); + LOG_DBG("Read soil moisture: %.2f | Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f", + 100.0f * percent, raw_adc_output, x, dry, wet); + return percent; } static int read_adc_spec(const struct adc_dt_spec* spec, prst_adc_read_t* out) { @@ -60,17 +74,22 @@ static int read_adc_spec(const struct adc_dt_spec* spec, prst_adc_read_t* out) { } int prst_adc_init() { - const struct adc_dt_spec* all_specs[] = { - &adc_soil_spec, - &adc_lux_spec, - &adc_batt_spec, - }; - for (int i = 0; i < sizeof(all_specs) / sizeof(all_specs[0]); i++) { - RET_IF_ERR(adc_channel_setup_dt(all_specs[i])); - } + RET_IF_ERR(adc_channel_setup_dt(&adc_soil_spec)); + RET_IF_ERR(adc_channel_setup_dt(&adc_batt_spec)); RET_IF_ERR(!device_is_ready(fast_disch_dt.port)); - return gpio_pin_configure_dt(&fast_disch_dt, GPIO_OUTPUT); + RET_IF_ERR(gpio_pin_configure_dt(&fast_disch_dt, GPIO_OUTPUT)); + +#if DT_NODE_EXISTS(DT_NODELABEL(photo_transistor)) + RET_IF_ERR(adc_channel_setup_dt(&adc_photo_transistor_spec)); + RET_IF_ERR(!device_is_ready(photo_transistor_enable_dt.port)); + RET_IF_ERR(gpio_pin_configure_dt(&photo_transistor_enable_dt, GPIO_OUTPUT)); +#elif DT_NODE_EXISTS(DT_NODELABEL(ldr)) + RET_IF_ERR(adc_channel_setup_dt(&adc_ldr_spec)); + RET_IF_ERR(!device_is_ready(ldr_enable_dt.port)); + RET_IF_ERR(gpio_pin_configure_dt(&ldr_enable_dt, GPIO_OUTPUT)); +#endif + return 0; } @@ -82,38 +101,59 @@ int prst_adc_batt_read(prst_adc_read_t* out) { int prst_adc_soil_read(float battery_voltage, prst_adc_soil_moisture_t* out) { // Enable fast discharge circuit. RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 1)); - // Start PWM. RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, soil_pwm_dt.period, pulse)); - k_msleep(30); - RET_IF_ERR(read_adc_spec(&adc_soil_spec, &out->adc_read)); - // Stop PWM. RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, 0, 0)); - // Turn off fast discharge circuit. RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 0)); - out->percentage = MAX(0.0f, MIN(1.0f, get_soil_moisture_percent(battery_voltage, buf))); return 0; } int prst_adc_photo_read(float battery_voltage, prst_adc_photo_sensor_t* out) { - RET_IF_ERR(read_adc_spec(&adc_soil_spec, &out->adc_read)); - - // The ALS-PT19 phototransistor is a device in which the current flow between - // its two terminals is controlled by how much light there is in the ambient. - // We measure that current by calculating the voltage across a resistor that - // is connected in series with the phototransistor. - const float phototransistor_resistor = 470.0f; - const float current_sun = 3.59e-3f; +#if DT_NODE_EXISTS(DT_NODELABEL(photo_transistor)) + RET_IF_ERR(gpio_pin_set_dt(&photo_transistor_enable_dt, 1)); + k_msleep(10); + RET_IF_ERR(read_adc_spec(&adc_photo_transistor_spec, &out->adc_read)); + RET_IF_ERR(gpio_pin_set_dt(&photo_transistor_enable_dt, 0)); + const float phototransistor_resistor = DT_PROP(DT_NODELABEL(photo_transistor), output_ohms); // Assuming 10000 lux for the saturation test. Calibration with a proper light // meter would be better. const float lux_sun = 10000.0f; + const float current_sun = 3.59e-3f; const float current = out->adc_read.voltage / phototransistor_resistor; out->brightness = MAX(0, MIN(lux_sun * current / current_sun, UINT16_MAX)); + LOG_DBG("Read phototransistor: %u lx | %.2f V", out->brightness, out->adc_read.voltage); + +#elif DT_NODE_EXISTS(DT_NODELABEL(ldr)) + RET_IF_ERR(gpio_pin_set_dt(&ldr_enable_dt, 1)); + k_msleep(10); + RET_IF_ERR(read_adc_spec(&adc_ldr_spec, &out->adc_read)); + RET_IF_ERR(gpio_pin_set_dt(&ldr_enable_dt, 0)); + // The photo resistor forms a voltage divider with R. + // The voltage here is measured in the middle of the voltage divider. + // Vcc ---- (R_photo) ---|--- (R) ---- GND + // Vout + // So we can estimate R_photo = R * (Vcc - Vout) / Vout + const float r = DT_PROP(DT_NODELABEL(ldr), output_ohms); + const float photo_resistance = + r * (battery_voltage - out->adc_read.voltage) / out->adc_read.voltage; + // The relationship between the LDR resistance and the lux level is + // logarithmic. We need to solve a logarithmic equation to find the lux + // level, given the LDR resistance we just measured. + // These values work for the GL5528 LDR and were borrowed from + // https://github.com/QuentinCG/Arduino-Light-Dependent-Resistor-Library. + const float mult_value = 32017200.0f; + const float pow_value = 1.5832f; + out->brightness = + MAX(0, MIN(mult_value / powf(photo_resistance, pow_value), UINT16_MAX)); + LOG_DBG("Read LDR: %u lx | %.2f V", out->brightness, out->adc_read.voltage); + +#endif + return 0; } diff --git a/code/nrf-connect/samples/ble/prj.conf b/code/nrf-connect/samples/ble/prj.conf index 7fb14f4..79f2154 100644 --- a/code/nrf-connect/samples/ble/prj.conf +++ b/code/nrf-connect/samples/ble/prj.conf @@ -20,3 +20,5 @@ CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y # Application config - see all options in Kconfig. +# CONFIG_PRST_BLE_ENCODING_BTHOME_V1=y +# CONFIG_PRST_SLEEP_DURATION_SEC=1 \ No newline at end of file