Compare commits
3 Commits
goodby-esp
...
containeri
Author | SHA1 | Date | |
---|---|---|---|
50a052df9a
|
|||
c4820e8035
|
|||
31b6f8633c
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
CONTAINER_NAME="localhost/wch-dev-tools:latest"
|
CONTAINER_NAME="localhost/esp-plant-dev-tools:latest"
|
||||||
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
|
||||||
pushd "$CONTAINER_TOOLS_BASEDIR"
|
pushd "$CONTAINER_TOOLS_BASEDIR"
|
||||||
podman build -t "$CONTAINER_NAME" -f "../wch-tools.Containerfile" .
|
podman build -t "$CONTAINER_NAME" -f "esp-plant-dev-tools.Containerfile" .
|
||||||
popd
|
popd
|
16
bin/esp-plant-dev-tools.Containerfile
Normal file
16
bin/esp-plant-dev-tools.Containerfile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
FROM debian:latest
|
||||||
|
|
||||||
|
RUN apt update -y && apt upgrade -y && apt install unzip curl xz-utils nodejs -y
|
||||||
|
|
||||||
|
RUN cd /root && \
|
||||||
|
curl -L -o xpack-riscv-toolchain.tar.gz "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.2.0-3/xpack-riscv-none-elf-gcc-14.2.0-3-linux-x64.tar.gz" && \
|
||||||
|
mkdir xpack-toolchain && \
|
||||||
|
tar -xvf xpack-riscv-toolchain.tar.gz -C xpack-toolchain --strip-components=1 && \
|
||||||
|
mv xpack-toolchain/bin/* /usr/local/bin && \
|
||||||
|
mv xpack-toolchain/lib/ /usr/local && \
|
||||||
|
mv xpack-toolchain/lib64/ /usr/local && \
|
||||||
|
mv xpack-toolchain/libexec /usr/local && \
|
||||||
|
mv xpack-toolchain/riscv-none-elf /usr/local && \
|
||||||
|
rm -rf xpack-toolchain xpack-riscv-toolchain.tar.gz
|
||||||
|
|
||||||
|
RUN apt install npm -y
|
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
CONTAINER_IMAGE="localhost/wch-dev-tools:latest"
|
CONTAINER_IMAGE="localhost/esp-plant-dev-tools:latest"
|
||||||
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
PLANTCTL_PROJECT_DIR="$(readlink -f "$CONTAINER_TOOLS_BASEDIR/..")"
|
||||||
|
|
||||||
function _fatal {
|
function _fatal {
|
||||||
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
||||||
@@ -12,8 +13,7 @@ function _fatal {
|
|||||||
|
|
||||||
declare -a PODMAN_ARGS=(
|
declare -a PODMAN_ARGS=(
|
||||||
"--rm" "-i" "--log-driver=none"
|
"--rm" "-i" "--log-driver=none"
|
||||||
"--network=host"
|
"-v" "$PLANTCTL_PROJECT_DIR:$PLANTCTL_PROJECT_DIR:rw"
|
||||||
"--pid=host"
|
|
||||||
"-v" "$PWD:$PWD:rw"
|
"-v" "$PWD:$PWD:rw"
|
||||||
"-w" "$PWD"
|
"-w" "$PWD"
|
||||||
)
|
)
|
||||||
@@ -22,8 +22,8 @@ declare -a PODMAN_ARGS=(
|
|||||||
|
|
||||||
if ! podman image exists "$CONTAINER_IMAGE"; then
|
if ! podman image exists "$CONTAINER_IMAGE"; then
|
||||||
#attempt to build container
|
#attempt to build container
|
||||||
"$CONTAINER_TOOLS_BASEDIR/build-wch-tools-container.sh" 1>&2 ||
|
"$CONTAINER_TOOLS_BASEDIR/build-esp-plant-dev-tools.sh" 1>&2 ||
|
||||||
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
podman run "${PODMAN_ARGS[@]}" --entrypoint riscv-none-elf-gdb-py3 "$CONTAINER_IMAGE" "$@"
|
podman run "${PODMAN_ARGS[@]}" --entrypoint npm "$CONTAINER_IMAGE" "$@"
|
29
bin/npx
Executable file
29
bin/npx
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONTAINER_IMAGE="localhost/esp-plant-dev-tools:latest"
|
||||||
|
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
PLANTCTL_PROJECT_DIR="$(readlink -f "$CONTAINER_TOOLS_BASEDIR/..")"
|
||||||
|
|
||||||
|
function _fatal {
|
||||||
|
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare -a PODMAN_ARGS=(
|
||||||
|
"--rm" "-i" "--log-driver=none"
|
||||||
|
"-v" "$PLANTCTL_PROJECT_DIR:$PLANTCTL_PROJECT_DIR:rw"
|
||||||
|
"-v" "$PWD:$PWD:rw"
|
||||||
|
"-w" "$PWD"
|
||||||
|
)
|
||||||
|
|
||||||
|
[[ -t 1 ]] && PODMAN_ARGS+=("-t")
|
||||||
|
|
||||||
|
if ! podman image exists "$CONTAINER_IMAGE"; then
|
||||||
|
#attempt to build container
|
||||||
|
"$CONTAINER_TOOLS_BASEDIR/build-esp-plant-dev-tools.sh" 1>&2 ||
|
||||||
|
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
||||||
|
fi
|
||||||
|
|
||||||
|
podman run "${PODMAN_ARGS[@]}" --entrypoint npx "$CONTAINER_IMAGE" "$@"
|
29
bin/riscv32-unknown-elf-gcc
Executable file
29
bin/riscv32-unknown-elf-gcc
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONTAINER_IMAGE="localhost/esp-plant-dev-tools:latest"
|
||||||
|
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
PLANTCTL_PROJECT_DIR="$(readlink -f "$CONTAINER_TOOLS_BASEDIR/..")"
|
||||||
|
|
||||||
|
function _fatal {
|
||||||
|
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare -a PODMAN_ARGS=(
|
||||||
|
"--rm" "-i" "--log-driver=none"
|
||||||
|
"-v" "$PLANTCTL_PROJECT_DIR:$PLANTCTL_PROJECT_DIR:rw"
|
||||||
|
"-v" "$PWD:$PWD:rw"
|
||||||
|
"-w" "$PWD"
|
||||||
|
)
|
||||||
|
|
||||||
|
[[ -t 1 ]] && PODMAN_ARGS+=("-t")
|
||||||
|
|
||||||
|
if ! podman image exists "$CONTAINER_IMAGE"; then
|
||||||
|
#attempt to build container
|
||||||
|
"$CONTAINER_TOOLS_BASEDIR/build-esp-plant-dev-tools.sh" 1>&2 ||
|
||||||
|
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
||||||
|
fi
|
||||||
|
|
||||||
|
podman run "${PODMAN_ARGS[@]}" --entrypoint riscv-none-elf-gcc "$CONTAINER_IMAGE" "$@"
|
2
board/.gitignore
vendored
2
board/.gitignore
vendored
@@ -34,5 +34,3 @@ _autosave-*
|
|||||||
|
|
||||||
# Autorouter files (exported from Pcbnew)
|
# Autorouter files (exported from Pcbnew)
|
||||||
fp-info-cache
|
fp-info-cache
|
||||||
*.zip
|
|
||||||
netlist.ipc
|
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
|
@@ -1 +0,0 @@
|
|||||||
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
|
@@ -1 +0,0 @@
|
|||||||
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
|
@@ -1 +0,0 @@
|
|||||||
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
|
@@ -1 +0,0 @@
|
|||||||
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
|
@@ -1,4 +0,0 @@
|
|||||||
(fp_lib_table
|
|
||||||
(version 7)
|
|
||||||
(lib (name "Sensor")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/Sensors/Sensors/Sensor.pretty")(options "")(descr ""))
|
|
||||||
)
|
|
@@ -1,71 +0,0 @@
|
|||||||
P CODE 00
|
|
||||||
P UNITS CUST 0
|
|
||||||
P arrayDim N
|
|
||||||
317GND VIA MD0118PA00X+040551Y-024902X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+054232Y-022933X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+053346Y-021949X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+040846Y-019980X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+041043Y-025787X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+040059Y-019980X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+044291Y-025787X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+046654Y-025000X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+041240Y-021949X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+043307Y-020768X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+039961Y-022539X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+049606Y-021260X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+043898Y-024803X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+044587Y-023917X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+041142Y-024016X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+052461Y-022835X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+053642Y-024016X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+047835Y-026378X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+042618Y-020669X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+049409Y-022047X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+042520Y-022441X0236Y0000R000S3
|
|
||||||
317GND VIA MD0118PA00X+048622Y-022835X0236Y0000R000S3
|
|
||||||
327GND R_slop-1 A01X+053967Y-020177X0315Y0374R180S2
|
|
||||||
327NET-(U1-RS) R_slop-2 A01X+053317Y-020177X0315Y0374R180S2
|
|
||||||
3173_3V U6 -1 D0394PA00X+039016Y-019370X0669Y0669R000S0
|
|
||||||
317(U6-VBAT-PAD2) U6 -2 D0394PA00X+039016Y-020370X0669Y0000R000S0
|
|
||||||
317-(U6-SDA-PAD3) U6 -3 D0394PA00X+039016Y-021370X0669Y0000R000S0
|
|
||||||
317-(U6-SCL-PAD4) U6 -4 D0394PA00X+039016Y-022370X0669Y0000R000S0
|
|
||||||
317ENABLE_CAN U6 -5 D0394PA00X+039016Y-023370X0669Y0000R000S0
|
|
||||||
317CAN+ U6 -6 D0394PA00X+039016Y-024370X0669Y0000R000S0
|
|
||||||
317CAN- U6 -7 D0394PA00X+039016Y-025370X0669Y0000R000S0
|
|
||||||
317GND U6 -8 D0394PA00X+039016Y-026370X0669Y0000R000S0
|
|
||||||
317GND U6 -9 D0394PA00X+071260Y-034252X0669Y0669R000S0
|
|
||||||
317GND U6 -10 D0394PA00X+055512Y-031299X0669Y0669R000S0
|
|
||||||
317GND U6 -11 D0394PA00X+038780Y-034252X0669Y0669R000S0
|
|
||||||
317GND U6 -12 D0394PA00X+055512Y-020669X0669Y0669R000S0
|
|
||||||
317GND U6 -13 D0394PA00X+071260Y-019094X0669Y0669R000S0
|
|
||||||
327NET-(QP_1-G) QP_1 -1 A01X+047835Y-021280X0354Y0315R000S2
|
|
||||||
3273_3V QP_1 -2 A01X+047835Y-022028X0354Y0315R000S2
|
|
||||||
327CAN_POWER QP_1 -3 A01X+048622Y-021654X0354Y0315R000S2
|
|
||||||
327CAN_POWER R5 -1 A01X+047835Y-022904X0315Y0374R090S2
|
|
||||||
327NET-(I1-A) R5 -2 A01X+047835Y-023553X0315Y0374R090S2
|
|
||||||
327NET-(QP_1-G) R6 -1 A01X+046654Y-021329X0315Y0374R090S2
|
|
||||||
3273_3V R6 -2 A01X+046654Y-021978X0315Y0374R090S2
|
|
||||||
327NET-(QP_1-G) R7 -1 A01X+045669Y-021329X0315Y0374R090S2
|
|
||||||
327NET-(Q1-D) R7 -2 A01X+045669Y-021978X0315Y0374R090S2
|
|
||||||
317CAN_POWER J1 -1 D0374PA00X+055197Y-025394X0669Y0768R270S0
|
|
||||||
317NET-(J1-PIN_2) J1 -2 D0374PA00X+055197Y-024409X0669Y0768R270S0
|
|
||||||
317NET-(J1-PIN_3) J1 -3 D0374PA00X+055197Y-023425X0669Y0768R270S0
|
|
||||||
317GND J1 -4 D0374PA00X+055197Y-022441X0669Y0768R270S0
|
|
||||||
327NET-(Q1-G) Q1 -1 A01X+043819Y-021280X0354Y0315R000S2
|
|
||||||
327GND Q1 -2 A01X+043819Y-022028X0354Y0315R000S2
|
|
||||||
327NET-(Q1-D) Q1 -3 A01X+044606Y-021654X0354Y0315R000S2
|
|
||||||
327CAN+ U1 -1 A01X+050295Y-020707X0768Y0236R000S2
|
|
||||||
327GND U1 -2 A01X+050295Y-021207X0768Y0236R000S2
|
|
||||||
327CAN_POWER U1 -3 A01X+050295Y-021707X0768Y0236R000S2
|
|
||||||
327CAN- U1 -4 A01X+050295Y-022207X0768Y0236R000S2
|
|
||||||
327(U1-VREF-PAD5) U1 -5 A01X+052244Y-022207X0768Y0236R000S2
|
|
||||||
327NET-(J1-PIN_2) U1 -6 A01X+052244Y-021707X0768Y0236R000S2
|
|
||||||
327NET-(J1-PIN_3) U1 -7 A01X+052244Y-021207X0768Y0236R000S2
|
|
||||||
327NET-(U1-RS) U1 -8 A01X+052244Y-020707X0768Y0236R000S2
|
|
||||||
327NET-(Q1-G) R8 -1 A01X+042520Y-021329X0315Y0374R090S2
|
|
||||||
327GND R8 -2 A01X+042520Y-021978X0315Y0374R090S2
|
|
||||||
327GND I1 -1 A01X+047835Y-025541X0384Y0551R270S2
|
|
||||||
327NET-(I1-A) I1 -2 A01X+047835Y-024803X0384Y0551R270S2
|
|
||||||
327NET-(Q1-G) R4 -1 A01X+040846Y-023346X0315Y0374R180S2
|
|
||||||
327ENABLE_CAN R4 -2 A01X+040197Y-023346X0315Y0374R180S2
|
|
||||||
999
|
|
@@ -1,32 +0,0 @@
|
|||||||
;;; .doomrc --- doom runtime config -*- mode: emacs-lisp; lexical-binding: t; -*-
|
|
||||||
;;; Commentary:
|
|
||||||
;;; Code:
|
|
||||||
(require 'doom) ; be silent, byte-compiler
|
|
||||||
|
|
||||||
(after! dape
|
|
||||||
(add-to-list
|
|
||||||
'dape-configs
|
|
||||||
`(gdb-dap-openocd
|
|
||||||
ensure (lambda (config)
|
|
||||||
(dape-ensure-command config)
|
|
||||||
(let* ((default-directory
|
|
||||||
(or (dape-config-get config 'command-cwd)
|
|
||||||
default-directory))
|
|
||||||
(command (dape-config-get config 'command))
|
|
||||||
(output (shell-command-to-string (format "%s --version" command)))
|
|
||||||
(version (save-match-data
|
|
||||||
(when (string-match "GNU gdb \\(?:(.*) \\)?\\([0-9.]+\\)" output)
|
|
||||||
(string-to-number (match-string 1 output))))))
|
|
||||||
(unless (>= version 14.1)
|
|
||||||
(user-error "Requires gdb version >= 14.1"))))
|
|
||||||
modes ()
|
|
||||||
command-cwd dape-command-cwd
|
|
||||||
command "gdb"
|
|
||||||
command-args ("--interpreter=dap")
|
|
||||||
:request nil
|
|
||||||
:program nil
|
|
||||||
:args []
|
|
||||||
:stopAtBeginningOfMainSubprogram nil))
|
|
||||||
)
|
|
||||||
|
|
||||||
;;; .doomrc ends here
|
|
8
board/modules/Sensors_can/ch32-sensor/.idea/.gitignore
generated
vendored
8
board/modules/Sensors_can/ch32-sensor/.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="EMPTY_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
10
bootloader/.gitignore
vendored
10
bootloader/.gitignore
vendored
@@ -1,10 +0,0 @@
|
|||||||
# ESP-IDF build artifacts
|
|
||||||
build/
|
|
||||||
.sdkconfig*
|
|
||||||
CMakeFiles/
|
|
||||||
CMakeCache.txt
|
|
||||||
cmake-build-*/
|
|
||||||
*.log
|
|
||||||
*.bin
|
|
||||||
*.elf
|
|
||||||
*.map
|
|
8
bootloader/.idea/.gitignore
generated
vendored
8
bootloader/.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
8
bootloader/.idea/bootloader.iml
generated
8
bootloader/.idea/bootloader.iml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="EMPTY_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
8
bootloader/.idea/modules.xml
generated
8
bootloader/.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/bootloader.iml" filepath="$PROJECT_DIR$/.idea/bootloader.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
7
bootloader/.idea/vcs.xml
generated
7
bootloader/.idea/vcs.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/../website/themes/blowfish" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@@ -1,11 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
# Minimal ESP-IDF project to build only the bootloader
|
|
||||||
# You must have ESP-IDF installed and IDF_PATH exported.
|
|
||||||
|
|
||||||
# Pin the target to ESP32-C6 to ensure correct bootloader build
|
|
||||||
# (must be set before including project.cmake)
|
|
||||||
set(IDF_TARGET "esp32c6")
|
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
|
||||||
project(custom_bootloader)
|
|
@@ -1,43 +0,0 @@
|
|||||||
Custom ESP-IDF Bootloader (Rollback Enabled)
|
|
||||||
|
|
||||||
This minimal project builds a custom ESP-IDF bootloader with rollback support enabled.
|
|
||||||
You can flash it later alongside a Rust firmware using `espflash`.
|
|
||||||
|
|
||||||
What this provides
|
|
||||||
- A minimal ESP-IDF project (CMake) that can build just the bootloader.
|
|
||||||
- Rollback support enabled via sdkconfig.defaults (CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y).
|
|
||||||
- A sample OTA partition table (partitions.csv) suitable for OTA and rollback (otadata + two OTA slots).
|
|
||||||
- A convenience script to build the bootloader for the desired target.
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
- ESP-IDF installed and set up (IDF_PATH exported, Python env activated).
|
|
||||||
- A selected target (esp32, esp32s3, esp32c3, etc.).
|
|
||||||
|
|
||||||
Build
|
|
||||||
1) Ensure ESP-IDF is set up:
|
|
||||||
source "$IDF_PATH/export.sh"
|
|
||||||
|
|
||||||
2) Pick a target (examples):
|
|
||||||
idf.py set-target esp32
|
|
||||||
# or use the script:
|
|
||||||
./build_bootloader.sh esp32
|
|
||||||
|
|
||||||
3) Build only the bootloader:
|
|
||||||
idf.py bootloader
|
|
||||||
# or using the script (which also supports setting target):
|
|
||||||
./build_bootloader.sh esp32
|
|
||||||
|
|
||||||
Artifacts
|
|
||||||
- build/bootloader/bootloader.bin
|
|
||||||
|
|
||||||
Using with espflash (Rust)
|
|
||||||
- For a no_std Rust firmware, you can pass this custom bootloader to espflash:
|
|
||||||
espflash flash --bootloader build/bootloader/bootloader.bin \
|
|
||||||
--partition-table partitions.csv \
|
|
||||||
<your-app-binary-or-elf>
|
|
||||||
|
|
||||||
Notes
|
|
||||||
- Rollback logic requires an OTA layout (otadata + at least two OTA app partitions). The provided partitions.csv is a starting point; adjust sizes/offsets to match your needs.
|
|
||||||
- This project doesn’t build an application; it exists solely to produce a bootloader with the right configuration.
|
|
||||||
- If you need different log verbosity or features, run `idf.py menuconfig` and then diff/port the changes back into sdkconfig.defaults.
|
|
||||||
- Targets supported depend on your ESP-IDF version. Use `idf.py set-target <chip>` or `./build_bootloader.sh <chip>`.
|
|
@@ -1,41 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Build script for custom ESP-IDF bootloader with rollback enabled.
|
|
||||||
# Requirements:
|
|
||||||
# - ESP-IDF installed
|
|
||||||
# - IDF_PATH exported
|
|
||||||
# - Python env prepared (the usual ESP-IDF setup)
|
|
||||||
# Usage:
|
|
||||||
# ./build_bootloader.sh [esp32|esp32s3|esp32c3|esp32s2|esp32c2|esp32c6|esp32h2]
|
|
||||||
# If target is omitted, the last configured target will be used.
|
|
||||||
|
|
||||||
TARGET=${1:-}
|
|
||||||
|
|
||||||
if [[ -z "${IDF_PATH:-}" ]]; then
|
|
||||||
echo "ERROR: IDF_PATH is not set. Please install ESP-IDF and export the environment (source export.sh)." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
source "$IDF_PATH/export.sh"
|
|
||||||
|
|
||||||
if [[ -n "$TARGET" ]]; then
|
|
||||||
idf.py set-target "$TARGET"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure sdkconfig.defaults is considered (ESP-IDF does this automatically).
|
|
||||||
# Build only the bootloader.
|
|
||||||
idf.py bootloader
|
|
||||||
|
|
||||||
echo
|
|
||||||
BOOTLOADER_BIN="build/bootloader/bootloader.bin"
|
|
||||||
if [[ -f "$BOOTLOADER_BIN" ]]; then
|
|
||||||
echo "Bootloader built: $BOOTLOADER_BIN"
|
|
||||||
echo "You can use this with espflash via:"
|
|
||||||
echo " espflash flash --bootloader $BOOTLOADER_BIN [--partition-table partitions.csv] <your-app-binary>"
|
|
||||||
else
|
|
||||||
echo "ERROR: Bootloader binary not found. Check build logs above." >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
cp build/bootloader/bootloader.bin ../rust/bootloader.bin
|
|
@@ -1 +0,0 @@
|
|||||||
idf_component_register(SRCS "dummy.c" INCLUDE_DIRS ".")
|
|
@@ -1,4 +0,0 @@
|
|||||||
// This file intentionally left almost empty.
|
|
||||||
// ESP-IDF expects at least one component; the bootloader build does not use this.
|
|
||||||
|
|
||||||
void __unused_dummy_symbol(void) {}
|
|
@@ -1,6 +0,0 @@
|
|||||||
nvs, data, nvs, , 16k,
|
|
||||||
otadata, data, ota, , 8k,
|
|
||||||
phy_init, data, phy, , 4k,
|
|
||||||
ota_0, app, ota_0, , 3968k,
|
|
||||||
ota_1, app, ota_1, , 3968k,
|
|
||||||
storage, data, littlefs,, 8M,
|
|
|
2385
bootloader/sdkconfig
2385
bootloader/sdkconfig
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
|||||||
# Target can be set with: idf.py set-target esp32|esp32s3|esp32c3|...
|
|
||||||
# If not set via idf.py, ESP-IDF may default to a target; it's recommended to set it explicitly.
|
|
||||||
|
|
||||||
# Explicitly pin target to ESP32-C6
|
|
||||||
CONFIG_IDF_TARGET="esp32c6"
|
|
||||||
CONFIG_IDF_TARGET_ESP32C6=y
|
|
||||||
CONFIG_IDF_TARGET_ARCH_RISCV=y
|
|
||||||
|
|
||||||
# Bootloader configuration
|
|
||||||
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
|
|
||||||
CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y
|
|
||||||
# Slightly faster boot by skipping GPIO checks unless you need that feature
|
|
||||||
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
|
|
||||||
|
|
||||||
# Partition table config is not required to build bootloader, but shown for clarity when you build full app later
|
|
||||||
# CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
|
||||||
# CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
|
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ rustflags = [
|
|||||||
target = "riscv32imac-unknown-none-elf"
|
target = "riscv32imac-unknown-none-elf"
|
||||||
|
|
||||||
[target.riscv32imac-unknown-none-elf]
|
[target.riscv32imac-unknown-none-elf]
|
||||||
#runner = "espflash flash --monitor --bootloader bootloader.bin --chip esp32c6 --baud 921600 --partition-table partitions.csv"
|
runner = "espflash flash --monitor --chip esp32c6 --baud 921600 --partition-table partitions.csv"
|
||||||
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
||||||
#runner = "espflash flash --monitor"
|
#runner = "espflash flash --monitor"
|
||||||
#runner = "cargo runner"
|
#runner = "cargo runner"
|
||||||
@@ -23,6 +23,7 @@ target = "riscv32imac-unknown-none-elf"
|
|||||||
CHRONO_TZ_TIMEZONE_FILTER = "UTC|America/New_York|America/Chicago|America/Los_Angeles|Europe/London|Europe/Berlin|Europe/Paris|Asia/Tokyo|Asia/Shanghai|Asia/Kolkata|Australia/Sydney|America/Sao_Paulo|Africa/Johannesburg|Asia/Dubai|Pacific/Auckland"
|
CHRONO_TZ_TIMEZONE_FILTER = "UTC|America/New_York|America/Chicago|America/Los_Angeles|Europe/London|Europe/Berlin|Europe/Paris|Asia/Tokyo|Asia/Shanghai|Asia/Kolkata|Australia/Sydney|America/Sao_Paulo|Africa/Johannesburg|Asia/Dubai|Pacific/Auckland"
|
||||||
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
||||||
ESP_LOG = "info"
|
ESP_LOG = "info"
|
||||||
|
PATH = { value = "../bin:/usr/bin:/usr/local/bin", force = true, relative = true }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
rust/.idea/dictionaries/project.xml
generated
4
rust/.idea/dictionaries/project.xml
generated
@@ -1,18 +1,14 @@
|
|||||||
<component name="ProjectDictionaryState">
|
<component name="ProjectDictionaryState">
|
||||||
<dictionary name="project">
|
<dictionary name="project">
|
||||||
<words>
|
<words>
|
||||||
<w>boardtest</w>
|
|
||||||
<w>buildtime</w>
|
<w>buildtime</w>
|
||||||
<w>deepsleep</w>
|
<w>deepsleep</w>
|
||||||
<w>githash</w>
|
<w>githash</w>
|
||||||
<w>lamptest</w>
|
|
||||||
<w>lightstate</w>
|
<w>lightstate</w>
|
||||||
<w>mppt</w>
|
<w>mppt</w>
|
||||||
<w>plantstate</w>
|
<w>plantstate</w>
|
||||||
<w>pumptest</w>
|
|
||||||
<w>sntp</w>
|
<w>sntp</w>
|
||||||
<w>vergen</w>
|
<w>vergen</w>
|
||||||
<w>wifiscan</w>
|
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
@@ -7,6 +7,5 @@
|
|||||||
</Languages>
|
</Languages>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
<inspection_tool class="NewCrateVersionAvailable" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
@@ -13,29 +13,32 @@ test = false
|
|||||||
bench = false
|
bench = false
|
||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
#this strips the bootloader, we need that tho
|
[package.metadata.cargo_runner]
|
||||||
#strip = true
|
# The string `$TARGET_FILE` will be replaced with the path from cargo.
|
||||||
|
command = [
|
||||||
|
"cargo",
|
||||||
|
"espflash",
|
||||||
|
"save-image",
|
||||||
|
"--chip",
|
||||||
|
"esp32c6",
|
||||||
|
"image.bin",
|
||||||
|
"--partition-table",
|
||||||
|
"partitions.csv"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
strip = true
|
||||||
debug = false
|
debug = false
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
incremental = true
|
incremental = true
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
lto = "fat"
|
|
||||||
#debug = false
|
|
||||||
overflow-checks = true
|
|
||||||
panic = "abort"
|
|
||||||
incremental = false
|
|
||||||
opt-level = "z"
|
|
||||||
|
|
||||||
[package.metadata.espflash]
|
[package.metadata.espflash]
|
||||||
partition_table = "partitions.csv"
|
partition_table = "partitions.csv"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#ESP stuff
|
#ESP stuff
|
||||||
esp-bootloader-esp-idf = { version = "0.2.0", features = ["esp32c6"] }
|
esp-bootloader-esp-idf = { version = "0.2.0", features = ["esp32c6"] }
|
||||||
@@ -53,8 +56,6 @@ embassy-net = { version = "0.7.1", default-features = false, features = [
|
|||||||
"medium-ethernet",
|
"medium-ethernet",
|
||||||
"tcp",
|
"tcp",
|
||||||
"udp",
|
"udp",
|
||||||
"proto-ipv4",
|
|
||||||
"dns"
|
|
||||||
] }
|
] }
|
||||||
embedded-io = "0.6.1"
|
embedded-io = "0.6.1"
|
||||||
embedded-io-async = "0.6.1"
|
embedded-io-async = "0.6.1"
|
||||||
@@ -92,7 +93,6 @@ smoltcp = { version = "0.12.0", default-features = false, features = [
|
|||||||
"medium-ethernet",
|
"medium-ethernet",
|
||||||
"multicast",
|
"multicast",
|
||||||
"proto-dhcpv4",
|
"proto-dhcpv4",
|
||||||
"proto-ipv6",
|
|
||||||
"proto-dns",
|
"proto-dns",
|
||||||
"proto-ipv4",
|
"proto-ipv4",
|
||||||
"socket-dns",
|
"socket-dns",
|
||||||
@@ -103,6 +103,7 @@ smoltcp = { version = "0.12.0", default-features = false, features = [
|
|||||||
] }
|
] }
|
||||||
#static_cell = "2.1.1"
|
#static_cell = "2.1.1"
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
|
heapless = { version = "0.8", features = ["serde"] }
|
||||||
embedded-hal-bus = { version = "0.3.0" }
|
embedded-hal-bus = { version = "0.3.0" }
|
||||||
|
|
||||||
#Hardware additional driver
|
#Hardware additional driver
|
||||||
@@ -117,6 +118,7 @@ ds323x = "0.6.0"
|
|||||||
serde = { version = "1.0.219", features = ["derive", "alloc"], default-features = false }
|
serde = { version = "1.0.219", features = ["derive", "alloc"], default-features = false }
|
||||||
serde_json = { version = "1.0.143", default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0.143", default-features = false, features = ["alloc"] }
|
||||||
|
|
||||||
|
#timezone
|
||||||
chrono = { version = "0.4.42", default-features = false, features = ["iana-time-zone", "alloc", "serde"] }
|
chrono = { version = "0.4.42", default-features = false, features = ["iana-time-zone", "alloc", "serde"] }
|
||||||
chrono-tz = { version = "0.10.4", default-features = false, features = ["filter-by-regex"] }
|
chrono-tz = { version = "0.10.4", default-features = false, features = ["filter-by-regex"] }
|
||||||
eeprom24x = "0.7.2"
|
eeprom24x = "0.7.2"
|
||||||
@@ -126,6 +128,8 @@ unit-enum = "1.4.1"
|
|||||||
pca9535 = { version = "2.0.0" }
|
pca9535 = { version = "2.0.0" }
|
||||||
ina219 = { version = "0.2.0" }
|
ina219 = { version = "0.2.0" }
|
||||||
embedded-storage = "=0.3.1"
|
embedded-storage = "=0.3.1"
|
||||||
|
ekv = "1.0.0"
|
||||||
|
embedded-can = "0.4.1"
|
||||||
portable-atomic = "1.11.1"
|
portable-atomic = "1.11.1"
|
||||||
embassy-sync = { version = "0.7.2", features = ["log"] }
|
embassy-sync = { version = "0.7.2", features = ["log"] }
|
||||||
async-trait = "0.1.89"
|
async-trait = "0.1.89"
|
||||||
@@ -141,19 +145,8 @@ bytemuck = { version = "1.23.2", features = ["derive", "min_const_generics", "po
|
|||||||
deranged = "0.5.3"
|
deranged = "0.5.3"
|
||||||
embassy-embedded-hal = "0.5.0"
|
embassy-embedded-hal = "0.5.0"
|
||||||
bincode = { version = "2.0.1", default-features = false, features = ["derive"] }
|
bincode = { version = "2.0.1", default-features = false, features = ["derive"] }
|
||||||
sntpc = { version = "0.6.0", default-features = false, features = ["log", "embassy-socket", "embassy-socket-ipv6"] }
|
|
||||||
option-lock = { version = "0.3.1", default-features = false }
|
|
||||||
|
|
||||||
#stay in sync with mcutie version here!
|
|
||||||
heapless = { version = "0.7.17", features = ["serde"] }
|
|
||||||
mcutie = { version = "0.3.0", default-features = false, features = ["log", "homeassistant"] }
|
|
||||||
nb = "1.1.0"
|
|
||||||
embedded-can = "0.4.1"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
mcutie = { git = 'https://github.com/empirephoenix/mcutie.git' }
|
|
||||||
#bq34z100 = { path = "../../bq34z100_rust" }
|
#bq34z100 = { path = "../../bq34z100_rust" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
12
rust/all.sh
12
rust/all.sh
@@ -1,12 +0,0 @@
|
|||||||
rm ./src/webserver/index.html.gz
|
|
||||||
rm ./src/webserver/bundle.js.gz
|
|
||||||
set -e
|
|
||||||
cd ./src_webpack/
|
|
||||||
npx webpack build
|
|
||||||
cp index.html.gz ../src/webserver/index.html.gz
|
|
||||||
cp bundle.js.gz ../src/webserver/bundle.js.gz
|
|
||||||
cd ../
|
|
||||||
|
|
||||||
cargo build --release
|
|
||||||
espflash save-image --bootloader bootloader.bin --partition-table partitions.csv --chip esp32c6 target/riscv32imac-unknown-none-elf/release/plant-ctrl2 image.bin
|
|
||||||
espflash flash --monitor --bootloader bootloader.bin --chip esp32c6 --baud 921600 --partition-table partitions.csv target/riscv32imac-unknown-none-elf/release/plant-ctrl2
|
|
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
use std::process::Command;
|
use std::{collections::VecDeque, env, process::Command};
|
||||||
|
|
||||||
use vergen::EmitBuilder;
|
use vergen::EmitBuilder;
|
||||||
|
|
||||||
@@ -50,7 +50,10 @@ fn linker_be_nice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//webpack();
|
if Command::new("podman").arg("--version").output().is_err() {
|
||||||
|
println!("Could not find `podman` installation, assuming the developer has setup all required tool for build manually! … ")
|
||||||
|
}
|
||||||
|
webpack();
|
||||||
linker_be_nice();
|
linker_be_nice();
|
||||||
let _ = EmitBuilder::builder().all_git().all_build().emit();
|
let _ = EmitBuilder::builder().all_git().all_build().emit();
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
rm ./src/webserver/index.html.gz
|
|
||||||
rm ./src/webserver/bundle.js.gz
|
|
||||||
set -e
|
|
||||||
cd ./src_webpack/
|
|
||||||
npx webpack build
|
|
||||||
cp index.html.gz ../src/webserver/index.html.gz
|
|
||||||
cp bundle.js.gz ../src/webserver/bundle.js.gz
|
|
||||||
cd ../
|
|
||||||
|
|
||||||
cargo build --release
|
|
||||||
espflash flash --monitor --bootloader bootloader.bin --chip esp32c6 --baud 921600 --partition-table partitions.csv target/riscv32imac-unknown-none-elf/release/plant-ctrl2
|
|
@@ -1,13 +0,0 @@
|
|||||||
rm image.bin
|
|
||||||
rm ./src/webserver/index.html.gz
|
|
||||||
rm ./src/webserver/bundle.js.gz
|
|
||||||
set -e
|
|
||||||
cd ./src_webpack/
|
|
||||||
npx webpack build
|
|
||||||
cp index.html.gz ../src/webserver/index.html.gz
|
|
||||||
cp bundle.js.gz ../src/webserver/bundle.js.gz
|
|
||||||
cd ../
|
|
||||||
|
|
||||||
set -e
|
|
||||||
cargo build --release
|
|
||||||
espflash save-image --bootloader bootloader.bin --partition-table partitions.csv --chip esp32c6 target/riscv32imac-unknown-none-elf/release/plant-ctrl2 image.bin
|
|
434
rust/scratch/v3_hal.rs
Normal file
434
rust/scratch/v3_hal.rs
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
use crate::hal::rtc::RTCModuleInteraction;
|
||||||
|
use crate::hal::water::TankSensor;
|
||||||
|
use crate::hal::{
|
||||||
|
deep_sleep, BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT,
|
||||||
|
};
|
||||||
|
use crate::log::{log, LogMessage};
|
||||||
|
use crate::{
|
||||||
|
config::PlantControllerConfig,
|
||||||
|
hal::{battery::BatteryInteraction, esp::Esp},
|
||||||
|
};
|
||||||
|
use anyhow::{bail, Ok, Result};
|
||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use measurements::{Current, Voltage};
|
||||||
|
use plant_ctrl2::sipo::ShiftRegister40;
|
||||||
|
use core::result::Result::Ok as OkStd;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use esp_hall::gpio::Pull;
|
||||||
|
|
||||||
|
const PUMP8_BIT: usize = 0;
|
||||||
|
const PUMP1_BIT: usize = 1;
|
||||||
|
const PUMP2_BIT: usize = 2;
|
||||||
|
const PUMP3_BIT: usize = 3;
|
||||||
|
const PUMP4_BIT: usize = 4;
|
||||||
|
const PUMP5_BIT: usize = 5;
|
||||||
|
const PUMP6_BIT: usize = 6;
|
||||||
|
const PUMP7_BIT: usize = 7;
|
||||||
|
const MS_0: usize = 8;
|
||||||
|
const MS_4: usize = 9;
|
||||||
|
const MS_2: usize = 10;
|
||||||
|
const MS_3: usize = 11;
|
||||||
|
const MS_1: usize = 13;
|
||||||
|
const SENSOR_ON: usize = 12;
|
||||||
|
|
||||||
|
const SENSOR_A_1: u8 = 7;
|
||||||
|
const SENSOR_A_2: u8 = 6;
|
||||||
|
const SENSOR_A_3: u8 = 5;
|
||||||
|
const SENSOR_A_4: u8 = 4;
|
||||||
|
const SENSOR_A_5: u8 = 3;
|
||||||
|
const SENSOR_A_6: u8 = 2;
|
||||||
|
const SENSOR_A_7: u8 = 1;
|
||||||
|
const SENSOR_A_8: u8 = 0;
|
||||||
|
|
||||||
|
const SENSOR_B_1: u8 = 8;
|
||||||
|
const SENSOR_B_2: u8 = 9;
|
||||||
|
const SENSOR_B_3: u8 = 10;
|
||||||
|
const SENSOR_B_4: u8 = 11;
|
||||||
|
const SENSOR_B_5: u8 = 12;
|
||||||
|
const SENSOR_B_6: u8 = 13;
|
||||||
|
const SENSOR_B_7: u8 = 14;
|
||||||
|
const SENSOR_B_8: u8 = 15;
|
||||||
|
|
||||||
|
const CHARGING: usize = 14;
|
||||||
|
const AWAKE: usize = 15;
|
||||||
|
|
||||||
|
const FAULT_3: usize = 16;
|
||||||
|
const FAULT_8: usize = 17;
|
||||||
|
const FAULT_7: usize = 18;
|
||||||
|
const FAULT_6: usize = 19;
|
||||||
|
const FAULT_5: usize = 20;
|
||||||
|
const FAULT_4: usize = 21;
|
||||||
|
const FAULT_1: usize = 22;
|
||||||
|
const FAULT_2: usize = 23;
|
||||||
|
|
||||||
|
const REPEAT_MOIST_MEASURE: usize = 1;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct V3<'a> {
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
esp: Esp<'a>,
|
||||||
|
shift_register: ShiftRegister40<
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
>,
|
||||||
|
_shift_register_enable_invert:
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Output>,
|
||||||
|
tank_sensor: TankSensor<'a>,
|
||||||
|
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
|
||||||
|
light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
main_pump: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
signal_counter: PcntDriver<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_v3(
|
||||||
|
peripherals: FreePeripherals,
|
||||||
|
esp: Esp<'static>,
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
||||||
|
log::info!("Start v3");
|
||||||
|
let mut clock = PinDriver::input_output(peripherals.gpio15.downgrade())?;
|
||||||
|
clock.set_pull(Pull::Floating)?;
|
||||||
|
let mut latch = PinDriver::input_output(peripherals.gpio3.downgrade())?;
|
||||||
|
latch.set_pull(Pull::Floating)?;
|
||||||
|
let mut data = PinDriver::input_output(peripherals.gpio23.downgrade())?;
|
||||||
|
data.set_pull(Pull::Floating)?;
|
||||||
|
let shift_register = ShiftRegister40::new(clock, latch, data);
|
||||||
|
//disable all
|
||||||
|
for mut pin in shift_register.decompose() {
|
||||||
|
pin.set_low()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let awake = &mut shift_register.decompose()[AWAKE];
|
||||||
|
awake.set_high()?;
|
||||||
|
|
||||||
|
let charging = &mut shift_register.decompose()[CHARGING];
|
||||||
|
charging.set_high()?;
|
||||||
|
|
||||||
|
let ms0 = &mut shift_register.decompose()[MS_0];
|
||||||
|
ms0.set_low()?;
|
||||||
|
let ms1 = &mut shift_register.decompose()[MS_1];
|
||||||
|
ms1.set_low()?;
|
||||||
|
let ms2 = &mut shift_register.decompose()[MS_2];
|
||||||
|
ms2.set_low()?;
|
||||||
|
let ms3 = &mut shift_register.decompose()[MS_3];
|
||||||
|
ms3.set_low()?;
|
||||||
|
|
||||||
|
let ms4 = &mut shift_register.decompose()[MS_4];
|
||||||
|
ms4.set_high()?;
|
||||||
|
|
||||||
|
let one_wire_pin = peripherals.gpio18.downgrade();
|
||||||
|
let tank_power_pin = peripherals.gpio11.downgrade();
|
||||||
|
|
||||||
|
let flow_sensor_pin = peripherals.gpio4.downgrade();
|
||||||
|
|
||||||
|
let tank_sensor = TankSensor::create(
|
||||||
|
one_wire_pin,
|
||||||
|
peripherals.adc1,
|
||||||
|
peripherals.gpio5,
|
||||||
|
tank_power_pin,
|
||||||
|
flow_sensor_pin,
|
||||||
|
peripherals.pcnt1,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut signal_counter = PcntDriver::new(
|
||||||
|
peripherals.pcnt0,
|
||||||
|
Some(peripherals.gpio22),
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
signal_counter.channel_config(
|
||||||
|
PcntChannel::Channel0,
|
||||||
|
PinIndex::Pin0,
|
||||||
|
PinIndex::Pin1,
|
||||||
|
&PcntChannelConfig {
|
||||||
|
lctrl_mode: PcntControlMode::Keep,
|
||||||
|
hctrl_mode: PcntControlMode::Keep,
|
||||||
|
pos_mode: PcntCountMode::Increment,
|
||||||
|
neg_mode: PcntCountMode::Hold,
|
||||||
|
counter_h_lim: i16::MAX,
|
||||||
|
counter_l_lim: 0,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
|
||||||
|
solar_is_day.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut light = PinDriver::input_output(peripherals.gpio10.downgrade())?;
|
||||||
|
light.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut main_pump = PinDriver::input_output(peripherals.gpio2.downgrade())?;
|
||||||
|
main_pump.set_pull(Pull::Floating)?;
|
||||||
|
main_pump.set_low()?;
|
||||||
|
|
||||||
|
let mut general_fault = PinDriver::input_output(peripherals.gpio6.downgrade())?;
|
||||||
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
|
general_fault.set_low()?;
|
||||||
|
|
||||||
|
let mut shift_register_enable_invert = PinDriver::output(peripherals.gpio21.downgrade())?;
|
||||||
|
|
||||||
|
unsafe { gpio_hold_dis(shift_register_enable_invert.pin()) };
|
||||||
|
shift_register_enable_invert.set_low()?;
|
||||||
|
unsafe { gpio_hold_en(shift_register_enable_invert.pin()) };
|
||||||
|
|
||||||
|
Ok(Box::new(V3 {
|
||||||
|
config,
|
||||||
|
battery_monitor,
|
||||||
|
rtc_module,
|
||||||
|
esp,
|
||||||
|
shift_register,
|
||||||
|
_shift_register_enable_invert: shift_register_enable_invert,
|
||||||
|
tank_sensor,
|
||||||
|
solar_is_day,
|
||||||
|
light,
|
||||||
|
main_pump,
|
||||||
|
general_fault,
|
||||||
|
signal_counter,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BoardInteraction<'a> for V3<'a> {
|
||||||
|
fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> {
|
||||||
|
Some(&mut self.tank_sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_esp(&mut self) -> &mut Esp<'a> {
|
||||||
|
&mut self.esp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config(&mut self) -> &PlantControllerConfig {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send + 'static> {
|
||||||
|
&mut self.battery_monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send> {
|
||||||
|
&mut self.rtc_module
|
||||||
|
}
|
||||||
|
fn set_charge_indicator(&mut self, charging: bool) -> Result<()> {
|
||||||
|
Ok(self.shift_register.decompose()[CHARGING].set_state(charging.into())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||||
|
let _ = self.shift_register.decompose()[AWAKE].set_low();
|
||||||
|
deep_sleep(duration_in_ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_day(&self) -> bool {
|
||||||
|
self.solar_is_day.get_level().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn light(&mut self, enable: bool) -> Result<()> {
|
||||||
|
unsafe { gpio_hold_dis(self.light.pin()) };
|
||||||
|
self.light.set_state(enable.into())?;
|
||||||
|
unsafe { gpio_hold_en(self.light.pin()) };
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn pump(&mut self, plant: usize, enable: bool) -> Result<()> {
|
||||||
|
if enable {
|
||||||
|
self.main_pump.set_high()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = match plant {
|
||||||
|
0 => PUMP1_BIT,
|
||||||
|
1 => PUMP2_BIT,
|
||||||
|
2 => PUMP3_BIT,
|
||||||
|
3 => PUMP4_BIT,
|
||||||
|
4 => PUMP5_BIT,
|
||||||
|
5 => PUMP6_BIT,
|
||||||
|
6 => PUMP7_BIT,
|
||||||
|
7 => PUMP8_BIT,
|
||||||
|
_ => bail!("Invalid pump {plant}",),
|
||||||
|
};
|
||||||
|
self.shift_register.decompose()[index].set_state(enable.into())?;
|
||||||
|
|
||||||
|
if !enable {
|
||||||
|
self.main_pump.set_low()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump_current(&mut self, _plant: usize) -> Result<Current> {
|
||||||
|
bail!("Not implemented in v3")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fault(&mut self, plant: usize, enable: bool) -> Result<()> {
|
||||||
|
let index = match plant {
|
||||||
|
0 => FAULT_1,
|
||||||
|
1 => FAULT_2,
|
||||||
|
2 => FAULT_3,
|
||||||
|
3 => FAULT_4,
|
||||||
|
4 => FAULT_5,
|
||||||
|
5 => FAULT_6,
|
||||||
|
6 => FAULT_7,
|
||||||
|
7 => FAULT_8,
|
||||||
|
_ => panic!("Invalid plant id {}", plant),
|
||||||
|
};
|
||||||
|
self.shift_register.decompose()[index].set_state(enable.into())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<f32> {
|
||||||
|
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||||
|
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||||
|
self.signal_counter.counter_pause()?;
|
||||||
|
self.signal_counter.counter_clear()?;
|
||||||
|
//Disable all
|
||||||
|
self.shift_register.decompose()[MS_4].set_high()?;
|
||||||
|
|
||||||
|
let sensor_channel = match sensor {
|
||||||
|
Sensor::A => match plant {
|
||||||
|
0 => SENSOR_A_1,
|
||||||
|
1 => SENSOR_A_2,
|
||||||
|
2 => SENSOR_A_3,
|
||||||
|
3 => SENSOR_A_4,
|
||||||
|
4 => SENSOR_A_5,
|
||||||
|
5 => SENSOR_A_6,
|
||||||
|
6 => SENSOR_A_7,
|
||||||
|
7 => SENSOR_A_8,
|
||||||
|
_ => bail!("Invalid plant id {}", plant),
|
||||||
|
},
|
||||||
|
Sensor::B => match plant {
|
||||||
|
0 => SENSOR_B_1,
|
||||||
|
1 => SENSOR_B_2,
|
||||||
|
2 => SENSOR_B_3,
|
||||||
|
3 => SENSOR_B_4,
|
||||||
|
4 => SENSOR_B_5,
|
||||||
|
5 => SENSOR_B_6,
|
||||||
|
6 => SENSOR_B_7,
|
||||||
|
7 => SENSOR_B_8,
|
||||||
|
_ => bail!("Invalid plant id {}", plant),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
||||||
|
let pin_0 = &mut self.shift_register.decompose()[MS_0];
|
||||||
|
let pin_1 = &mut self.shift_register.decompose()[MS_1];
|
||||||
|
let pin_2 = &mut self.shift_register.decompose()[MS_2];
|
||||||
|
let pin_3 = &mut self.shift_register.decompose()[MS_3];
|
||||||
|
if is_bit_set(0) {
|
||||||
|
pin_0.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_0.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(1) {
|
||||||
|
pin_1.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_1.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(2) {
|
||||||
|
pin_2.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_2.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(3) {
|
||||||
|
pin_3.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_3.set_low()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shift_register.decompose()[MS_4].set_low()?;
|
||||||
|
self.shift_register.decompose()[SENSOR_ON].set_high()?;
|
||||||
|
|
||||||
|
let measurement = 100; //how long to measure and then extrapolate to hz
|
||||||
|
let factor = 1000f32 / measurement as f32; //scale raw cound by this number to get hz
|
||||||
|
|
||||||
|
//give some time to stabilize
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
self.signal_counter.counter_resume()?;
|
||||||
|
self.esp.delay.delay_ms(measurement);
|
||||||
|
self.signal_counter.counter_pause()?;
|
||||||
|
self.shift_register.decompose()[MS_4].set_high()?;
|
||||||
|
self.shift_register.decompose()[SENSOR_ON].set_low()?;
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
let unscaled = self.signal_counter.get_counter_value()? as i32;
|
||||||
|
let hz = unscaled as f32 * factor;
|
||||||
|
log(
|
||||||
|
LogMessage::RawMeasure,
|
||||||
|
unscaled as u32,
|
||||||
|
hz as u32,
|
||||||
|
&plant.to_string(),
|
||||||
|
&format!("{sensor:?}"),
|
||||||
|
);
|
||||||
|
results[repeat] = hz;
|
||||||
|
}
|
||||||
|
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
||||||
|
|
||||||
|
let mid = results.len() / 2;
|
||||||
|
let median = results[mid];
|
||||||
|
Ok(median)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn general_fault(&mut self, enable: bool) {
|
||||||
|
unsafe { gpio_hold_dis(self.general_fault.pin()) };
|
||||||
|
self.general_fault.set_state(enable.into()).unwrap();
|
||||||
|
unsafe { gpio_hold_en(self.general_fault.pin()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(&mut self) -> Result<()> {
|
||||||
|
self.general_fault(true);
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.general_fault(false);
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.light(true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.light(false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.fault(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.fault(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
}
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.pump(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.pump(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
}
|
||||||
|
for plant in 0..PLANT_COUNT {
|
||||||
|
let a = self.measure_moisture_hz(plant, Sensor::A);
|
||||||
|
let b = self.measure_moisture_hz(plant, Sensor::B);
|
||||||
|
let aa = match a {
|
||||||
|
OkStd(a) => a as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
let bb = match b {
|
||||||
|
OkStd(b) => b as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "");
|
||||||
|
}
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_config(&mut self, config: PlantControllerConfig) -> Result<()> {
|
||||||
|
self.config = config;
|
||||||
|
self.esp.save_config(&self.config)?;
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_voltage(&mut self) -> Result<Voltage> {
|
||||||
|
//assuming module to work, these are the hardware set values
|
||||||
|
if self.is_day() {
|
||||||
|
Ok(Voltage::from_volts(15_f64))
|
||||||
|
} else {
|
||||||
|
Ok(Voltage::from_volts(0_f64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_current(&mut self) -> Result<Current> {
|
||||||
|
bail!("Board does not have current sensor")
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
use crate::hal::PLANT_COUNT;
|
|
||||||
use crate::plant_state::PlantWateringMode;
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
use crate::hal::PLANT_COUNT;
|
||||||
|
use crate::plant_state::PlantWateringMode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
@@ -10,10 +10,10 @@ pub struct NetworkConfig {
|
|||||||
pub ap_ssid: heapless::String<32>,
|
pub ap_ssid: heapless::String<32>,
|
||||||
pub ssid: Option<heapless::String<32>>,
|
pub ssid: Option<heapless::String<32>>,
|
||||||
pub password: Option<heapless::String<64>>,
|
pub password: Option<heapless::String<64>>,
|
||||||
pub mqtt_url: Option<String>,
|
pub mqtt_url: Option<heapless::String<128>>,
|
||||||
pub base_topic: Option<heapless::String<64>>,
|
pub base_topic: Option<heapless::String<64>>,
|
||||||
pub mqtt_user: Option<String>,
|
pub mqtt_user: Option<heapless::String<32>>,
|
||||||
pub mqtt_password: Option<String>,
|
pub mqtt_password: Option<heapless::String<64>>,
|
||||||
pub max_wait: u32,
|
pub max_wait: u32,
|
||||||
}
|
}
|
||||||
impl Default for NetworkConfig {
|
impl Default for NetworkConfig {
|
||||||
|
@@ -6,10 +6,7 @@ use core::str::Utf8Error;
|
|||||||
use embassy_embedded_hal::shared_bus::I2cDeviceError;
|
use embassy_embedded_hal::shared_bus::I2cDeviceError;
|
||||||
use embassy_executor::SpawnError;
|
use embassy_executor::SpawnError;
|
||||||
use embassy_sync::mutex::TryLockError;
|
use embassy_sync::mutex::TryLockError;
|
||||||
use embedded_storage::nor_flash::NorFlashErrorKind;
|
|
||||||
use esp_hal::i2c::master::ConfigError;
|
use esp_hal::i2c::master::ConfigError;
|
||||||
use esp_hal::pcnt::unit::{InvalidHighLimit, InvalidLowLimit};
|
|
||||||
use esp_hal::twai::EspTwaiError;
|
|
||||||
use esp_wifi::wifi::WifiError;
|
use esp_wifi::wifi::WifiError;
|
||||||
use ina219::errors::{BusVoltageReadError, ShuntVoltageReadError};
|
use ina219::errors::{BusVoltageReadError, ShuntVoltageReadError};
|
||||||
use littlefs2_core::PathError;
|
use littlefs2_core::PathError;
|
||||||
@@ -62,12 +59,6 @@ pub enum FatError {
|
|||||||
ExpanderError {
|
ExpanderError {
|
||||||
error: String,
|
error: String,
|
||||||
},
|
},
|
||||||
CanBusError {
|
|
||||||
error: EspTwaiError,
|
|
||||||
},
|
|
||||||
SNTPError {
|
|
||||||
error: sntpc::Error,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FatResult<T> = Result<T, FatError>;
|
pub type FatResult<T> = Result<T, FatError>;
|
||||||
@@ -96,10 +87,6 @@ impl fmt::Display for FatError {
|
|||||||
FatError::DS323 { error } => write!(f, "DS323 {:?}", error),
|
FatError::DS323 { error } => write!(f, "DS323 {:?}", error),
|
||||||
FatError::Eeprom24x { error } => write!(f, "Eeprom24x {:?}", error),
|
FatError::Eeprom24x { error } => write!(f, "Eeprom24x {:?}", error),
|
||||||
FatError::ExpanderError { error } => write!(f, "ExpanderError {:?}", error),
|
FatError::ExpanderError { error } => write!(f, "ExpanderError {:?}", error),
|
||||||
FatError::CanBusError { error } => {
|
|
||||||
write!(f, "CanBusError {:?}", error)
|
|
||||||
}
|
|
||||||
FatError::SNTPError { error } => write!(f, "SNTPError {:?}", error),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,49 +257,3 @@ impl<E: core::fmt::Debug> From<ShuntVoltageReadError<I2cDeviceError<E>>> for Fat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Infallible> for FatError {
|
|
||||||
fn from(value: Infallible) -> Self {
|
|
||||||
panic!("Infallible error: {:?}", value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<InvalidLowLimit> for FatError {
|
|
||||||
fn from(value: InvalidLowLimit) -> Self {
|
|
||||||
FatError::String {
|
|
||||||
error: format!("{:?}", value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<InvalidHighLimit> for FatError {
|
|
||||||
fn from(value: InvalidHighLimit) -> Self {
|
|
||||||
FatError::String {
|
|
||||||
error: format!("{:?}", value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<nb::Error<EspTwaiError>> for FatError {
|
|
||||||
fn from(value: nb::Error<EspTwaiError>) -> Self {
|
|
||||||
match value {
|
|
||||||
nb::Error::Other(can_error) => FatError::CanBusError { error: can_error },
|
|
||||||
nb::Error::WouldBlock => FatError::String {
|
|
||||||
error: "Would block".to_string(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NorFlashErrorKind> for FatError {
|
|
||||||
fn from(value: NorFlashErrorKind) -> Self {
|
|
||||||
FatError::String {
|
|
||||||
error: value.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<sntpc::Error> for FatError {
|
|
||||||
fn from(value: sntpc::Error) -> Self {
|
|
||||||
FatError::SNTPError { error: value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use crate::fat_error::{FatError, FatResult};
|
|
||||||
use crate::hal::Box;
|
use crate::hal::Box;
|
||||||
|
use crate::fat_error::{FatError, FatResult};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bq34z100::{Bq34z100g1, Bq34z100g1Driver, Flags};
|
use bq34z100::{Bq34z100g1, Bq34z100g1Driver, Flags};
|
||||||
@@ -43,6 +43,14 @@ pub enum BatteryError {
|
|||||||
CommunicationError(String),
|
CommunicationError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl From<Bq34Z100Error<esp_idf_hal::i2c::I2cError>> for BatteryError {
|
||||||
|
// fn from(err: Bq34Z100Error<esp_idf_hal::i2c::I2cError>) -> Self {
|
||||||
|
// BatteryError::CommunicationError(
|
||||||
|
// anyhow!("failed to communicate with battery monitor: {:?}", err).to_string(),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum BatteryState {
|
pub enum BatteryState {
|
||||||
Unknown,
|
Unknown,
|
||||||
@@ -54,8 +62,7 @@ pub struct NoBatteryMonitor {}
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl BatteryInteraction for NoBatteryMonitor {
|
impl BatteryInteraction for NoBatteryMonitor {
|
||||||
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
||||||
// No monitor configured: assume full battery for lightstate logic
|
Err(FatError::NoBatteryMonitor)
|
||||||
Ok(100.0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user