Compare commits
45 commits
zb-bug-rep
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5214f904f1 | ||
|
|
20693143ae | ||
|
|
2e5f89b228 | ||
|
|
2dc7144de1 | ||
|
|
5f671b0170 | ||
|
|
21dd14d7f3 | ||
|
|
f8c28cebd6 | ||
|
|
8ef2b5b748 | ||
|
|
4e0f3911bd | ||
|
|
20d98d02a0 | ||
|
|
ccdbaaf142 | ||
|
|
57cf5aa0e5 | ||
|
|
e7e4b77eef | ||
|
|
dc02480da9 | ||
|
|
4796bfab5f | ||
|
|
e62521d2ae | ||
|
|
16c4d23c47 | ||
|
|
15920b1ae4 | ||
|
|
d26eab5825 | ||
|
|
c7aaf5b388 | ||
|
|
905978e8c9 | ||
|
|
4c0fe9b4c6 | ||
|
|
dd373ea235 | ||
|
|
25a5941777 | ||
|
|
37ea3a1062 | ||
|
|
d3ddd089bd | ||
|
|
28c2809b04 | ||
|
|
ad3cd4194f | ||
|
|
171a1eb4a0 | ||
|
|
5199ceaa50 | ||
|
|
7de5115705 | ||
|
|
d5ed701c45 | ||
|
|
141071a414 | ||
|
|
35618227d5 | ||
|
|
77c204397e | ||
|
|
5d2b648b22 | ||
|
|
da1642514a | ||
|
|
85ca1a67bc | ||
|
|
e68c113513 | ||
|
|
e0481994b2 | ||
|
|
9ea5c7b4d0 | ||
|
|
1a5acd02a5 | ||
|
|
8fb45f7165 | ||
|
|
9fdd15626a | ||
|
|
c70eb600a3 |
30 changed files with 226 additions and 189 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "nrf-connect:v2.2",
|
||||
"image": "nordicplayground/nrfconnect-sdk:v2.2-branch",
|
||||
"name": "nrf-connect:v2.4",
|
||||
"image": "nordicplayground/nrfconnect-sdk:v2.5-branch",
|
||||
"features": {
|
||||
},
|
||||
"customizations": {
|
||||
|
|
|
|||
5
.github/actions/build/Dockerfile
vendored
5
.github/actions/build/Dockerfile
vendored
|
|
@ -1,5 +0,0 @@
|
|||
FROM nordicplayground/nrfconnect-sdk:v2.2-branch
|
||||
|
||||
COPY build.sh /build.sh
|
||||
|
||||
ENTRYPOINT ["/build.sh"]
|
||||
38
.github/actions/build/action.yml
vendored
38
.github/actions/build/action.yml
vendored
|
|
@ -1,27 +1,27 @@
|
|||
name: 'Build'
|
||||
description: 'Builds a nrf-connect sample for b-parasite'
|
||||
name: "Build"
|
||||
description: "Builds a nrf-connect sample for b-parasite"
|
||||
inputs:
|
||||
sample-dir:
|
||||
description: 'Sample directory to build'
|
||||
description: "Sample directory to build"
|
||||
required: true
|
||||
board:
|
||||
description: 'Board definition to use'
|
||||
description: "Board definition to use"
|
||||
default: bparasite_nrf52840
|
||||
revision:
|
||||
description: 'Board revision use'
|
||||
default: '1.2.0'
|
||||
description: "Board revision use"
|
||||
default: "2.0.0"
|
||||
cmake-extra:
|
||||
description: 'Extra CMake arguments'
|
||||
default: ''
|
||||
output-bin:
|
||||
description: 'Name of the .hex output'
|
||||
required: true
|
||||
description: "Extra CMake arguments"
|
||||
default: ""
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
args:
|
||||
- ${{ inputs.sample-dir }}
|
||||
- ${{ inputs.board }}
|
||||
- ${{ inputs.revision }}
|
||||
- ${{ inputs.cmake-extra }}
|
||||
- ${{ inputs.output-bin }}
|
||||
using: "composite"
|
||||
steps:
|
||||
- run: |
|
||||
docker run --rm -v ${GITHUB_WORKSPACE}:/repo \
|
||||
nordicplayground/nrfconnect-sdk:v2.5-branch \
|
||||
west build \
|
||||
--build-dir /repo/${{ inputs.sample-dir }}/build \
|
||||
--pristine \
|
||||
--board ${{ inputs.board }}@${{ inputs.revision }} \
|
||||
/repo/${{ inputs.sample-dir }} -- ${{ inputs.cmake-extra }}
|
||||
shell: bash
|
||||
|
|
|
|||
21
.github/actions/build/build.sh
vendored
21
.github/actions/build/build.sh
vendored
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -eux -o pipefail
|
||||
|
||||
SAMPLE_DIR=$1
|
||||
BOARD=$2
|
||||
REVISION=$3
|
||||
CMAKE_EXTRA=$4
|
||||
OUTPUT_BIN=$5
|
||||
|
||||
TODAY=$(date +'%Y-%m-%d')
|
||||
|
||||
# Replaces occurrences of "__TODAY__" with $TODAY in $CMAKE_EXTRA.
|
||||
CMAKE_EXTRA="${CMAKE_EXTRA/__TODAY__/"$TODAY"}"
|
||||
|
||||
cd "${GITHUB_WORKSPACE}/${SAMPLE_DIR}"
|
||||
|
||||
echo $CMAKE_EXTRA
|
||||
|
||||
west build --build-dir ./build --pristine --board "${BOARD}@${REVISION}" -- $CMAKE_EXTRA
|
||||
|
||||
mv build/zephyr/zephyr.hex build/zephyr/"${OUTPUT_BIN}"
|
||||
33
.github/actions/build_and_upload/action.yml
vendored
33
.github/actions/build_and_upload/action.yml
vendored
|
|
@ -1,33 +0,0 @@
|
|||
name: 'Build and upload artifact'
|
||||
description: 'Builds a nrf-connect sample for b-parasite'
|
||||
inputs:
|
||||
sample-dir:
|
||||
description: 'Sample directory to build'
|
||||
required: true
|
||||
board:
|
||||
description: 'Board definition to use'
|
||||
required: true
|
||||
revision:
|
||||
description: 'Board revision use'
|
||||
default: '1.2.0'
|
||||
cmake-extra:
|
||||
description: 'Extra CMake arguments'
|
||||
default: ''
|
||||
output-bin:
|
||||
description: 'Name of the .hex output'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: ./.github/actions/build
|
||||
with:
|
||||
sample-dir: ${{ inputs.sample-dir }}
|
||||
board: ${{ inputs.board }}
|
||||
revision: ${{ inputs.revision }}
|
||||
cmake-extra: ${{ inputs.cmake-extra }}
|
||||
output-bin: ${{ inputs.output-bin }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sample-binaries
|
||||
path: ${{ inputs.sample-dir }}/build/zephyr/${{ inputs.output-bin }}
|
||||
18
.github/workflows/b-parasite.yml
vendored
18
.github/workflows/b-parasite.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Check clang-format
|
||||
uses: jidicula/clang-format-action@v4.9.0
|
||||
with:
|
||||
check-path: 'code/nrf-connect'
|
||||
check-path: "code/nrf-connect"
|
||||
exclude-regex: '\/build\/'
|
||||
|
||||
build-blinky:
|
||||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
- lint
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build blinky
|
||||
uses: ./.github/actions/build
|
||||
with:
|
||||
|
|
@ -43,7 +43,7 @@ jobs:
|
|||
- lint
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build input
|
||||
uses: ./.github/actions/build
|
||||
with:
|
||||
|
|
@ -59,7 +59,7 @@ jobs:
|
|||
- lint
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build soil_read_loop
|
||||
uses: ./.github/actions/build
|
||||
with:
|
||||
|
|
@ -79,14 +79,14 @@ jobs:
|
|||
- lint
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
uses: ./.github/actions/build_and_upload
|
||||
uses: ./.github/actions/build
|
||||
with:
|
||||
sample-dir: code/nrf-connect/samples/ble
|
||||
board: bparasite_${{ matrix.soc }}
|
||||
revision: ${{ matrix.revision }}
|
||||
cmake-extra: -DCONFIG_PRST_BLE_ENCODING_BTHOME_V2=y -DCONFIG_PRST_SLEEP_DURATION_SEC=1 -DCONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
||||
cmake-extra: -DCONFIG_PRST_BLE_ENCODING_BTHOME_V2=y -DCONFIG_PRST_SLEEP_DURATION_MSEC=1000 -DCONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
||||
output-bin: ble_${{ matrix.soc }}_${{ matrix.revision }}_debug.hex
|
||||
|
||||
build-zigbee:
|
||||
|
|
@ -100,9 +100,9 @@ jobs:
|
|||
- lint
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
uses: ./.github/actions/build_and_upload
|
||||
uses: ./.github/actions/build
|
||||
with:
|
||||
sample-dir: code/nrf-connect/samples/zigbee
|
||||
board: bparasite_${{ matrix.soc }}
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -10,7 +10,7 @@ b-parasite is an open source soil moisture and ambient temperature/humidity/ligh
|
|||
# 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
|
||||
* 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://everlighteurope.com/ambient-light-sensors/7/ALSPT19315CL177TR8.html) phototransistor
|
||||
* 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
|
||||
* 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
|
||||
* Open hardware and open source design
|
||||
|
|
@ -20,7 +20,7 @@ This repository also hosts a few different firmware samples for b-parasite.
|
|||
|
||||
|Sample|Description|Extra Documentation|
|
||||
|---|---|---|
|
||||
|[samples/ble](./code/nrf-connect/samples/ble)|This is the most battle-tested and useful firmware. It periodically reads all sensors and broadcast them via Bluetooth Low Energy (BLE). It works with [Home Assistant](https://www.home-assistant.io/) out of the box. |[Docs](./code/nrf-connect/samples/ble/README.md)|
|
||||
|[samples/ble](./code/nrf-connect/samples/ble)|This is the most battle-tested and useful firmware. It periodically reads all sensors and broadcast them via Bluetooth Low Energy (BLE). It works with [Home Assistant](https://www.home-assistant.io/) + [BTHome](https://bthome.io/) out of the box. |[Docs](./code/nrf-connect/samples/ble/README.md)|
|
||||
|[samples/zigbee](./code/nrf-connect/samples/zigbee)| An experimental/educational/exploratory basic Zigbee sample built on [nRF Connect + ZBOSS](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_zigbee.html). It integrates with [Home Assistant](https://www.home-assistant.io/) via [ZHA](https://www.home-assistant.io/integrations/zha) or [Zigbee2MQTT](https://www.zigbee2mqtt.io/). |[Docs](./code/nrf-connect/samples/zigbee/README.md)|
|
||||
|[samples/blinky](./code/nrf-connect/samples/blinky)| The classic "Hello, world" |-|
|
||||
|[samples/soil_read_loop](./code/nrf-connect/samples/soil_read_loop)| Reads the soil moisture sensor on a loop. Useful for experimenting and calibrating the sensor. |-|
|
||||
|
|
@ -49,6 +49,12 @@ We have three different 3D-printable cases:
|
|||
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)
|
||||
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
|
||||
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/).
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&uicr {
|
||||
gpio-as-nreset;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -135,7 +139,6 @@
|
|||
|
||||
|
||||
&flash0 {
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
|
|
@ -143,33 +146,23 @@
|
|||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x0000C000>;
|
||||
reg = <0x000000000 0xC000>;
|
||||
};
|
||||
slot0_partition: partition@c000 {
|
||||
label = "image-0";
|
||||
reg = <0x0000C000 0x00067000>;
|
||||
reg = <0x0000C000 0x32000>;
|
||||
};
|
||||
slot1_partition: partition@73000 {
|
||||
slot1_partition: partition@3e000 {
|
||||
label = "image-1";
|
||||
reg = <0x00073000 0x00067000>;
|
||||
reg = <0x0003E000 0x32000>;
|
||||
};
|
||||
scratch_partition: partition@da000 {
|
||||
scratch_partition: partition@70000 {
|
||||
label = "image-scratch";
|
||||
reg = <0x000da000 0x0001e000>;
|
||||
reg = <0x00070000 0xA000>;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
storage_partition: partition@7a000 {
|
||||
label = "storage";
|
||||
reg = <0x000f8000 0x00008000>;
|
||||
reg = <0x0007A000 0x00006000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -16,6 +16,4 @@ CONFIG_GPIO=y
|
|||
CONFIG_CONSOLE=y
|
||||
CONFIG_RTT_CONSOLE=y
|
||||
|
||||
CONFIG_GPIO_AS_PINRESET=y
|
||||
|
||||
CONFIG_PINCTRL=y
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&uicr {
|
||||
gpio-as-nreset;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,4 @@ CONFIG_GPIO=y
|
|||
CONFIG_CONSOLE=y
|
||||
CONFIG_RTT_CONSOLE=y
|
||||
|
||||
CONFIG_GPIO_AS_PINRESET=y
|
||||
|
||||
CONFIG_PINCTRL=y
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static int read_adc_spec(const struct adc_dt_spec* spec, prst_adc_read_t* out) {
|
|||
|
||||
int32_t val_mv = buf;
|
||||
RET_IF_ERR(adc_raw_to_millivolts_dt(spec, &val_mv));
|
||||
val_mv = MAX(0, val_mv);
|
||||
|
||||
out->raw = buf;
|
||||
out->millivolts = val_mv;
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ int prst_sensors_read_all(prst_sensors_t *sensors) {
|
|||
|
||||
LOG_DBG("Batt: %d mV (%.2f%%)", sensors->batt.adc_read.millivolts,
|
||||
100 * sensors->batt.percentage);
|
||||
LOG_DBG("Soil: %.0f %% (%d mV)", 100 * sensors->soil.percentage,
|
||||
sensors->soil.adc_read.millivolts);
|
||||
LOG_DBG("Soil: %.0f %%", 100 * sensors->soil.percentage);
|
||||
LOG_DBG("Photo: %u lx (%d mV)", sensors->photo.brightness,
|
||||
sensors->soil.adc_read.millivolts);
|
||||
sensors->photo.adc_read.millivolts);
|
||||
LOG_DBG("Temp: %f oC", sensors->shtc3.temp_c);
|
||||
LOG_DBG("Humi: %.0f %%", 100 * sensors->shtc3.rel_humi);
|
||||
LOG_DBG("--------------------------------------------------");
|
||||
|
|
|
|||
|
|
@ -32,11 +32,10 @@ int prst_shtc3_read(prst_shtc3_read_t *out) {
|
|||
|
||||
// Reading in normal (not low power) mode can take up to 12.1 ms, according to
|
||||
// the datasheet.
|
||||
k_msleep(15);
|
||||
k_msleep(20);
|
||||
|
||||
while (i2c_read_dt(&shtc3, buff, 6) != 0) {
|
||||
k_msleep(10);
|
||||
}
|
||||
// Read response.
|
||||
RET_IF_ERR(i2c_read_dt(&shtc3, buff, 6));
|
||||
|
||||
// Put the sensor in sleep mode.
|
||||
RET_IF_ERR(write_cmd(PRST_SHTC3_CMD_SLEEP));
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
source "Kconfig.zephyr"
|
||||
rsource "../../prstlib/Kconfig"
|
||||
|
||||
config PRST_SLEEP_DURATION_SEC
|
||||
int "Sleep duration in seconds"
|
||||
default 600
|
||||
config PRST_SLEEP_DURATION_MSEC
|
||||
int "Sleep duration in milliseconds"
|
||||
default 600000
|
||||
|
||||
config PRST_BLE_ADV_DURATION_SEC
|
||||
int "Advertising duration in seconds"
|
||||
default 1
|
||||
config PRST_BLE_ADV_DURATION_MSEC
|
||||
int "Advertising duration in milliseconds"
|
||||
default 1000
|
||||
|
||||
config PRST_BLE_MIN_ADV_INTERVAL
|
||||
int "Minimum advertising interval in milliseconds"
|
||||
|
|
@ -20,7 +20,7 @@ config PRST_BLE_MAX_ADV_INTERVAL
|
|||
|
||||
choice PRST_BLE_ENCODING
|
||||
prompt "b-parasite BLE encoding"
|
||||
default PRST_BLE_ENCODING_BPARASITE_V2
|
||||
default PRST_BLE_ENCODING_BTHOME_V2
|
||||
|
||||
config PRST_BLE_ENCODING_BPARASITE_V2
|
||||
bool "Uses the custom b-parasite protocol v2 for encoding advertising packets"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Bluetooth Low Energy (BLE)
|
||||
In this saple, b-parasite sensors are periodically read and broadcast using Bluetooth Low Energy (BLE) dvertising packets.
|
||||
In this sample, b-parasite sensors are periodically read and broadcast using Bluetooth Low Energy (BLE) dvertising packets.
|
||||
|
||||
## Configuration
|
||||
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.
|
||||
|
||||
### Advertising Duration
|
||||
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.
|
||||
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.
|
||||
|
||||
### Advertising Packet Encoding
|
||||
There are different ways to encode the sensor data in a BLE advertising packet.
|
||||
|
|
@ -22,11 +22,10 @@ This is what a typical deployment with BTHome looks like:
|
|||

|
||||
|
||||
There are two versions of BTHome encodings supported by this sample:
|
||||
* `PRST_BLE_ENCODING_BTHOME_V2=y` (**default**) uses the [BTHome V2](https://bthome.io/format/), supported by Home Assistant since version `2022.12`
|
||||
* `PRST_BLE_ENCODING_BTHOME_V1=y` uses the [legacy BTHome V1](https://bthome.io/v1/), which was briefly in use
|
||||
* `PRST_BLE_ENCODING_BTHOME_V2=y` uses the [BTHome V2](https://bthome.io/format/), which is not yet (as of early Dec/2022) in the stable Home Assistant release. This will soon become the default.
|
||||
|
||||
#### b-parasite Encoding
|
||||
`PRST_BLE_ENCODING_BPARASITE_V2=y` selects the "legacy" encoding, used historically inn this project. This is the encoding that the [`b_parasite`](https://esphome.io/components/sensor/b_parasite.html) ESPHome component understands.
|
||||
`PRST_BLE_ENCODING_BPARASITE_V2=y` selects the legacy encoding, used historically in this project. This is the encoding that the [`b_parasite`](https://esphome.io/components/sensor/b_parasite.html) ESPHome component understands.
|
||||
|
||||
With this encoding and a ESPHome + `b_parasite` component, this is an usual deployment topology:
|
||||
|
||||
|
|
@ -53,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.
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ CONFIG_BT_DEVICE_NAME="prst"
|
|||
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
|
||||
|
||||
CONFIG_SERIAL=n
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
||||
CONFIG_NEWLIB_LIBC=y
|
||||
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
|
||||
|
||||
CONFIG_ASSERT=y
|
||||
|
||||
# Application config - see all options in Kconfig.
|
||||
# CONFIG_PRST_BLE_ENCODING_BTHOME_V2=y
|
||||
# CONFIG_PRST_SLEEP_DURATION_SEC=1
|
||||
# CONFIG_PRST_SLEEP_DURATION_MSEC=1000
|
||||
|
||||
# prstlib config - ser all options in prstlib/Kconfig.
|
||||
# CONFIG_PRSTLIB_LOG_LEVEL_DBG=y
|
||||
|
|
|
|||
|
|
@ -104,33 +104,36 @@ int prst_ble_encode_service_data(const prst_sensors_t* sensors,
|
|||
out[4] = temp_val & 0xff;
|
||||
out[5] = temp_val >> 8;
|
||||
// Humidity.
|
||||
out[6] = 0x03;
|
||||
// Value. Factor 0.01, over 100%.
|
||||
uint16_t humi_val = 10000 * sensors->shtc3.rel_humi;
|
||||
out[7] = humi_val & 0xff;
|
||||
out[8] = humi_val >> 8;
|
||||
out[6] = 0x2E;
|
||||
// Value. Factor 1 over 100%.
|
||||
uint8_t humi_val = 100 * sensors->shtc3.rel_humi + 0.5f;
|
||||
out[7] = humi_val;
|
||||
// Illuminance.
|
||||
out[9] = 0x05;
|
||||
out[8] = 0x05;
|
||||
// Value. Factor of 0.01.
|
||||
uint32_t lux_val = sensors->photo.brightness * 100;
|
||||
out[10] = lux_val & 0xff;
|
||||
out[11] = (lux_val >> 8) & 0xff;
|
||||
out[12] = (lux_val >> 16) & 0xff;
|
||||
out[9] = lux_val & 0xff;
|
||||
out[10] = (lux_val >> 8) & 0xff;
|
||||
out[11] = (lux_val >> 16) & 0xff;
|
||||
// Battery voltage.
|
||||
out[13] = 0x0c;
|
||||
out[12] = 0x0c;
|
||||
// Value. Factor of 0.001.
|
||||
uint16_t batt_val = sensors->batt.adc_read.millivolts;
|
||||
out[14] = batt_val & 0xff;
|
||||
out[15] = batt_val >> 8;
|
||||
out[13] = batt_val & 0xff;
|
||||
out[14] = batt_val >> 8;
|
||||
// Soil moisture.
|
||||
out[16] = 0x14;
|
||||
// Factor of 0.01, so we need to multiply our the value in 100% by 1/0.01 = 100.
|
||||
uint16_t soil_val = 10000 * sensors->soil.percentage;
|
||||
out[17] = soil_val & 0xff;
|
||||
out[18] = soil_val >> 8;
|
||||
out[15] = 0x2F;
|
||||
// Factor of 1 over 100%
|
||||
uint8_t soil_val = 100 * sensors->soil.percentage + 0.5f;
|
||||
out[16] = soil_val;
|
||||
// Battery percentage.
|
||||
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
|
||||
|
||||
LOG_HEXDUMP_DBG(out, out_len, "Encoded BLE adv: ");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,25 +14,29 @@
|
|||
|
||||
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
|
||||
|
||||
int main(void) {
|
||||
static int prst_init() {
|
||||
RET_IF_ERR(prst_adc_init());
|
||||
RET_IF_ERR(prst_led_init());
|
||||
RET_IF_ERR(prst_button_init());
|
||||
RET_IF_ERR(prst_ble_init());
|
||||
return 0;
|
||||
}
|
||||
|
||||
RET_IF_ERR(prst_led_flash(2));
|
||||
static int prst_loop(prst_sensors_t *sensors) {
|
||||
RET_IF_ERR(prst_sensors_read_all(sensors));
|
||||
RET_IF_ERR(prst_ble_adv_set_data(sensors));
|
||||
RET_IF_ERR(prst_ble_adv_start());
|
||||
k_msleep(CONFIG_PRST_BLE_ADV_DURATION_MSEC);
|
||||
RET_IF_ERR(prst_ble_adv_stop());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
__ASSERT(!prst_init(), "Error in prst_init()");
|
||||
prst_led_flash(2);
|
||||
prst_sensors_t sensors;
|
||||
while (true) {
|
||||
RET_IF_ERR(prst_sensors_read_all(&sensors));
|
||||
|
||||
RET_IF_ERR(prst_ble_adv_set_data(&sensors));
|
||||
RET_IF_ERR(prst_ble_adv_start());
|
||||
|
||||
k_sleep(K_SECONDS(CONFIG_PRST_BLE_ADV_DURATION_SEC));
|
||||
|
||||
RET_IF_ERR(prst_ble_adv_stop());
|
||||
|
||||
k_sleep(K_SECONDS(CONFIG_PRST_SLEEP_DURATION_SEC));
|
||||
__ASSERT(!prst_loop(&sensors), "Error in prst_loop()");
|
||||
k_msleep(CONFIG_PRST_SLEEP_DURATION_MSEC);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ CONFIG_GPIO=y
|
|||
CONFIG_CBPRINTF_FP_SUPPORT=y
|
||||
|
||||
CONFIG_SERIAL=n
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,4 @@ CONFIG_PWM_LOG_LEVEL_DBG=y
|
|||
CONFIG_CBPRINTF_FP_SUPPORT=y
|
||||
CONFIG_ADC=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ target_sources(app PRIVATE
|
|||
src/prst_zb_attrs.c
|
||||
src/prst_zb_soil_moisture_defs.c
|
||||
src/restart_handler.c
|
||||
src/watchdog.c
|
||||
)
|
||||
|
||||
add_subdirectory(../../prstlib prstlib)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ CONFIG_FLASH_PAGE_LAYOUT=y
|
|||
CONFIG_FILE_SYSTEM=y
|
||||
CONFIG_FILE_SYSTEM_LITTLEFS=y
|
||||
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_HWINFO=y
|
||||
CONFIG_ASSERT=y
|
||||
|
||||
# Uncomment for debug log level.
|
||||
# CONFIG_LOG_DEFAULT_LEVEL=4
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
|
|||
static struct fs_mount_t lfs_storage_mnt = {
|
||||
.type = FS_LITTLEFS,
|
||||
.fs_data = &storage,
|
||||
.storage_dev = (void *)FLASH_AREA_ID(storage),
|
||||
.storage_dev = (void *)FIXED_PARTITION_ID(storage_partition),
|
||||
.mnt_point = "/lfs",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <zboss_api.h>
|
||||
#include <zboss_api_addons.h>
|
||||
#include <zcl/zb_zcl_power_config.h>
|
||||
#include <zephyr/drivers/hwinfo.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zigbee/zigbee_app_utils.h>
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
#include "prst_zb_endpoint_defs.h"
|
||||
#include "prst_zb_soil_moisture_defs.h"
|
||||
#include "restart_handler.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
|
|
@ -132,14 +134,15 @@ void update_sensors_cb(zb_uint8_t arg) {
|
|||
ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000 * CONFIG_PRST_ZB_SLEEP_DURATION_SEC));
|
||||
if (ret != RET_OK) {
|
||||
prst_debug_counters_increment("sens_cb_schedule_err");
|
||||
zb_reset(0);
|
||||
__ASSERT(false, "Unable to schedule sensor update callback");
|
||||
}
|
||||
|
||||
__ASSERT(!prst_watchdog_feed(), "Failed to feed watchdog");
|
||||
|
||||
prst_debug_counters_increment("sensors_read_before");
|
||||
if (prst_sensors_read_all(&sensors)) {
|
||||
prst_debug_counters_increment("sensors_read_error");
|
||||
LOG_ERR("Unable to read sensors");
|
||||
return;
|
||||
__ASSERT(false, "Unable to read sensors");
|
||||
}
|
||||
prst_debug_counters_increment("sensors_read_after");
|
||||
|
||||
|
|
@ -227,9 +230,10 @@ void zboss_signal_handler(zb_bufid_t bufid) {
|
|||
k_timer_start(&led_flashing_timer, K_NO_WAIT, K_SECONDS(1));
|
||||
|
||||
// Kick off main sensor update task.
|
||||
ZB_SCHEDULE_APP_ALARM(update_sensors_cb,
|
||||
/*param=*/0,
|
||||
ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000));
|
||||
ZB_ERROR_CHECK(ZB_SCHEDULE_APP_ALARM(update_sensors_cb,
|
||||
/*param=*/0,
|
||||
ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000)));
|
||||
__ASSERT_NO_MSG(!prst_watchdog_start());
|
||||
break;
|
||||
}
|
||||
case ZB_NLME_STATUS_INDICATION: {
|
||||
|
|
@ -255,10 +259,40 @@ void zboss_signal_handler(zb_bufid_t bufid) {
|
|||
}
|
||||
}
|
||||
|
||||
void log_counter(const char *counter_name, prst_debug_counter_t value) {
|
||||
void dump_counter(const char *counter_name, prst_debug_counter_t value) {
|
||||
LOG_INF("- %s: %d", counter_name, value);
|
||||
}
|
||||
|
||||
int log_reset_reason_counter() {
|
||||
uint32_t cause;
|
||||
const char *reset_counter_str = "reset_cause_unknown";
|
||||
RET_IF_ERR(hwinfo_get_reset_cause(&cause));
|
||||
RET_IF_ERR(hwinfo_clear_reset_cause());
|
||||
if (cause & RESET_PIN) {
|
||||
reset_counter_str = "reset_cause_pin";
|
||||
} else if (cause & RESET_SOFTWARE) {
|
||||
// Includes fatal errors from __ASSERT, ZB_ERROR_CHECK and friends.
|
||||
reset_counter_str = "reset_cause_software";
|
||||
} else if (cause & RESET_BROWNOUT) {
|
||||
reset_counter_str = "reset_cause_brownout";
|
||||
} else if (cause & RESET_POR) {
|
||||
reset_counter_str = "reset_cause_power_on";
|
||||
} else if (cause & RESET_WATCHDOG) {
|
||||
reset_counter_str = "reset_cause_watchdog";
|
||||
} else if (cause & RESET_DEBUG) {
|
||||
reset_counter_str = "reset_cause_debug";
|
||||
} else if (cause & RESET_LOW_POWER_WAKE) {
|
||||
reset_counter_str = "reset_cause_low_power";
|
||||
} else if (cause & RESET_CPU_LOCKUP) {
|
||||
reset_counter_str = "reset_cause_cpu_lockup";
|
||||
} else if (cause & RESET_HARDWARE) {
|
||||
reset_counter_str = "reset_cause_hardware";
|
||||
} else if (cause & RESET_USER) {
|
||||
reset_counter_str = "reset_cause_user";
|
||||
}
|
||||
return prst_debug_counters_increment(reset_counter_str);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
RET_IF_ERR(prst_adc_init());
|
||||
RET_IF_ERR(prst_led_init());
|
||||
|
|
@ -267,20 +301,22 @@ int main(void) {
|
|||
RET_IF_ERR(prst_debug_counters_init());
|
||||
|
||||
// Initialize sensors - quickly put them into low power mode.
|
||||
RET_IF_ERR(prst_sensors_read_all(&sensors));
|
||||
__ASSERT_NO_MSG(!prst_sensors_read_all(&sensors));
|
||||
|
||||
prst_debug_counters_increment("boot");
|
||||
|
||||
LOG_INF("Dumping debug counters:");
|
||||
prst_debug_counters_get_all(log_counter);
|
||||
log_reset_reason_counter();
|
||||
|
||||
RET_IF_ERR(prst_zb_factory_reset_check());
|
||||
LOG_INF("Dumping debug counters:");
|
||||
prst_debug_counters_get_all(dump_counter);
|
||||
|
||||
__ASSERT_NO_MSG(!prst_zb_factory_reset_check());
|
||||
|
||||
prst_zb_attrs_init(&dev_ctx);
|
||||
|
||||
ZB_AF_REGISTER_DEVICE_CTX(&app_template_ctx);
|
||||
|
||||
RET_IF_ERR(prst_led_flash(2));
|
||||
prst_led_flash(2);
|
||||
k_msleep(100);
|
||||
|
||||
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(PRST_ZIGBEE_ENDPOINT, identify_cb);
|
||||
|
|
|
|||
47
code/nrf-connect/samples/zigbee/src/watchdog.c
Normal file
47
code/nrf-connect/samples/zigbee/src/watchdog.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include "watchdog.h"
|
||||
|
||||
#include <prstlib/macros.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/watchdog.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#define PRST_ZB_WATCHDOG_TIMEOUT_SEC (2 * CONFIG_PRST_ZB_SLEEP_DURATION_SEC)
|
||||
|
||||
LOG_MODULE_REGISTER(watchdog, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
typedef struct {
|
||||
const struct device *const wdt;
|
||||
int wtd_channel_id;
|
||||
} wtd_data_t;
|
||||
|
||||
static wtd_data_t wtd_data = {
|
||||
.wdt = DEVICE_DT_GET(DT_NODELABEL(wdt)),
|
||||
};
|
||||
|
||||
int prst_watchdog_start() {
|
||||
static const struct wdt_timeout_cfg wdt_settings = {
|
||||
.window = {
|
||||
.min = 0,
|
||||
.max = PRST_ZB_WATCHDOG_TIMEOUT_SEC * MSEC_PER_SEC,
|
||||
},
|
||||
// NULL callback means use the default, which is the system reset.
|
||||
.callback = NULL,
|
||||
.flags = WDT_FLAG_RESET_SOC};
|
||||
|
||||
RET_IF_ERR(!device_is_ready(wtd_data.wdt));
|
||||
|
||||
// Install timeout.
|
||||
wtd_data.wtd_channel_id = wdt_install_timeout(wtd_data.wdt, &wdt_settings);
|
||||
RET_CHECK(wtd_data.wtd_channel_id >= 0, "Failed to install watchdog timeout.");
|
||||
|
||||
// Start watchdog.
|
||||
RET_IF_ERR(wdt_setup(wtd_data.wdt, WDT_OPT_PAUSE_HALTED_BY_DBG));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int prst_watchdog_feed() {
|
||||
RET_IF_ERR(wdt_feed(wtd_data.wdt, wtd_data.wtd_channel_id));
|
||||
return 0;
|
||||
}
|
||||
8
code/nrf-connect/samples/zigbee/src/watchdog.h
Normal file
8
code/nrf-connect/samples/zigbee/src/watchdog.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _PRST_ZB_WATCHDOG_H_
|
||||
#define _PRST_ZB_WATCHDOG_H_
|
||||
|
||||
int prst_watchdog_start();
|
||||
|
||||
int prst_watchdog_feed();
|
||||
|
||||
#endif // _PRST_ZB_WATCHDOG_H_
|
||||
|
|
@ -3,7 +3,7 @@ Comment,Designator,Footprint,LCSC
|
|||
"1n","C1","Capacitor_SMD:C_0402_1005Metric","C1523"
|
||||
"100n","C2","Capacitor_SMD:C_0402_1005Metric","C1525"
|
||||
"12p","C3,C4","Capacitor_SMD:C_0402_1005Metric","C1547"
|
||||
"LL4148","D1","Diode_SMD:D_MiniMELF","C9808"
|
||||
"LL4148","D1","Diode_SMD:D_MiniMELF","C3011166"
|
||||
"LED","D2","LED_SMD:LED_0603_1608Metric","C2286"
|
||||
"MMBT3906","Q1","Package_TO_SOT_SMD:SOT-23","C2910191"
|
||||
"Q_Photo_NPN","Q4","snapeda:TR8","C146233"
|
||||
|
|
|
|||
|
|
|
@ -1027,7 +1027,7 @@
|
|||
(at 66.742 55.536 180)
|
||||
(descr "Diode Mini-MELF")
|
||||
(tags "Diode Mini-MELF")
|
||||
(property "LCSC" "C9808")
|
||||
(property "LCSC" "C3011166")
|
||||
(property "Sheetfile" "parasite.kicad_sch")
|
||||
(property "Sheetname" "")
|
||||
(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)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "http://www.vishay.com/docs/85557/ll4148.pdf" (at 63.5 115.57 0)
|
||||
(property "Datasheet" "https://datasheet.lcsc.com/lcsc/2205131645_JUXING-LL4148_C3011166.pdf" (at 63.5 115.57 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "LCSC" "C9808" (at 63.5 115.57 0)
|
||||
(property "LCSC" "C3011166" (at 63.5 115.57 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid b7ede69c-719d-4a3e-977e-6b4e4c5e39dd))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue