Add board 1.0.0, 1.1.0, 1.2.0 board revisions for nRF52840 variant
This commit is contained in:
parent
a93171b9bf
commit
dc88916823
10 changed files with 135 additions and 42 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
zephyr,user {
|
zephyr,user {
|
||||||
io-channels = <&adc 0>, <&adc 1>, <&adc 2>;
|
io-channels = <&adc 0>, <&adc 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
leds {
|
leds {
|
||||||
|
|
@ -108,17 +108,6 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Photo.
|
|
||||||
channel@1 {
|
|
||||||
reg = <1>;
|
|
||||||
zephyr,gain = "ADC_GAIN_1_6";
|
|
||||||
zephyr,reference = "ADC_REF_INTERNAL";
|
|
||||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
|
||||||
// P0.02.
|
|
||||||
zephyr,input-positive = <NRF_SAADC_AIN0>;
|
|
||||||
zephyr,resolution = <10>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Battery.
|
// Battery.
|
||||||
channel@2 {
|
channel@2 {
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# Comment
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# Comment
|
||||||
|
|
@ -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 = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
// P0.02.
|
||||||
|
zephyr,input-positive = <NRF_SAADC_AIN0>;
|
||||||
|
zephyr,resolution = <10>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -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 = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
// P0.02.
|
||||||
|
zephyr,input-positive = <NRF_SAADC_AIN0>;
|
||||||
|
zephyr,resolution = <10>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
board_check_revision(FORMAT MAJOR.MINOR.PATCH)
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <drivers/gpio.h>
|
#include <drivers/gpio.h>
|
||||||
#include <drivers/pwm.h>
|
#include <drivers/pwm.h>
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
|
#include <math.h>
|
||||||
#include <zephyr/zephyr.h>
|
#include <zephyr/zephyr.h>
|
||||||
|
|
||||||
#include "prstlib/macros.h"
|
#include "prstlib/macros.h"
|
||||||
|
|
@ -28,21 +29,34 @@ static struct adc_sequence sequence = {
|
||||||
static const struct adc_dt_spec adc_soil_spec =
|
static const struct adc_dt_spec adc_soil_spec =
|
||||||
ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
|
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);
|
ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1);
|
||||||
|
|
||||||
static const struct adc_dt_spec adc_batt_spec =
|
#if DT_NODE_EXISTS(DT_NODELABEL(photo_transistor))
|
||||||
ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 2);
|
|
||||||
|
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,
|
static inline float get_soil_moisture_percent(float battery_voltage,
|
||||||
int16_t raw_adc_output) {
|
int16_t raw_adc_output) {
|
||||||
const double x = battery_voltage;
|
const double x = battery_voltage;
|
||||||
const double dry = -11.7f * x * x + 101.0f * x + 306.0f;
|
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 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,
|
const float percent = (raw_adc_output - dry) / (wet - dry);
|
||||||
wet);
|
LOG_DBG("Read soil moisture: %.2f | Raw %u | Batt: %.2f | Dry: %.2f | Wet: %.2f",
|
||||||
return (raw_adc_output - dry) / (wet - dry);
|
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) {
|
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() {
|
int prst_adc_init() {
|
||||||
const struct adc_dt_spec* all_specs[] = {
|
RET_IF_ERR(adc_channel_setup_dt(&adc_soil_spec));
|
||||||
&adc_soil_spec,
|
RET_IF_ERR(adc_channel_setup_dt(&adc_batt_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(!device_is_ready(fast_disch_dt.port));
|
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;
|
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) {
|
int prst_adc_soil_read(float battery_voltage, prst_adc_soil_moisture_t* out) {
|
||||||
// Enable fast discharge circuit.
|
// Enable fast discharge circuit.
|
||||||
RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 1));
|
RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 1));
|
||||||
|
|
||||||
// Start PWM.
|
// Start PWM.
|
||||||
RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, soil_pwm_dt.period, pulse));
|
RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, soil_pwm_dt.period, pulse));
|
||||||
|
|
||||||
k_msleep(30);
|
k_msleep(30);
|
||||||
|
|
||||||
RET_IF_ERR(read_adc_spec(&adc_soil_spec, &out->adc_read));
|
RET_IF_ERR(read_adc_spec(&adc_soil_spec, &out->adc_read));
|
||||||
|
|
||||||
// Stop PWM.
|
// Stop PWM.
|
||||||
RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, 0, 0));
|
RET_IF_ERR(pwm_set_dt(&soil_pwm_dt, 0, 0));
|
||||||
|
|
||||||
// Turn off fast discharge circuit.
|
// Turn off fast discharge circuit.
|
||||||
RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 0));
|
RET_IF_ERR(gpio_pin_set_dt(&fast_disch_dt, 0));
|
||||||
|
|
||||||
out->percentage =
|
out->percentage =
|
||||||
MAX(0.0f, MIN(1.0f, get_soil_moisture_percent(battery_voltage, buf)));
|
MAX(0.0f, MIN(1.0f, get_soil_moisture_percent(battery_voltage, buf)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prst_adc_photo_read(float battery_voltage, prst_adc_photo_sensor_t* out) {
|
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));
|
#if DT_NODE_EXISTS(DT_NODELABEL(photo_transistor))
|
||||||
|
RET_IF_ERR(gpio_pin_set_dt(&photo_transistor_enable_dt, 1));
|
||||||
// The ALS-PT19 phototransistor is a device in which the current flow between
|
k_msleep(10);
|
||||||
// its two terminals is controlled by how much light there is in the ambient.
|
RET_IF_ERR(read_adc_spec(&adc_photo_transistor_spec, &out->adc_read));
|
||||||
// We measure that current by calculating the voltage across a resistor that
|
RET_IF_ERR(gpio_pin_set_dt(&photo_transistor_enable_dt, 0));
|
||||||
// is connected in series with the phototransistor.
|
const float phototransistor_resistor = DT_PROP(DT_NODELABEL(photo_transistor), output_ohms);
|
||||||
const float phototransistor_resistor = 470.0f;
|
|
||||||
const float current_sun = 3.59e-3f;
|
|
||||||
// Assuming 10000 lux for the saturation test. Calibration with a proper light
|
// Assuming 10000 lux for the saturation test. Calibration with a proper light
|
||||||
// meter would be better.
|
// meter would be better.
|
||||||
const float lux_sun = 10000.0f;
|
const float lux_sun = 10000.0f;
|
||||||
|
const float current_sun = 3.59e-3f;
|
||||||
const float current = out->adc_read.voltage / phototransistor_resistor;
|
const float current = out->adc_read.voltage / phototransistor_resistor;
|
||||||
out->brightness = MAX(0, MIN(lux_sun * current / current_sun, UINT16_MAX));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,5 @@ CONFIG_NEWLIB_LIBC=y
|
||||||
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
|
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
|
||||||
|
|
||||||
# Application config - see all options in Kconfig.
|
# Application config - see all options in Kconfig.
|
||||||
|
# CONFIG_PRST_BLE_ENCODING_BTHOME_V1=y
|
||||||
|
# CONFIG_PRST_SLEEP_DURATION_SEC=1
|
||||||
Loading…
Add table
Reference in a new issue