shepherd-core 2024.7.4__tar.gz → 2024.8.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/PKG-INFO +1 -1
- shepherd_core-2024.8.1/examples/eenv_generator.py +43 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/vharvester_simulation.py +26 -3
- shepherd_core-2024.8.1/examples/vsource_emulation.py +86 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/calibration.py +20 -22
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/virtual_harvester.py +18 -11
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/virtual_harvester_fixture.yaml +10 -13
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/virtual_source.py +6 -4
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/virtual_source_fixture.yaml +10 -8
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/reader.py +9 -4
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/version.py +1 -1
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/vsource/virtual_converter_model.py +21 -6
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/vsource/virtual_harvester_model.py +18 -8
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/writer.py +13 -3
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/PKG-INFO +1 -1
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/SOURCES.txt +2 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/vsource/test_converter.py +10 -4
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/README.md +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/experiment_from_yaml.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/experiment_generic_var1.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/experiment_generic_var2.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/experiment_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/firmware_model.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/firmware_modification.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/inventory.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/uart_decode_waveform.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/uart_raw2.csv +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/examples/vsource_simulation.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/pyproject.toml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/setup.cfg +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/calibration_hw_def.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/commons.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/cal_measurement.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/content.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/shepherd.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/timezone.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/wrapper.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/_external_fixtures.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/energy_environment.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/energy_environment_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/firmware.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/content/firmware_datatype.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/experiment/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/experiment/experiment.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/experiment/observer_features.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/experiment/target_config.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/readme.md +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/emulation.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/firmware_mod.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/harvest.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/observer_tasks.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/programming.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/task/testbed_tasks.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/cape.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/cape_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/gpio.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/gpio_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/mcu.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/mcu_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/observer.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/observer_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/target.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/target_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/testbed.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/testbed/testbed_fixture.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/virtual_source_doc.txt +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/decoder_waveform/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/decoder_waveform/uart.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/fw_tools/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/fw_tools/converter.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/fw_tools/converter_elf.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/fw_tools/patcher.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/fw_tools/validation.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/inventory/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/inventory/python.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/inventory/system.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/inventory/target.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/logger.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/cache_path.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/client_abc_fix.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/client_web.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/fixtures.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/testbed_client/user_model.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/vsource/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/vsource/virtual_source_model.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/dependency_links.txt +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/requires.txt +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/top_level.txt +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core.egg-info/zip-safe +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/conftest.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/conftest.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_cal_data.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_cal_data_faulty.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_cal_meas.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_cal_meas_faulty1.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_cal_meas_faulty2.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_emulator.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_experiment.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_experiment_alternative.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_harvester.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_testbed.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/example_config_virtsource.yaml +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_base_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_content_fixtures.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_content_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_examples.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_experiment_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_task_generation.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_task_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_testbed_fixtures.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/data_models/test_testbed_models.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/decoder_waveform/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/decoder_waveform/test_decoder.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/build_msp.elf +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/build_nrf.elf +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/conftest.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/test_converter.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/test_patcher.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/fw_tools/test_validation.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/inventory/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/inventory/test_inventory.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/test_cal_hw.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/test_examples.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/test_logger.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/test_reader.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/test_writer.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/testbed_client/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/vsource/__init__.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/vsource/conftest.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/vsource/test_harvester.py +0 -0
- {shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/tests/vsource/test_z.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: shepherd_core
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.8.1
|
|
4
4
|
Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
|
|
5
5
|
Author-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
|
|
6
6
|
Maintainer-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Create a set of static artificial energy environments."""
|
|
2
|
+
|
|
3
|
+
from itertools import product
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from tqdm import trange
|
|
8
|
+
|
|
9
|
+
from shepherd_core import Reader as ShpReader
|
|
10
|
+
from shepherd_core import Writer as ShpWriter
|
|
11
|
+
from shepherd_core import logger
|
|
12
|
+
|
|
13
|
+
# Config
|
|
14
|
+
voltages_V = [4.0, 2.0]
|
|
15
|
+
currents_A = [2e-3, 1e-3]
|
|
16
|
+
duration_s = 10
|
|
17
|
+
repetitions = 1
|
|
18
|
+
|
|
19
|
+
path_here = Path(__file__).parent.absolute()
|
|
20
|
+
|
|
21
|
+
for _v, _c in product(voltages_V, currents_A):
|
|
22
|
+
v_str = f"{round(_v * 1000)}mV"
|
|
23
|
+
c_str = f"{round(_c * 1000)}mA"
|
|
24
|
+
t_str = f"{round(duration_s * repetitions)}s"
|
|
25
|
+
name = f"eenv_static_{v_str}_{c_str}_{t_str}"
|
|
26
|
+
file_path = path_here / f"{name}.h5"
|
|
27
|
+
|
|
28
|
+
if file_path.exists():
|
|
29
|
+
logger.info("File exists, will skip: %s", file_path.name)
|
|
30
|
+
else:
|
|
31
|
+
with ShpWriter(file_path) as file:
|
|
32
|
+
file.store_hostname("artificial")
|
|
33
|
+
# values in SI units
|
|
34
|
+
timestamp_vector = np.arange(0.0, duration_s, file.sample_interval_ns / 1e9)
|
|
35
|
+
voltage_vector = np.linspace(_v, _v, int(file.samplerate_sps * duration_s))
|
|
36
|
+
current_vector = np.linspace(_c, _c, int(file.samplerate_sps * duration_s))
|
|
37
|
+
|
|
38
|
+
for idx in trange(repetitions, desc="generate"):
|
|
39
|
+
timestamps = idx * duration_s + timestamp_vector
|
|
40
|
+
file.append_iv_data_si(timestamps, voltage_vector, current_vector)
|
|
41
|
+
|
|
42
|
+
with ShpReader(file_path) as file:
|
|
43
|
+
file.save_metadata()
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
from contextlib import ExitStack
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
12
|
+
from shepherd_core import CalibrationHarvester
|
|
11
13
|
from shepherd_core import Reader
|
|
14
|
+
from shepherd_core import Writer
|
|
12
15
|
from shepherd_core.data_models import VirtualHarvesterConfig
|
|
13
16
|
from shepherd_core.data_models.content.virtual_harvester import HarvesterPRUConfig
|
|
14
17
|
from shepherd_core.vsource import VirtualHarvesterModel
|
|
@@ -32,6 +35,8 @@ hrv_list = [
|
|
|
32
35
|
"mppt_opt",
|
|
33
36
|
]
|
|
34
37
|
|
|
38
|
+
save_files: bool = True
|
|
39
|
+
|
|
35
40
|
# convert IVonne to IVCurve
|
|
36
41
|
if not file_ivcurve.exists():
|
|
37
42
|
with ivonne.Reader(file_ivonne) as db:
|
|
@@ -45,7 +50,7 @@ with Reader(file_ivcurve, verbose=False) as file:
|
|
|
45
50
|
I_in_max = max(I_in_max, _i.max())
|
|
46
51
|
print(
|
|
47
52
|
f"Input-file: \n"
|
|
48
|
-
f"\tE_in = {file.energy() * 1e3:.3f} mWs\n"
|
|
53
|
+
f"\tE_in = {file.energy() * 1e3:.3f} mWs (not representative)\n"
|
|
49
54
|
f"\tI_in_max = {I_in_max * 1e3:.3f} mA\n"
|
|
50
55
|
f"\twindow_size = {window_size} n\n",
|
|
51
56
|
)
|
|
@@ -53,21 +58,39 @@ with Reader(file_ivcurve, verbose=False) as file:
|
|
|
53
58
|
# Simulation
|
|
54
59
|
for hrv_name in hrv_list:
|
|
55
60
|
E_out_Ws = 0.0
|
|
61
|
+
_cal = CalibrationHarvester()
|
|
62
|
+
if save_files:
|
|
63
|
+
stack = ExitStack()
|
|
64
|
+
file_output = file_ivcurve.with_name(
|
|
65
|
+
file_ivcurve.stem + "_" + hrv_name + file_ivcurve.suffix
|
|
66
|
+
)
|
|
67
|
+
fh_output = Writer(
|
|
68
|
+
file_output, cal_data=_cal, mode="harvester", verbose=False, force_overwrite=True
|
|
69
|
+
)
|
|
70
|
+
stack.enter_context(fh_output)
|
|
71
|
+
fh_output.store_hostname("hrv_sim_" + hrv_name)
|
|
72
|
+
|
|
56
73
|
with Reader(file_ivcurve, verbose=False) as file:
|
|
57
74
|
hrv_config = VirtualHarvesterConfig(name=hrv_name)
|
|
58
75
|
hrv_pru = HarvesterPRUConfig.from_vhrv(
|
|
59
76
|
hrv_config,
|
|
60
77
|
for_emu=True,
|
|
61
78
|
dtype_in=file.get_datatype(),
|
|
62
|
-
window_size=file.get_window_samples(),
|
|
79
|
+
window_size=4 * file.get_window_samples(),
|
|
63
80
|
)
|
|
64
81
|
hrv = VirtualHarvesterModel(hrv_pru)
|
|
65
82
|
for _t, _v, _i in file.read_buffers():
|
|
83
|
+
# TODO: _t should be handed to new file without conversions
|
|
66
84
|
length = max(_v.size, _i.size)
|
|
67
85
|
for _n in range(length):
|
|
68
86
|
_v[_n], _i[_n] = hrv.ivcurve_sample(
|
|
69
87
|
_voltage_uV=_v[_n] * 10**6, _current_nA=_i[_n] * 10**9
|
|
70
88
|
)
|
|
71
89
|
E_out_Ws += (_v * _i).sum() * 1e-15 * file.sample_interval_s
|
|
72
|
-
|
|
90
|
+
if save_files:
|
|
91
|
+
fh_output.append_iv_data_si(_t, _v / 1e6, _i / 1e9)
|
|
92
|
+
if save_files:
|
|
93
|
+
stack.close()
|
|
94
|
+
with Reader(file_output) as fh_output:
|
|
95
|
+
fh_output.save_metadata()
|
|
73
96
|
print(f"E_out = {E_out_Ws * 1e3:.3f} mWs -> {hrv_name}")
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Demonstrate behavior of Virtual Source Algorithms.
|
|
2
|
+
|
|
3
|
+
The emulation recreates an observer-cape, the virtual Source and a virtual target
|
|
4
|
+
- input = hdf5-file with a harvest-recording
|
|
5
|
+
- output = hdf5-file
|
|
6
|
+
- config is currently hardcoded, but it could be an emulation-task
|
|
7
|
+
- target is currently a simple resistor
|
|
8
|
+
|
|
9
|
+
The output file can be analyzed and plotted with shepherds tool suite.
|
|
10
|
+
"""
|
|
11
|
+
# TODO: `shepherd-data emulate config.yaml`
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from tqdm import tqdm
|
|
17
|
+
|
|
18
|
+
from shepherd_core import CalibrationEmulator
|
|
19
|
+
from shepherd_core import Reader
|
|
20
|
+
from shepherd_core import Writer
|
|
21
|
+
from shepherd_core.data_models import VirtualHarvesterConfig
|
|
22
|
+
from shepherd_core.data_models import VirtualSourceConfig
|
|
23
|
+
from shepherd_core.vsource import VirtualSourceModel
|
|
24
|
+
|
|
25
|
+
# config simulation
|
|
26
|
+
file_input = Path(__file__).parent / "jogging_ivcurve.h5"
|
|
27
|
+
|
|
28
|
+
src_list = ["BQ25504"]
|
|
29
|
+
|
|
30
|
+
I_mcu_sleep_A = 3e-3
|
|
31
|
+
I_mcu_active_A = 3e-3
|
|
32
|
+
R_Ohm = 1000
|
|
33
|
+
|
|
34
|
+
for vs_name in src_list:
|
|
35
|
+
file_output = file_input.with_name(file_input.stem + "_emu_" + vs_name + file_input.suffix)
|
|
36
|
+
|
|
37
|
+
cal_emu = CalibrationEmulator()
|
|
38
|
+
src_config = VirtualSourceConfig(
|
|
39
|
+
inherit_from=vs_name,
|
|
40
|
+
V_intermediate_init_mV=3000,
|
|
41
|
+
harvester=VirtualHarvesterConfig(name="mppt_bq_solar"),
|
|
42
|
+
C_intermediate_uF=50,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
with Reader(file_input, verbose=False) as f_inp, Writer(
|
|
46
|
+
file_output, cal_data=cal_emu, mode="emulator", verbose=False
|
|
47
|
+
) as f_out:
|
|
48
|
+
window_size = f_inp.get_window_samples()
|
|
49
|
+
f_out.store_hostname("emu_sim_" + vs_name)
|
|
50
|
+
f_out.store_config(src_config.model_dump())
|
|
51
|
+
src = VirtualSourceModel(
|
|
52
|
+
src_config, cal_emu, log_intermediate=False, window_size=window_size
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
I_out_nA = 0
|
|
56
|
+
|
|
57
|
+
for _t, _V_inp, _I_inp in tqdm(f_inp.read_buffers(), total=f_inp.buffers_n):
|
|
58
|
+
V_out = np.empty(_V_inp.shape)
|
|
59
|
+
I_out = np.empty(_I_inp.shape)
|
|
60
|
+
|
|
61
|
+
for _iter in range(len(_t)):
|
|
62
|
+
V_out_uV = src.iterate_sampling(
|
|
63
|
+
V_inp_uV=_V_inp[_iter] * 10**6,
|
|
64
|
+
I_inp_nA=_I_inp[_iter] * 10**9,
|
|
65
|
+
I_out_nA=I_out_nA,
|
|
66
|
+
)
|
|
67
|
+
I_out_nA = 1e3 * V_out_uV / R_Ohm
|
|
68
|
+
|
|
69
|
+
V_out[_iter] = V_out_uV / 1e6
|
|
70
|
+
I_out[_iter] = I_out_nA / 1e9
|
|
71
|
+
|
|
72
|
+
# TODO: src.cnv.get_I_mod_out_nA() has more internal drains
|
|
73
|
+
|
|
74
|
+
f_out.append_iv_data_si(_t, V_out, I_out)
|
|
75
|
+
|
|
76
|
+
# listen to power-good signal
|
|
77
|
+
"""
|
|
78
|
+
if src.cnv.get_power_good():
|
|
79
|
+
I_out_nA = int(I_mcu_active_A * 10 ** 9)
|
|
80
|
+
N_good += 1
|
|
81
|
+
else:
|
|
82
|
+
I_out_nA = int(I_mcu_sleep_A * 10 ** 9)
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
with Reader(file_output, verbose=False) as f_out:
|
|
86
|
+
f_out.save_metadata()
|
{shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/data_models/base/calibration.py
RENAMED
|
@@ -51,7 +51,7 @@ class CalibrationPair(ShpModel):
|
|
|
51
51
|
|
|
52
52
|
gain: PositiveFloat
|
|
53
53
|
offset: float = 0
|
|
54
|
-
# TODO: add
|
|
54
|
+
unit: Optional[str] = None # TODO: add units when used
|
|
55
55
|
|
|
56
56
|
def raw_to_si(self, values_raw: Calc_t, *, allow_negative: bool = True) -> Calc_t:
|
|
57
57
|
"""Convert between physical units and raw unsigned integers."""
|
|
@@ -78,14 +78,11 @@ class CalibrationPair(ShpModel):
|
|
|
78
78
|
return values_raw
|
|
79
79
|
|
|
80
80
|
@classmethod
|
|
81
|
-
def from_fn(cls, fn: Callable) -> Self:
|
|
81
|
+
def from_fn(cls, fn: Callable, unit: Optional[str] = None) -> Self:
|
|
82
82
|
"""Probe linear function to determine scaling values."""
|
|
83
83
|
offset = fn(0, limited=False)
|
|
84
84
|
gain_inv = fn(1.0, limited=False) - offset
|
|
85
|
-
return cls(
|
|
86
|
-
gain=1.0 / float(gain_inv),
|
|
87
|
-
offset=-float(offset) / gain_inv,
|
|
88
|
-
)
|
|
85
|
+
return cls(gain=1.0 / float(gain_inv), offset=-float(offset) / gain_inv, unit=unit)
|
|
89
86
|
|
|
90
87
|
|
|
91
88
|
cal_hrv_legacy = { # legacy translator
|
|
@@ -99,10 +96,10 @@ cal_hrv_legacy = { # legacy translator
|
|
|
99
96
|
class CalibrationHarvester(ShpModel):
|
|
100
97
|
"""Container for all calibration-pairs for that device."""
|
|
101
98
|
|
|
102
|
-
dac_V_Hrv: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw)
|
|
103
|
-
dac_V_Sim: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw)
|
|
104
|
-
adc_V_Sense: CalibrationPair = CalibrationPair.from_fn(adc_voltage_to_raw)
|
|
105
|
-
adc_C_Hrv: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw)
|
|
99
|
+
dac_V_Hrv: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw, unit="V")
|
|
100
|
+
dac_V_Sim: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw, unit="V")
|
|
101
|
+
adc_V_Sense: CalibrationPair = CalibrationPair.from_fn(adc_voltage_to_raw, unit="V")
|
|
102
|
+
adc_C_Hrv: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw, unit="A")
|
|
106
103
|
|
|
107
104
|
def export_for_sysfs(self) -> dict:
|
|
108
105
|
"""Convert and write the essential data.
|
|
@@ -143,10 +140,10 @@ class CalibrationEmulator(ShpModel):
|
|
|
143
140
|
Differentiates between both target-ports A/B.
|
|
144
141
|
"""
|
|
145
142
|
|
|
146
|
-
dac_V_A: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw)
|
|
147
|
-
dac_V_B: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw)
|
|
148
|
-
adc_C_A: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw)
|
|
149
|
-
adc_C_B: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw)
|
|
143
|
+
dac_V_A: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw, unit="V")
|
|
144
|
+
dac_V_B: CalibrationPair = CalibrationPair.from_fn(dac_voltage_to_raw, unit="V")
|
|
145
|
+
adc_C_A: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw, unit="A")
|
|
146
|
+
adc_C_B: CalibrationPair = CalibrationPair.from_fn(adc_current_to_raw, unit="A")
|
|
150
147
|
|
|
151
148
|
def export_for_sysfs(self) -> dict:
|
|
152
149
|
"""Convert and write the essential data.
|
|
@@ -233,10 +230,11 @@ class CalibrationCape(ShpModel):
|
|
|
233
230
|
|
|
234
231
|
"""
|
|
235
232
|
dv = cls().model_dump(include={"harvester", "emulator"})
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
lw1 = list(dict_generator(dv))
|
|
234
|
+
lw2 = [elem for elem in lw1 if isinstance(elem[-1], float)]
|
|
235
|
+
values = struct.unpack(">" + len(lw2) * "d", data)
|
|
238
236
|
# ⤷ X => double float, big endian
|
|
239
|
-
for _i, walk in enumerate(
|
|
237
|
+
for _i, walk in enumerate(lw2):
|
|
240
238
|
# hardcoded fixed depth ... bad but easy
|
|
241
239
|
dv[walk[0]][walk[1]][walk[2]] = float(values[_i])
|
|
242
240
|
dv["cape"] = cape
|
|
@@ -252,18 +250,18 @@ class CalibrationCape(ShpModel):
|
|
|
252
250
|
|
|
253
251
|
"""
|
|
254
252
|
lw = list(dict_generator(self.model_dump(include={"harvester", "emulator"})))
|
|
255
|
-
values = [walk[-1] for walk in lw]
|
|
256
|
-
return struct.pack(">" + len(
|
|
253
|
+
values = [walk[-1] for walk in lw if isinstance(walk[-1], float)]
|
|
254
|
+
return struct.pack(">" + len(values) * "d", *values)
|
|
257
255
|
|
|
258
256
|
|
|
259
257
|
class CalibrationSeries(ShpModel):
|
|
260
258
|
"""Cal-Data for a typical recording of a testbed experiment."""
|
|
261
259
|
|
|
262
|
-
voltage: CalibrationPair = CalibrationPair(gain=3 * 1e-9)
|
|
260
|
+
voltage: CalibrationPair = CalibrationPair(gain=3 * 1e-9, unit="V")
|
|
263
261
|
# ⤷ default allows 0 - 12 V in 3 nV-Steps
|
|
264
|
-
current: CalibrationPair = CalibrationPair(gain=250 * 1e-12)
|
|
262
|
+
current: CalibrationPair = CalibrationPair(gain=250 * 1e-12, unit="A")
|
|
265
263
|
# ⤷ default allows 0 - 1 A in 250 pA - Steps
|
|
266
|
-
time: CalibrationPair = CalibrationPair(gain=1e-9)
|
|
264
|
+
time: CalibrationPair = CalibrationPair(gain=1e-9, unit="s")
|
|
267
265
|
# ⤷ default = nanoseconds
|
|
268
266
|
|
|
269
267
|
@classmethod
|
|
@@ -149,20 +149,27 @@ class VirtualHarvesterConfig(ContentModel, title="Config for the Harvester"):
|
|
|
149
149
|
|
|
150
150
|
def calc_window_size(
|
|
151
151
|
self,
|
|
152
|
-
dtype_in: Optional[EnergyDType] =
|
|
152
|
+
dtype_in: Optional[EnergyDType] = None,
|
|
153
153
|
*,
|
|
154
154
|
for_emu: bool,
|
|
155
155
|
) -> int:
|
|
156
|
-
if for_emu:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
raise NotImplementedError
|
|
156
|
+
if not for_emu:
|
|
157
|
+
# TODO: should be named 'for_ivcurve_recording'
|
|
158
|
+
# TODO: add extra variable to distinguish step_count
|
|
159
|
+
# and window_size (currently mixed together)
|
|
160
|
+
# only used by ivcurve algo (in ADC-Mode)
|
|
161
|
+
return self.samples_n
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
if dtype_in is None:
|
|
164
|
+
dtype_in = self.get_datatype()
|
|
165
|
+
|
|
166
|
+
if dtype_in == EnergyDType.ivcurve:
|
|
167
|
+
return self.samples_n * (1 + self.wait_cycles)
|
|
168
|
+
if dtype_in == EnergyDType.ivsample:
|
|
169
|
+
return 0
|
|
170
|
+
if dtype_in == EnergyDType.isc_voc:
|
|
171
|
+
return 2 * (1 + self.wait_cycles)
|
|
172
|
+
raise NotImplementedError
|
|
166
173
|
|
|
167
174
|
|
|
168
175
|
u32 = Annotated[int, Field(ge=0, lt=2**32)]
|
|
@@ -234,7 +241,7 @@ class HarvesterPRUConfig(ShpModel):
|
|
|
234
241
|
dtype_in = EnergyDType[dtype_in]
|
|
235
242
|
if for_emu and dtype_in not in {EnergyDType.ivsample, EnergyDType.ivcurve}:
|
|
236
243
|
raise NotImplementedError
|
|
237
|
-
|
|
244
|
+
|
|
238
245
|
interval_ms, duration_ms = data.calc_timings_ms(for_emu=for_emu)
|
|
239
246
|
return cls(
|
|
240
247
|
algorithm=data.calc_algorithm_num(for_emu=for_emu),
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
id: 1010
|
|
20
20
|
name: ivcurve
|
|
21
21
|
description: Postpone harvesting by sampling ivcurves (voltage stepped as sawtooth-wave)
|
|
22
|
-
comment: ~
|
|
22
|
+
comment: ~110 Hz, Between 50 & 60 Hz line-frequency to avoid standing waves
|
|
23
23
|
inherit_from: neutral
|
|
24
24
|
algorithm: ivcurve
|
|
25
|
-
samples_n:
|
|
25
|
+
samples_n: 909
|
|
26
26
|
voltage_min_mV: 0
|
|
27
27
|
voltage_max_mV: 5000
|
|
28
|
-
wait_cycles:
|
|
28
|
+
wait_cycles: 0
|
|
29
29
|
rising: false # downward sawtooth seems to have advantages for solar cells
|
|
30
30
|
# todo: also add switch for sawtooth- vs triangle-wave?
|
|
31
31
|
# todo: could also include a version with dynamic upper-boundary, varied if voc is reached very early
|
|
@@ -38,20 +38,17 @@
|
|
|
38
38
|
|
|
39
39
|
- datatype: VirtualHarvesterConfig
|
|
40
40
|
parameters:
|
|
41
|
-
id:
|
|
42
|
-
name:
|
|
43
|
-
comment: Name relates to curves per second
|
|
41
|
+
id: 1013
|
|
42
|
+
name: iv110 # synonym
|
|
44
43
|
inherit_from: ivcurve
|
|
45
|
-
samples_n: 100
|
|
46
|
-
wait_cycles: 0
|
|
47
44
|
|
|
48
45
|
- datatype: VirtualHarvesterConfig
|
|
49
46
|
parameters:
|
|
50
|
-
id:
|
|
51
|
-
name:
|
|
52
|
-
comment:
|
|
47
|
+
id: 1012
|
|
48
|
+
name: iv1000
|
|
49
|
+
comment: Name relates to curves per second
|
|
53
50
|
inherit_from: ivcurve
|
|
54
|
-
samples_n:
|
|
51
|
+
samples_n: 100
|
|
55
52
|
wait_cycles: 0
|
|
56
53
|
|
|
57
54
|
- datatype: VirtualHarvesterConfig
|
|
@@ -61,7 +58,7 @@
|
|
|
61
58
|
description: Postpone harvesting by sampling short circuit current & open circuit voltage
|
|
62
59
|
inherit_from: neutral
|
|
63
60
|
algorithm: isc_voc
|
|
64
|
-
wait_cycles:
|
|
61
|
+
wait_cycles: 4 # results in 10 kHz (isc, wait, voc, wait)
|
|
65
62
|
|
|
66
63
|
- datatype: VirtualHarvesterConfig
|
|
67
64
|
parameters:
|
|
@@ -76,6 +76,8 @@ class VirtualSourceConfig(ContentModel, title="Config for the virtual Source"):
|
|
|
76
76
|
# final (always last) stage to compensate undetectable current spikes
|
|
77
77
|
# when enabling power for target
|
|
78
78
|
C_output_uF: Annotated[float, Field(ge=0, le=4.29e6)] = 1.0
|
|
79
|
+
# TODO: C_output is handled internally as delta-V, but should be a I_transient
|
|
80
|
+
# that makes it visible in simulation as additional i_out_drain
|
|
79
81
|
|
|
80
82
|
# Extra
|
|
81
83
|
V_output_log_gpio_threshold_mV: Annotated[float, Field(ge=0, le=4.29e6)] = 1_400
|
|
@@ -93,7 +95,7 @@ class VirtualSourceConfig(ContentModel, title="Config for the virtual Source"):
|
|
|
93
95
|
# influence of cap-voltage is not implemented
|
|
94
96
|
LUT_input_V_min_log2_uV: Annotated[int, Field(ge=0, le=20)] = 0
|
|
95
97
|
# ⤷ 2^7 = 128 uV -> LUT[0][:] is for inputs < 128 uV
|
|
96
|
-
LUT_input_I_min_log2_nA: Annotated[int, Field(ge=
|
|
98
|
+
LUT_input_I_min_log2_nA: Annotated[int, Field(ge=1, le=20)] = 1
|
|
97
99
|
# ⤷ 2^8 = 256 nA -> LUT[:][0] is for inputs < 256 nA
|
|
98
100
|
|
|
99
101
|
# Buck Converter
|
|
@@ -103,7 +105,7 @@ class VirtualSourceConfig(ContentModel, title="Config for the virtual Source"):
|
|
|
103
105
|
|
|
104
106
|
LUT_output_efficiency: LUT1D = 12 * [1.00]
|
|
105
107
|
# ⤷ array[12] depending on output_current
|
|
106
|
-
LUT_output_I_min_log2_nA: Annotated[int, Field(ge=
|
|
108
|
+
LUT_output_I_min_log2_nA: Annotated[int, Field(ge=1, le=20)] = 1
|
|
107
109
|
# ⤷ 2^8 = 256 nA -> LUT[0] is for inputs < 256 nA, see notes on LUT_input for explanation
|
|
108
110
|
|
|
109
111
|
@model_validator(mode="before")
|
|
@@ -318,8 +320,8 @@ class ConverterPRUConfig(ShpModel):
|
|
|
318
320
|
V_buck_drop_uV=round(data.V_buck_drop_mV * 1e3),
|
|
319
321
|
# LUTs
|
|
320
322
|
LUT_input_V_min_log2_uV=data.LUT_input_V_min_log2_uV,
|
|
321
|
-
LUT_input_I_min_log2_nA=data.LUT_input_I_min_log2_nA,
|
|
322
|
-
LUT_output_I_min_log2_nA=data.LUT_output_I_min_log2_nA,
|
|
323
|
+
LUT_input_I_min_log2_nA=data.LUT_input_I_min_log2_nA - 1, # sub-1 due to later log2-op
|
|
324
|
+
LUT_output_I_min_log2_nA=data.LUT_output_I_min_log2_nA - 1, # sub-1 due to later log2
|
|
323
325
|
LUT_inp_efficiency_n8=[
|
|
324
326
|
[min(255, round(256 * ival)) for ival in il] for il in data.LUT_input_efficiency
|
|
325
327
|
],
|
|
@@ -56,16 +56,18 @@
|
|
|
56
56
|
[ 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00 ],
|
|
57
57
|
[ 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00 ],
|
|
58
58
|
[ 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00 ],
|
|
59
|
-
]
|
|
59
|
+
]
|
|
60
|
+
# input-array[12][12] depending on array[inp_voltage][log(inp_current)],
|
|
61
|
+
# influence of cap-voltage is not implemented
|
|
60
62
|
LUT_input_V_min_log2_uV: 0 # 2^7 = 128 uV -> array[0] is for inputs < 128 uV
|
|
61
|
-
LUT_input_I_min_log2_nA:
|
|
63
|
+
LUT_input_I_min_log2_nA: 1 # 2^8 = 256 nA -> array[0] is for inputs < 256 nA
|
|
62
64
|
|
|
63
65
|
# Buck-converter
|
|
64
66
|
V_output_mV: 2400
|
|
65
67
|
V_buck_drop_mV: 0.0 # simulate LDO min voltage differential or output-diode
|
|
66
68
|
|
|
67
69
|
LUT_output_efficiency: [ 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00 ] # array[12] depending on output_current
|
|
68
|
-
LUT_output_I_min_log2_nA:
|
|
70
|
+
LUT_output_I_min_log2_nA: 1 # 2^8 = 256 nA -> array[0] is for inputs < 256 nA, see notes on LUT_input for explanation
|
|
69
71
|
|
|
70
72
|
owner: Ingmar
|
|
71
73
|
group: NES Lab
|
|
@@ -114,7 +116,7 @@
|
|
|
114
116
|
parameters:
|
|
115
117
|
id: 1020
|
|
116
118
|
name: BQ25504
|
|
117
|
-
description: TI BQ25504 with integrated boost-converter
|
|
119
|
+
description: TI BQ25504 with integrated boost-converter. Values are taken from the DK-Board.
|
|
118
120
|
inherit_from: neutral # to complete undefined vars
|
|
119
121
|
enable_boost: true # if false -> v_intermediate = v_input, output-switch-hysteresis is still usable
|
|
120
122
|
|
|
@@ -124,16 +126,16 @@
|
|
|
124
126
|
V_input_max_mV: 3000
|
|
125
127
|
I_input_max_mA: 100
|
|
126
128
|
|
|
127
|
-
C_intermediate_uF:
|
|
129
|
+
C_intermediate_uF: 100.0 # primary storage-Cap
|
|
128
130
|
V_intermediate_init_mV: 3000 # allow a proper / fast startup
|
|
129
131
|
I_intermediate_leak_nA: 330
|
|
130
132
|
|
|
131
|
-
V_intermediate_enable_threshold_mV:
|
|
132
|
-
V_intermediate_disable_threshold_mV:
|
|
133
|
+
V_intermediate_enable_threshold_mV: 1000 # -> target gets connected (hysteresis-combo with next value)
|
|
134
|
+
V_intermediate_disable_threshold_mV: 0 # -> target gets disconnected
|
|
133
135
|
interval_check_thresholds_ms: 64.0 # some BQs check every 64 ms if output should be disconnected
|
|
134
136
|
|
|
135
137
|
V_pwr_good_enable_threshold_mV: 2800 # target is informed by pwr-good on output-pin (hysteresis) -> for intermediate voltage
|
|
136
|
-
V_pwr_good_disable_threshold_mV:
|
|
138
|
+
V_pwr_good_disable_threshold_mV: 2340
|
|
137
139
|
immediate_pwr_good_signal: false # 1: activate instant schmitt-trigger, 0: stay in interval for checking thresholds
|
|
138
140
|
|
|
139
141
|
# Boost Converter
|
|
@@ -84,6 +84,7 @@ class Reader:
|
|
|
84
84
|
|
|
85
85
|
# init stats
|
|
86
86
|
self.runtime_s: float = 0
|
|
87
|
+
self.buffers_n: int = 0
|
|
87
88
|
self.file_size: int = 0
|
|
88
89
|
self.data_rate: float = 0
|
|
89
90
|
|
|
@@ -170,12 +171,16 @@ class Reader:
|
|
|
170
171
|
def _refresh_file_stats(self) -> None:
|
|
171
172
|
"""Update internal states, helpful after resampling or other changes in data-group."""
|
|
172
173
|
self.h5file.flush()
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
sample_count = self.ds_time.shape[0]
|
|
175
|
+
duration_raw = self.ds_time[sample_count - 1] - self.ds_time[0] if sample_count > 0 else 0
|
|
176
|
+
if (sample_count > 0) and (duration_raw > 0):
|
|
177
|
+
# this assumes iso-chronous sampling
|
|
178
|
+
duration_s = self._cal.time.raw_to_si(duration_raw)
|
|
179
|
+
self.sample_interval_s = duration_s / sample_count
|
|
176
180
|
self.sample_interval_ns = int(10**9 * self.sample_interval_s)
|
|
177
|
-
self.samplerate_sps = max(int(
|
|
181
|
+
self.samplerate_sps = max(int((sample_count - 1) / duration_s), 1)
|
|
178
182
|
self.runtime_s = round(self.ds_voltage.shape[0] / self.samplerate_sps, 1)
|
|
183
|
+
self.buffers_n = int(self.ds_voltage.shape[0] // self.samples_per_buffer)
|
|
179
184
|
if isinstance(self.file_path, Path):
|
|
180
185
|
self.file_size = self.file_path.stat().st_size
|
|
181
186
|
else:
|
{shepherd_core-2024.7.4 → shepherd_core-2024.8.1}/shepherd_core/vsource/virtual_converter_model.py
RENAMED
|
@@ -25,12 +25,28 @@ from ..data_models.content.virtual_source import ConverterPRUConfig
|
|
|
25
25
|
class PruCalibration:
|
|
26
26
|
"""part of calibration.h."""
|
|
27
27
|
|
|
28
|
+
# negative residue compensation - compensate for noise around 0
|
|
29
|
+
# -> current uint-design cuts away negative part and leads to biased mean()
|
|
30
|
+
NOISE_ESTIMATE_nA: int = 2000
|
|
31
|
+
RESIDUE_SIZE_FACTOR: int = 30
|
|
32
|
+
RESIDUE_MAX_nA: int = NOISE_ESTIMATE_nA * RESIDUE_SIZE_FACTOR
|
|
33
|
+
negative_residue_nA = 0
|
|
34
|
+
|
|
28
35
|
def __init__(self, cal_emu: Optional[CalibrationEmulator] = None) -> None:
|
|
29
36
|
self.cal = cal_emu if cal_emu else CalibrationEmulator()
|
|
30
37
|
|
|
31
38
|
def conv_adc_raw_to_nA(self, current_raw: int) -> float:
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
I_nA = self.cal.adc_C_A.raw_to_si(current_raw) * (10**9)
|
|
40
|
+
if self.cal.adc_C_A.offset < 0:
|
|
41
|
+
if I_nA > self.negative_residue_nA:
|
|
42
|
+
I_nA -= self.negative_residue_nA
|
|
43
|
+
self.negative_residue_nA = 0
|
|
44
|
+
else:
|
|
45
|
+
self.negative_residue_nA = self.negative_residue_nA - I_nA
|
|
46
|
+
if self.negative_residue_nA > self.RESIDUE_MAX_nA:
|
|
47
|
+
self.negative_residue_nA = self.RESIDUE_MAX_nA
|
|
48
|
+
I_nA = 0
|
|
49
|
+
return I_nA
|
|
34
50
|
|
|
35
51
|
@staticmethod
|
|
36
52
|
def conv_adc_raw_to_uV(voltage_raw: int) -> float:
|
|
@@ -88,10 +104,11 @@ class VirtualConverterModel:
|
|
|
88
104
|
self.vsource_skip_gpio_logging: bool = False
|
|
89
105
|
|
|
90
106
|
def calc_inp_power(self, input_voltage_uV: float, input_current_nA: float) -> int:
|
|
91
|
-
# Next 2 lines are Python-specific
|
|
107
|
+
# Next 2 lines are Python-specific (model unsigned int)
|
|
92
108
|
input_voltage_uV = max(0.0, input_voltage_uV)
|
|
93
109
|
input_current_nA = max(0.0, input_current_nA)
|
|
94
110
|
|
|
111
|
+
# Input diode
|
|
95
112
|
if input_voltage_uV > self._cfg.V_input_drop_uV:
|
|
96
113
|
input_voltage_uV -= self._cfg.V_input_drop_uV
|
|
97
114
|
else:
|
|
@@ -108,8 +125,6 @@ class VirtualConverterModel:
|
|
|
108
125
|
if self.enable_boost:
|
|
109
126
|
if input_voltage_uV < self._cfg.V_input_boost_threshold_uV:
|
|
110
127
|
input_voltage_uV = 0.0
|
|
111
|
-
if input_voltage_uV > self.V_mid_uV:
|
|
112
|
-
input_voltage_uV = self.V_mid_uV
|
|
113
128
|
elif not self.enable_storage:
|
|
114
129
|
# direct connection
|
|
115
130
|
self.V_mid_uV = input_voltage_uV
|
|
@@ -134,7 +149,7 @@ class VirtualConverterModel:
|
|
|
134
149
|
return round(self.P_inp_fW) # Python-specific, added for easier testing
|
|
135
150
|
|
|
136
151
|
def calc_out_power(self, current_adc_raw: int) -> int:
|
|
137
|
-
# Next 2 lines are Python-specific
|
|
152
|
+
# Next 2 lines are Python-specific (model unsigned int)
|
|
138
153
|
current_adc_raw = max(0, current_adc_raw)
|
|
139
154
|
current_adc_raw = min((2**18) - 1, current_adc_raw)
|
|
140
155
|
|