Compare commits
No commits in common. "main" and "nrf2.5" have entirely different histories.
13 changed files with 59 additions and 57 deletions
2
.github/workflows/b-parasite.yml
vendored
2
.github/workflows/b-parasite.yml
vendored
|
|
@ -86,7 +86,7 @@ jobs:
|
||||||
sample-dir: code/nrf-connect/samples/ble
|
sample-dir: code/nrf-connect/samples/ble
|
||||||
board: bparasite_${{ matrix.soc }}
|
board: bparasite_${{ matrix.soc }}
|
||||||
revision: ${{ matrix.revision }}
|
revision: ${{ matrix.revision }}
|
||||||
cmake-extra: -DCONFIG_PRST_BLE_ENCODING_BTHOME_V2=y -DCONFIG_PRST_SLEEP_DURATION_MSEC=1000 -DCONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
cmake-extra: -DCONFIG_PRST_BLE_ENCODING_BTHOME_V2=y -DCONFIG_PRST_SLEEP_DURATION_SEC=1 -DCONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
||||||
output-bin: ble_${{ matrix.soc }}_${{ matrix.revision }}_debug.hex
|
output-bin: ble_${{ matrix.soc }}_${{ matrix.revision }}_debug.hex
|
||||||
|
|
||||||
build-zigbee:
|
build-zigbee:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ b-parasite is an open source soil moisture and ambient temperature/humidity/ligh
|
||||||
# Features
|
# Features
|
||||||
* Capacitive Soil moisture sensor - see [this blog post](https://rbaron.net/blog/2021/04/05/How-capacitive-soil-moisture-sensors-work.html), [this Twitter thread](https://twitter.com/rbaron_/status/1367182806368071685), and [this post](https://wemakethings.net/2012/09/26/capacitance_measurement/) for nice resources on how they work
|
* Capacitive Soil moisture sensor - see [this blog post](https://rbaron.net/blog/2021/04/05/How-capacitive-soil-moisture-sensors-work.html), [this Twitter thread](https://twitter.com/rbaron_/status/1367182806368071685), and [this post](https://wemakethings.net/2012/09/26/capacitance_measurement/) for nice resources on how they work
|
||||||
* Air temperature and humidity sensor using a [Sensirion's SHTC3](https://www.sensirion.com/en/environmental-sensors/humidity-sensors/digital-humidity-sensor-shtc3-our-new-standard-for-consumer-electronics/)
|
* Air temperature and humidity sensor using a [Sensirion's SHTC3](https://www.sensirion.com/en/environmental-sensors/humidity-sensors/digital-humidity-sensor-shtc3-our-new-standard-for-consumer-electronics/)
|
||||||
* Light sensor using an [ALS-PT19](https://en.everlight.com/wp-content/plugins/ItemRelationship/product_files/pdf/ALS-PT19-315C-L177-TR8_V8.pdf) phototransistor
|
* Light sensor using an [ALS-PT19](https://everlighteurope.com/ambient-light-sensors/7/ALSPT19315CL177TR8.html) phototransistor
|
||||||
* Powered by a common CR2032 coin cell, potentially for over two years
|
* Powered by a common CR2032 coin cell, potentially for over two years
|
||||||
* Support for [nRF52840](https://www.nordicsemi.com/products/nrf52840) and [nRF52833](https://www.nordicsemi.com/products/nrf52833) modules
|
* Support for [nRF52840](https://www.nordicsemi.com/products/nrf52840) and [nRF52833](https://www.nordicsemi.com/products/nrf52833) modules
|
||||||
* Open hardware and open source design
|
* Open hardware and open source design
|
||||||
|
|
@ -49,12 +49,6 @@ We have three different 3D-printable cases:
|
||||||
1. Original snap-on case - [case/Top.stl](./case/Top.stl), [case/Bottom.stl](./case/Bottom.stl)
|
1. Original snap-on case - [case/Top.stl](./case/Top.stl), [case/Bottom.stl](./case/Bottom.stl)
|
||||||
2. High airflow - [case/b_parasite_case_high_airflow.stl](./case/b_parasite_case_high_airflow.stl)
|
2. High airflow - [case/b_parasite_case_high_airflow.stl](./case/b_parasite_case_high_airflow.stl)
|
||||||
3. Mushroom-style - available on [Printables](https://www.printables.com/model/456571-mushroomcap-for-b-parasite-soil-moisture-sensor)
|
3. Mushroom-style - available on [Printables](https://www.printables.com/model/456571-mushroomcap-for-b-parasite-soil-moisture-sensor)
|
||||||
4. b-parasite Hat - available on [Printables](https://www.printables.com/model/901220-waterproof-case-for-b-parasite-soil-moisture-air-s)
|
|
||||||
|
|
||||||
# Accessories
|
|
||||||
|
|
||||||
Designs and hardware to help you, when building your own:
|
|
||||||
1. Desk holder for b-parasites [Printables](https://www.printables.com/de/model/566974-b-parasite-holder)
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
The hardware and associated design files are released under the [Creative Commons CC BY-SA 4.0 license](https://creativecommons.org/licenses/by-sa/4.0/).
|
The hardware and associated design files are released under the [Creative Commons CC BY-SA 4.0 license](https://creativecommons.org/licenses/by-sa/4.0/).
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,7 @@
|
||||||
|
|
||||||
|
|
||||||
&flash0 {
|
&flash0 {
|
||||||
|
|
||||||
partitions {
|
partitions {
|
||||||
compatible = "fixed-partitions";
|
compatible = "fixed-partitions";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
@ -146,23 +147,33 @@
|
||||||
|
|
||||||
boot_partition: partition@0 {
|
boot_partition: partition@0 {
|
||||||
label = "mcuboot";
|
label = "mcuboot";
|
||||||
reg = <0x000000000 0xC000>;
|
reg = <0x00000000 0x0000C000>;
|
||||||
};
|
};
|
||||||
slot0_partition: partition@c000 {
|
slot0_partition: partition@c000 {
|
||||||
label = "image-0";
|
label = "image-0";
|
||||||
reg = <0x0000C000 0x32000>;
|
reg = <0x0000C000 0x00067000>;
|
||||||
};
|
};
|
||||||
slot1_partition: partition@3e000 {
|
slot1_partition: partition@73000 {
|
||||||
label = "image-1";
|
label = "image-1";
|
||||||
reg = <0x0003E000 0x32000>;
|
reg = <0x00073000 0x00067000>;
|
||||||
};
|
};
|
||||||
scratch_partition: partition@70000 {
|
scratch_partition: partition@da000 {
|
||||||
label = "image-scratch";
|
label = "image-scratch";
|
||||||
reg = <0x00070000 0xA000>;
|
reg = <0x000da000 0x0001e000>;
|
||||||
};
|
};
|
||||||
storage_partition: partition@7a000 {
|
|
||||||
|
/*
|
||||||
|
* The flash starting at 0x000f8000 and ending at
|
||||||
|
* 0x000fffff is reserved for use by the application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Storage partition will be used by FCB/LittleFS/NVS
|
||||||
|
* if enabled.
|
||||||
|
*/
|
||||||
|
storage_partition: partition@f8000 {
|
||||||
label = "storage";
|
label = "storage";
|
||||||
reg = <0x0007A000 0x00006000>;
|
reg = <0x000f8000 0x00008000>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,6 @@ static int read_adc_spec(const struct adc_dt_spec* spec, prst_adc_read_t* out) {
|
||||||
|
|
||||||
int32_t val_mv = buf;
|
int32_t val_mv = buf;
|
||||||
RET_IF_ERR(adc_raw_to_millivolts_dt(spec, &val_mv));
|
RET_IF_ERR(adc_raw_to_millivolts_dt(spec, &val_mv));
|
||||||
val_mv = MAX(0, val_mv);
|
|
||||||
|
|
||||||
out->raw = buf;
|
out->raw = buf;
|
||||||
out->millivolts = val_mv;
|
out->millivolts = val_mv;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@ int prst_sensors_read_all(prst_sensors_t *sensors) {
|
||||||
|
|
||||||
LOG_DBG("Batt: %d mV (%.2f%%)", sensors->batt.adc_read.millivolts,
|
LOG_DBG("Batt: %d mV (%.2f%%)", sensors->batt.adc_read.millivolts,
|
||||||
100 * sensors->batt.percentage);
|
100 * sensors->batt.percentage);
|
||||||
LOG_DBG("Soil: %.0f %%", 100 * sensors->soil.percentage);
|
LOG_DBG("Soil: %.0f %% (%d mV)", 100 * sensors->soil.percentage,
|
||||||
|
sensors->soil.adc_read.millivolts);
|
||||||
LOG_DBG("Photo: %u lx (%d mV)", sensors->photo.brightness,
|
LOG_DBG("Photo: %u lx (%d mV)", sensors->photo.brightness,
|
||||||
sensors->photo.adc_read.millivolts);
|
sensors->soil.adc_read.millivolts);
|
||||||
LOG_DBG("Temp: %f oC", sensors->shtc3.temp_c);
|
LOG_DBG("Temp: %f oC", sensors->shtc3.temp_c);
|
||||||
LOG_DBG("Humi: %.0f %%", 100 * sensors->shtc3.rel_humi);
|
LOG_DBG("Humi: %.0f %%", 100 * sensors->shtc3.rel_humi);
|
||||||
LOG_DBG("--------------------------------------------------");
|
LOG_DBG("--------------------------------------------------");
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
source "Kconfig.zephyr"
|
source "Kconfig.zephyr"
|
||||||
rsource "../../prstlib/Kconfig"
|
rsource "../../prstlib/Kconfig"
|
||||||
|
|
||||||
config PRST_SLEEP_DURATION_MSEC
|
config PRST_SLEEP_DURATION_SEC
|
||||||
int "Sleep duration in milliseconds"
|
int "Sleep duration in seconds"
|
||||||
default 600000
|
default 600
|
||||||
|
|
||||||
config PRST_BLE_ADV_DURATION_MSEC
|
config PRST_BLE_ADV_DURATION_SEC
|
||||||
int "Advertising duration in milliseconds"
|
int "Advertising duration in seconds"
|
||||||
default 1000
|
default 1
|
||||||
|
|
||||||
config PRST_BLE_MIN_ADV_INTERVAL
|
config PRST_BLE_MIN_ADV_INTERVAL
|
||||||
int "Minimum advertising interval in milliseconds"
|
int "Minimum advertising interval in milliseconds"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Bluetooth Low Energy (BLE)
|
# Bluetooth Low Energy (BLE)
|
||||||
In this sample, b-parasite sensors are periodically read and broadcast using Bluetooth Low Energy (BLE) dvertising packets.
|
In this saple, b-parasite sensors are periodically read and broadcast using Bluetooth Low Energy (BLE) dvertising packets.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Available configurations and their default values are in [`Kconfig`](./Kconfig). They are set in [`prj.conf`](./prj.conf). Here are some notable examples.
|
Available configurations and their default values are in [`Kconfig`](./Kconfig). They are set in [`prj.conf`](./prj.conf). Here are some notable examples.
|
||||||
|
|
@ -8,7 +8,7 @@ Available configurations and their default values are in [`Kconfig`](./Kconfig).
|
||||||
To save energy, the board spends most of the time in a "deep sleep" state, in which most peripherals and radio are completely turned off. The period of sleep is controlled by the `PRST_SLEEP_DURATION_SEC` config.
|
To save energy, the board spends most of the time in a "deep sleep" state, in which most peripherals and radio are completely turned off. The period of sleep is controlled by the `PRST_SLEEP_DURATION_SEC` config.
|
||||||
|
|
||||||
### Advertising Duration
|
### Advertising Duration
|
||||||
When it wakes up, the sample reads all sensors and keep broadcasting advertising packets for `PRST_BLE_ADV_DURATION_MSEC` before going back to sleep.
|
When it wakes up, the sample reads all sensors and keep broadcasting advertising packets for `PRST_BLE_ADV_DURATION_SEC` before going back to sleep.
|
||||||
|
|
||||||
### Advertising Packet Encoding
|
### Advertising Packet Encoding
|
||||||
There are different ways to encode the sensor data in a BLE advertising packet.
|
There are different ways to encode the sensor data in a BLE advertising packet.
|
||||||
|
|
@ -52,4 +52,4 @@ If for example we lower the connection interval to the SDK defaults (`[100, 150]
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
With a `200 mAh` CR2032 battery, we can use [this spreadsheet](https://docs.google.com/spreadsheets/d/157JQiX20bGkTrlbvWbWRrs_WViL3MgVZffSCWRR7uAI/edit#gid=0) to estimate the battery life to over two years. Note that this is a simplified model and results in practice may vary.
|
With a `200 mAh` CR2032 battery, we can use [this spreadsheet](https://docs.google.com/spreadsheets/d/157JQiX20bGkTrlbvWbWRrs_WViL3MgVZffSCWRR7uAI/edit#gid=0) to estimate the battery life to over two years. Note that this is a simplified model and results in practice may vary.
|
||||||
|
|
@ -21,7 +21,7 @@ CONFIG_ASSERT=y
|
||||||
|
|
||||||
# Application config - see all options in Kconfig.
|
# Application config - see all options in Kconfig.
|
||||||
# CONFIG_PRST_BLE_ENCODING_BTHOME_V2=y
|
# CONFIG_PRST_BLE_ENCODING_BTHOME_V2=y
|
||||||
# CONFIG_PRST_SLEEP_DURATION_MSEC=1000
|
# CONFIG_PRST_SLEEP_DURATION_SEC=1
|
||||||
|
|
||||||
# prstlib config - ser all options in prstlib/Kconfig.
|
# prstlib config - ser all options in prstlib/Kconfig.
|
||||||
# CONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
# CONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
||||||
|
|
|
||||||
|
|
@ -104,36 +104,33 @@ int prst_ble_encode_service_data(const prst_sensors_t* sensors,
|
||||||
out[4] = temp_val & 0xff;
|
out[4] = temp_val & 0xff;
|
||||||
out[5] = temp_val >> 8;
|
out[5] = temp_val >> 8;
|
||||||
// Humidity.
|
// Humidity.
|
||||||
out[6] = 0x2E;
|
out[6] = 0x03;
|
||||||
// Value. Factor 1 over 100%.
|
// Value. Factor 0.01, over 100%.
|
||||||
uint8_t humi_val = 100 * sensors->shtc3.rel_humi + 0.5f;
|
uint16_t humi_val = 10000 * sensors->shtc3.rel_humi;
|
||||||
out[7] = humi_val;
|
out[7] = humi_val & 0xff;
|
||||||
|
out[8] = humi_val >> 8;
|
||||||
// Illuminance.
|
// Illuminance.
|
||||||
out[8] = 0x05;
|
out[9] = 0x05;
|
||||||
// Value. Factor of 0.01.
|
// Value. Factor of 0.01.
|
||||||
uint32_t lux_val = sensors->photo.brightness * 100;
|
uint32_t lux_val = sensors->photo.brightness * 100;
|
||||||
out[9] = lux_val & 0xff;
|
out[10] = lux_val & 0xff;
|
||||||
out[10] = (lux_val >> 8) & 0xff;
|
out[11] = (lux_val >> 8) & 0xff;
|
||||||
out[11] = (lux_val >> 16) & 0xff;
|
out[12] = (lux_val >> 16) & 0xff;
|
||||||
// Battery voltage.
|
// Battery voltage.
|
||||||
out[12] = 0x0c;
|
out[13] = 0x0c;
|
||||||
// Value. Factor of 0.001.
|
// Value. Factor of 0.001.
|
||||||
uint16_t batt_val = sensors->batt.adc_read.millivolts;
|
uint16_t batt_val = sensors->batt.adc_read.millivolts;
|
||||||
out[13] = batt_val & 0xff;
|
out[14] = batt_val & 0xff;
|
||||||
out[14] = batt_val >> 8;
|
out[15] = batt_val >> 8;
|
||||||
// Soil moisture.
|
// Soil moisture.
|
||||||
out[15] = 0x2F;
|
out[16] = 0x14;
|
||||||
// Factor of 1 over 100%
|
// Factor of 0.01, so we need to multiply our the value in 100% by 1/0.01 = 100.
|
||||||
uint8_t soil_val = 100 * sensors->soil.percentage + 0.5f;
|
uint16_t soil_val = 10000 * sensors->soil.percentage;
|
||||||
out[16] = soil_val;
|
out[17] = soil_val & 0xff;
|
||||||
// Battery percentage.
|
out[18] = soil_val >> 8;
|
||||||
out[17] = 0x01;
|
|
||||||
// Value. Factor 1 over 100%
|
|
||||||
uint8_t batt_percentage_val = 100 * sensors->batt.percentage + 0.5f;
|
|
||||||
out[18] = batt_percentage_val;
|
|
||||||
|
|
||||||
#endif // Encoding protocols
|
#endif // Encoding protocols
|
||||||
|
|
||||||
LOG_HEXDUMP_DBG(out, out_len, "Encoded BLE adv: ");
|
LOG_HEXDUMP_DBG(out, out_len, "Encoded BLE adv: ");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ static int prst_loop(prst_sensors_t *sensors) {
|
||||||
RET_IF_ERR(prst_sensors_read_all(sensors));
|
RET_IF_ERR(prst_sensors_read_all(sensors));
|
||||||
RET_IF_ERR(prst_ble_adv_set_data(sensors));
|
RET_IF_ERR(prst_ble_adv_set_data(sensors));
|
||||||
RET_IF_ERR(prst_ble_adv_start());
|
RET_IF_ERR(prst_ble_adv_start());
|
||||||
k_msleep(CONFIG_PRST_BLE_ADV_DURATION_MSEC);
|
k_sleep(K_SECONDS(CONFIG_PRST_BLE_ADV_DURATION_SEC));
|
||||||
RET_IF_ERR(prst_ble_adv_stop());
|
RET_IF_ERR(prst_ble_adv_stop());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +37,6 @@ int main(void) {
|
||||||
prst_sensors_t sensors;
|
prst_sensors_t sensors;
|
||||||
while (true) {
|
while (true) {
|
||||||
__ASSERT(!prst_loop(&sensors), "Error in prst_loop()");
|
__ASSERT(!prst_loop(&sensors), "Error in prst_loop()");
|
||||||
k_msleep(CONFIG_PRST_SLEEP_DURATION_MSEC);
|
k_sleep(K_SECONDS(CONFIG_PRST_SLEEP_DURATION_SEC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Comment,Designator,Footprint,LCSC
|
||||||
"1n","C1","Capacitor_SMD:C_0402_1005Metric","C1523"
|
"1n","C1","Capacitor_SMD:C_0402_1005Metric","C1523"
|
||||||
"100n","C2","Capacitor_SMD:C_0402_1005Metric","C1525"
|
"100n","C2","Capacitor_SMD:C_0402_1005Metric","C1525"
|
||||||
"12p","C3,C4","Capacitor_SMD:C_0402_1005Metric","C1547"
|
"12p","C3,C4","Capacitor_SMD:C_0402_1005Metric","C1547"
|
||||||
"LL4148","D1","Diode_SMD:D_MiniMELF","C3011166"
|
"LL4148","D1","Diode_SMD:D_MiniMELF","C9808"
|
||||||
"LED","D2","LED_SMD:LED_0603_1608Metric","C2286"
|
"LED","D2","LED_SMD:LED_0603_1608Metric","C2286"
|
||||||
"MMBT3906","Q1","Package_TO_SOT_SMD:SOT-23","C2910191"
|
"MMBT3906","Q1","Package_TO_SOT_SMD:SOT-23","C2910191"
|
||||||
"Q_Photo_NPN","Q4","snapeda:TR8","C146233"
|
"Q_Photo_NPN","Q4","snapeda:TR8","C146233"
|
||||||
|
|
|
||||||
|
|
|
@ -1027,7 +1027,7 @@
|
||||||
(at 66.742 55.536 180)
|
(at 66.742 55.536 180)
|
||||||
(descr "Diode Mini-MELF")
|
(descr "Diode Mini-MELF")
|
||||||
(tags "Diode Mini-MELF")
|
(tags "Diode Mini-MELF")
|
||||||
(property "LCSC" "C3011166")
|
(property "LCSC" "C9808")
|
||||||
(property "Sheetfile" "parasite.kicad_sch")
|
(property "Sheetfile" "parasite.kicad_sch")
|
||||||
(property "Sheetname" "")
|
(property "Sheetname" "")
|
||||||
(property "ki_description" "100V 0.15A standard switching diode, MiniMELF")
|
(property "ki_description" "100V 0.15A standard switching diode, MiniMELF")
|
||||||
|
|
|
||||||
|
|
@ -1963,10 +1963,10 @@
|
||||||
(property "Footprint" "Diode_SMD:D_MiniMELF" (at 63.5 111.125 0)
|
(property "Footprint" "Diode_SMD:D_MiniMELF" (at 63.5 111.125 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(property "Datasheet" "https://datasheet.lcsc.com/lcsc/2205131645_JUXING-LL4148_C3011166.pdf" (at 63.5 115.57 0)
|
(property "Datasheet" "http://www.vishay.com/docs/85557/ll4148.pdf" (at 63.5 115.57 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(property "LCSC" "C3011166" (at 63.5 115.57 0)
|
(property "LCSC" "C9808" (at 63.5 115.57 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(pin "1" (uuid b7ede69c-719d-4a3e-977e-6b4e4c5e39dd))
|
(pin "1" (uuid b7ede69c-719d-4a3e-977e-6b4e4c5e39dd))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue