Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
92d5f67
update tooling and lint c-code
orgua Sep 10, 2025
1f09b52
add doc for virtual battery
orgua Sep 15, 2025
5a478ba
add doc for DC-Bias effect
orgua Sep 15, 2025
d8379a3
add doc for battery storage
orgua Sep 22, 2025
677596a
migrate battery-model to revised virtual storage
orgua Sep 22, 2025
bca2025
migrate python pru-module
orgua Sep 24, 2025
e825d48
add get/set in kMod for storage
orgua Sep 24, 2025
d7bd1ee
add get/set for storage in python
orgua Sep 24, 2025
e1930e3
various small fixes
orgua Sep 24, 2025
336b01d
Update build_py.sh
orgua Sep 24, 2025
33a4e20
bump ver
orgua Sep 24, 2025
d6e3f05
Improve debugging for PRUs
orgua Oct 14, 2025
849ea02
Fix bug in kernel-code and improve code
orgua Oct 14, 2025
4c7ffc0
Update .pre-commit-config.yaml
orgua Oct 14, 2025
0697b8f
Update build_py.sh
orgua Oct 14, 2025
869e442
Update msg_sys.c
orgua Oct 14, 2025
1e7435d
minor improvements to sheep-package
orgua Oct 16, 2025
af0f029
sheep: use ExitStack() more correctly
orgua Oct 16, 2025
dc33c40
fix pru-python-module
orgua Oct 16, 2025
c0dabdf
cleanup
orgua Oct 16, 2025
683ef92
add special math-fn for PRU
orgua Oct 17, 2025
ff25a72
harvester c-code - improve over/underflow protection of vars
orgua Oct 17, 2025
472ca84
minor overflow improvement for storage
orgua Oct 17, 2025
b6d689a
minor improvements to overflow protection in converter
orgua Oct 17, 2025
47102ad
pru-code - solve compiler warnings
orgua Oct 17, 2025
a8db31c
pru - fix init of timer-var
orgua Oct 17, 2025
5278012
inline math fn
orgua Oct 17, 2025
0176432
minor tuning to vsource-code
orgua Oct 17, 2025
4278be0
pru1 - allow debugging realtime-violations
orgua Oct 17, 2025
ebd3b62
Update build_py.sh
orgua Oct 17, 2025
cf81480
update tooling & lint
orgua Nov 11, 2025
e2a2d45
bump ver
orgua Nov 11, 2025
2568be6
move to newer core/data-lib
orgua Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
[bumpversion]
current_version = 2025.8.1
current_version = 2025.11.1
commit = False
tag = False

[bumpversion:file:pyproject.toml]

[bumpversion:file:docs/conf.py]

[bumpversion:file:software/firmware/pru0-module-py/shepherd_pru/__init__.py]
Expand Down
8 changes: 7 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AllowShortNamespacesOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
Expand All @@ -29,16 +32,19 @@ BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterExternBlock: true
AfterFunction: true
AfterNamespace: true
AfterUnion: true
AfterStruct: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
BeforeWhile: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ repos:
- id: text-unicode-replacement-char

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.12.9'
rev: v0.14.4
hooks:
- id: ruff-format
- id: ruff-check
Expand Down Expand Up @@ -89,7 +89,7 @@ repos:
exclude: \.(sch|brd|lbr)$

- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.8
rev: v21.1.5
hooks:
- id: clang-format
types_or: [c++, c]
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# History of Changes

## 2025.8.1
## 2025.11.1

- project changes to stable and adjusts version-format to `YYYY.MM.r` (year, month, release-number)
- py-packaging:
Expand Down Expand Up @@ -39,6 +39,9 @@
- kMod
- disable experimental code - not compatible with non-ti kernel
- verify canaries less often (~ 2 min)
- add virtual storage (battery)
- tbd


## 0.9.3

Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
project = "SHEPHERD"
project_copyright = "2019-2025, Networked Embedded Systems Lab, TU Darmstadt & TU Dresden"
author = "Ingmar Splitt, Kai Geissdoerfer"
release = "2025.8.1"
release = "2025.11.1"

# -- General configuration ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/dev/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ uv venv
uv pip install .[dev]
# and then
pre-commit run --all-files
bump2version --allow-dirty --new-version 2025.8.1 patch
bump2version --allow-dirty --new-version 2025.11.1 patch
# version-format: YYYY.MM.r
```

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Welcome to SHEPHERD's documentation
./user/data_format.md
./user/performance.rst
./user/virtual_source.md
./user/virtual_storage.md
./user/virtual_harvester.md
./user/virtual_source_old.rst

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/media_storage/comparison_dc_bias.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/media_storage/electrical_equ.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/media_storage/electrical_mdl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/user/virtual_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ As an actual YAML-Example describing a simple diode & capacitor circuit:
description: Simple Converter based on diode and buffer capacitor
inherit_from: neutral
V_input_drop_mV: 300 # simulate input-diode
C_intermediate_uF: 10 # primary storage-Cap
storage: # primary storage-Cap
name: Capacitor_10uF_10.0V
```

## Sim-Example 1
Expand Down
132 changes: 132 additions & 0 deletions docs/user/virtual_storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Battery Model for Shepherd

## Basis

The model is based on the electrical model introduced in [_An Accurate Electrical Battery Model Capable of Predicting Runtime and I–V Performance_](https://rincon-mora.gatech.edu/publicat/jrnls/tec05_batt_mdl.pdf).

The circuit diagram of the electrical model is shown here:
![electrical circuit model](./media_storage/electrical_mdl.png)

The model uses:

- a capacitor (`C_capacity`) to model the `State of Charge` (SoC)
- a controlled voltage source to model the relation of SoC to open-circuit voltage
- a series resistor to model the current dependent voltage drop
- two RC elements to model transient voltage effects
- a resistor to model self-discharge (however, they later omit this, deeming it negligible)

The component values depend on the SoC through a set of equations:
![electrical circuit model equations](./media_storage/electrical_equ.png)

These parameters model a specific battery and are provided by the authors.

## Kinetic Battery Model

The electrical model described above was used as a basis for the more complex hybrid model introduced in [_A Hybrid Battery Model Capable of Capturing Dynamic Circuit Characteristics and Nonlinear Capacity Effects_](https://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1210&context=electricalengineeringfacpub).

This model introduces the so called `rate capacity` effect which causes temporary changes in available capacity due to chemical effects that occur when a current is applied.
Since the corresponding formulas are rather complex, implementing them on the PRU is unfeasible.

However, the authors also parameterize their model and provide parameter values for both a Lithium-Polymer [(PL-383562)](https://www.batteryspace.com/prod-specs/pl383562.pdf) and a Lead-Acid [(LEOCH LP12-1.2AH)](https://www.leoch.com/pdf/reserve-power/agm-vrla/lp-general/LP12-1.2.pdf) battery.
A subset of these parameters can be used to configure the electrical model and extend the PRU implementation.
Shepherd keeps the whole parameter-set for a future-proof basis were the models can be extended when the computing platform changes.

Experiments showed that a broad range of configurations can be covered by this model:

- various capacitors (ideal, Tantal, MLCC inkluding Bias-Effect)
- lithium batteries (LiPo, LiOn, LiFe)
- lead acid

## Modifications

For a more generalized `virtual storage`, the following extensions were implemented for `KiBaM`:

- support the rate capacity effect and transients during charging (the original focuses only on discharge)
- self discharge was added as it is relevant for capacitors
- a 0 % SoC will let the voltage break down to 0
- future extension: include DC-bias effect, see section below

Due to processing-constraints the following modifications are made implementing the model on the PRU:

- the transient effects (e.g. the two RC elements, eq. 4 - 7) are omitted
- the equations (2, 3) for the open-circuit voltage and series resistor are replaced by lookup-tables (LuTs) which are generated from the model equations ahead of time
- future plan: the quantized output voltage (due to the 128-entry LuT) may be smoothed via interpolation
- the capacitor is modeled discretely: `V_soc(t + dt) = V_soc(t) - (1 / C_capacity) * I_batt * dt`

## Comparison of Models

For qualifying the implementation a set of models was used to show differences in behavior:

- `KiBaM` is the model presented in the mentioned paper
- `KiBaMPlus` was extended to support the rate capacity effect and transients during charging (the original focuses only on discharge). It also added self discharge via a parallel leakage resistor
- `VirtualStorage` is the stripped down PRU-Version (see Modifications listed above)
- `ShpCap` is the (now) legacy implementation of the energy storage for shepherd

These models are capable of receiving and simulating the same parameter-sets

- `LiPo` battery with 10 mAh & 3.7 V nominal voltage
- ~~`Lead Acid` battery with 10 mAh & 12 V nominal voltage (6 cells)~~
- an ideal `Capacitor` with 10 F (to be comparable) and a rated Voltage of 4.2 V

For each a set of experiments was constructed to display the individual behavior

- a 20 Ohm resistive load
- pulsed charging
- ~~pulsed discharging~~ (similar to resistive load)
- ~~self discharge~~

The python scripts can be found in [shepherd_core/examples/simulations/vstorage.py](https://github.com/nes-lab/shepherd-tools/blob/dev/shepherd_core/examples/simulations/vstorage.py).

### Resistive Load

Putting a 20 Ohm load on the capacitor shows no surprises - all 4 models match in behavior:

![comparison cap resistive load](./media_storage/Capacitor_10000000uF_4.2V_resistive_load_20_Ohm.png)

Differences start to show when looking at the LiPo battery:

![comparison lipo resistive load](./media_storage/LiPo_10mAh_3.7V_resistive_load_20_Ohm.png)

The KiBaM-based models both match in behavior and show the voltage curve of a typical lithium battery.
Even the stripped PRU-model (`VirtualStorage`) is close by, but lacks the rate capacity effect and is therefore missing the voltage drop.
The old shepherd capacitor (`ShpCap`) was not designed to mimic a battery and misbehaves completely.

### Pulsed Charging

Charging a capacitor with pulsed 100 mA is again covered by all 4 models:

![comparison cap pulsed_charging](./media_storage/Capacitor_10000000uF_4.2V_pulsed_charge_.1A.png)

Differences show again when looking at the LiPo:

![comparison bat pulsed_charging](./media_storage/LiPo_10mAh_3.7V_pulsed_charge_.1A.png)

While the old shepherd capacitor (`ShpCap`) was not designed to mimic a battery and can be ignored, the other models show interesting behaviors.
This time the simple KiBaM and the stripped PRU-Model (`VirtualStorage`) match, as both don't support transients during charging.
Looking at the voltages a non-linear trend shows, typical for lithium batteries.
In addition `KiBaMPlus` handles the rate capacity effect during charging, which shows as voltage increase while current is flowing.

## DC-Bias Effect

Some capacitors like MLCC-variants show a variable capacity, depending on the voltage they are used.
Small packages with high capacity are particularly susceptible to this DC-bias effect.
The datasheet of the JMK316ABJ107ML a 100 uF X5R MLCC with a rated voltage of 6.3 V show a capacity decrease of 80 % when run at the rated voltage.

![dc-bias](./media_storage/comparison_dc_bias.png)

In comparison to an ideal capacitor the charge- and discharge-curves differ substantially.
We were able to verify the datasheet for that specific capacitor by measuring both curves and plotting the datasheet data next to it (`direct`).
As an experiment the `VirtualStorage` PRU-Model (called `BatteryModel` in plot) was adapted to contain this effect in the SoC-LuT.

:::{note}
TODO: WORK IN PROGRESS
The DC-bias effect will be included in the near future. More measurements and research are needed to offer a parameter-set.
:::

## References

- parameters for the config can be found as [data-model in the core-tool](https://github.com/nes-lab/shepherd-tools/tree/main/shepherd_core/shepherd_core/data_models/content)
- a fixture creation script and the fixtures itself are in the same directory
- the virtual storage for the testbed is implemented in c and [part of the PRU-firmware](https://github.com/nes-lab/shepherd/tree/main/software/firmware/pru0-shepherd-fw)
- the 1-to-1 simulation-models are part of the [python vSource-implementation](https://github.com/nes-lab/shepherd-tools/tree/main/shepherd_core/shepherd_core/vsource)
- simulation-experiments are kept in the [examples-directory of the core-tool](https://github.com/nes-lab/shepherd-tools/tree/main/shepherd_core/examples/simulation)
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# uv pip install .
[project]
name = "shepherd-main"
version = "2025.08.1"
version = "2025.11.1"
description = "Infrastructure for the Testbed, mainly focused on the Observers "
readme = "README.md"

Expand Down Expand Up @@ -56,6 +56,10 @@ shepherd-cal = { path = "./software/shepherd-calibration", editable = true}
shepherd-pru = { path = "./software/firmware/pru0-module-py", editable = true}
sync-analysis = { path = "./software/debug_analyze_time_sync", editable = true}

# temporary dev-versions of sub-packets
shepherd-data = { git = "https://github.com/nes-lab/shepherd-tools/", branch = "dev", subdirectory = "shepherd_data"}
shepherd-core = { git = "https://github.com/nes-lab/shepherd-tools/", branch = "dev", subdirectory = "shepherd_core"}

[tool.setuptools]
# alibi declaration to avoid auto-discovery
packages = ["shepherd-herd",]
Expand Down
14 changes: 14 additions & 0 deletions software/build_py.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# dev-script for faster rebuilding (compared to ansible)
sudo systemctl stop shepherd-watchdog
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_sheep/__pycache__
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_watchdog/__pycache__
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_core/__pycache__
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_core/testbed_client/__pycache__
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_core/vsource/__pycache__
sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib/python3.11/site-packages/shepherd_core/inventory/__pycache__
sudo rm -rf /home/jane/.venv/lib/python3.11/site-packages/shepherd_sheep/__pycache__
sudo rm -rf /home/jane/.venv/lib/python3.11/site-packages/shepherd_watchdog/__pycache__
sudo rm -rf /home/jane/.venv/lib/python3.11/site-packages/shepherd_core/vsource/__pycache__
sudo rm -rf /home/jane/.venv/lib/python3.11/site-packages/shepherd_core/__pycache__
# sudo rm -rf /home/jane/.local/share/uv/tools/shepherd-sheep/lib
# TODO: last can replace the 3 before
uv tool install /opt/shepherd/software/python-package/.
uv cache prune
sudo systemctl start shepherd-watchdog
# sudo shepherd-sheep -v run /etc/shepherd/example_config_emulation.yaml
4 changes: 3 additions & 1 deletion software/debug_analyze_time_sync/config_emulation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ parameters:
inherit_from: BQ25570
harvester:
name: mppt_bq_solar
V_intermediate_init_mV: 3600
storage:
name: Capacitor_100uF_6.3V
SoC_init: 0.8 # allow a proper / fast startup
V_buck_drop_mV: 0
V_output_mV: 3000
use_cal_default: false
Expand Down
2 changes: 1 addition & 1 deletion software/debug_analyze_time_sync/sync_analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .logic_trace import LogicTrace
from .logic_traces import LogicTraces

__version__ = "2025.8.1"
__version__ = "2025.11.1"

__all__ = [
"LogicTrace",
Expand Down
48 changes: 48 additions & 0 deletions software/debug_compare_vsources/bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Alternative to sampling real data from harvester

This only tests the emulation-tool-chain from virtual harvesting and all major virtual sources.

Input data is the jogging-dataset from the shepherd-tools.
"""

from pathlib import Path
from urllib.request import urlretrieve

from shepherd_core import log
from shepherd_core.data_models import VirtualHarvesterConfig
from shepherd_core.vsource import simulate_harvester
from shepherd_data import ivonne

sim_duration = 32
file_url = "https://github.com/nes-lab/shepherd-tools/raw/refs/heads/main/shepherd_data/examples/jogging_10m.iv"
path_root = Path(__file__).parent / "sheep0"
file_ivonne = path_root / "jogging_10m.iv"
file_ivcurve = path_root / "hrv_ivcurve.h5"

hrv_list = [
"mppt_voc",
"mppt_po",
]

if not file_ivonne.exists():
log.info("Input-IV-File not found - will download it")
urlretrieve(file_url, file_ivonne) # noqa: S310

# convert IVonne to IVCurve
if not file_ivcurve.exists():
log.info("Input-IVCurve-File not found - will download it")
with ivonne.Reader(file_ivonne) as db:
db.convert_2_ivsurface(file_ivcurve, duration_s=sim_duration)

# Simulated harvest
for hrv_name in hrv_list:
file_output = path_root / f"hrv_{hrv_name}.h5"
if file_output.exists():
log.info("Output-File file '%s' already exists, will skip!", file_output.name)

E_out_Ws = simulate_harvester(
config=VirtualHarvesterConfig(name=hrv_name),
path_input=file_ivcurve,
path_output=file_output,
)
log.info("E_out = %.3f mWs -> %s", E_out_Ws * 1e3, hrv_name)
2 changes: 1 addition & 1 deletion software/debug_compare_vsources/emulate_cpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# #####################################################################

for hrv_name, src_name in product(emu_hrv_list, emu_src_list):
path_input = Path(__file__).parent / host_selected / f"hrv_{hrv_name}.h5"
path_input = path_here / host_selected / f"hrv_{hrv_name}.h5"
path_output = path_input.with_stem(path_input.stem + "_" + src_name + "_cpy_sim")
if not path_output.exists():
simulate_source(
Expand Down
Loading
Loading