shepherd-core 2024.9.1__py3-none-any.whl → 2024.11.1__py3-none-any.whl
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/data_models/content/virtual_source_fixture.yaml +1 -0
- shepherd_core/version.py +1 -1
- shepherd_core/vsource/target_model.py +5 -4
- shepherd_core/vsource/virtual_converter_model.py +8 -5
- shepherd_core/vsource/virtual_harvester_model.py +2 -1
- shepherd_core/writer.py +47 -54
- {shepherd_core-2024.9.1.dist-info → shepherd_core-2024.11.1.dist-info}/METADATA +1 -1
- {shepherd_core-2024.9.1.dist-info → shepherd_core-2024.11.1.dist-info}/RECORD +11 -11
- {shepherd_core-2024.9.1.dist-info → shepherd_core-2024.11.1.dist-info}/WHEEL +1 -1
- {shepherd_core-2024.9.1.dist-info → shepherd_core-2024.11.1.dist-info}/top_level.txt +0 -0
- {shepherd_core-2024.9.1.dist-info → shepherd_core-2024.11.1.dist-info}/zip-safe +0 -0
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
enable_feedback_to_hrv: true # src can control a cv-harvester for ivcurve
|
|
103
103
|
V_intermediate_enable_threshold_mV: 2000
|
|
104
104
|
V_intermediate_disable_threshold_mV: 1800 # nRF draw ~0.5 mA below that point
|
|
105
|
+
# TODO: put switch-output into special nRF Version
|
|
105
106
|
|
|
106
107
|
- datatype: VirtualSourceConfig
|
|
107
108
|
parameters:
|
shepherd_core/version.py
CHANGED
|
@@ -79,10 +79,10 @@ class DiodeTarget(TargetABC):
|
|
|
79
79
|
|
|
80
80
|
def step(self, voltage_uV: int, *, pwr_good: bool) -> float:
|
|
81
81
|
if pwr_good or not self.ctrl:
|
|
82
|
-
V_CC = voltage_uV * 1e-
|
|
82
|
+
V_CC = voltage_uV * 1e-6
|
|
83
83
|
V_D = V_CC / 2
|
|
84
84
|
I_R = I_D = 0
|
|
85
|
-
# there is no direct formular, but this
|
|
85
|
+
# there is no direct formular, but this iteration converges fast
|
|
86
86
|
for _ in range(10):
|
|
87
87
|
# low voltages tend to produce log(x<0)=err
|
|
88
88
|
with suppress(ValueError):
|
|
@@ -90,8 +90,9 @@ class DiodeTarget(TargetABC):
|
|
|
90
90
|
# both currents are positive and should be identical
|
|
91
91
|
I_R = max(0.0, (V_CC - V_D) / self.R_Ohm)
|
|
92
92
|
I_D = max(0.0, self.I_S * math.expm1(V_D / self.c1))
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
with suppress(ZeroDivisionError):
|
|
94
|
+
if abs(I_R / I_D - 1) < 1e-6:
|
|
95
|
+
break
|
|
95
96
|
# take mean of both currents and determine a new V_D
|
|
96
97
|
V_D = V_CC - self.R_Ohm * (I_R + I_D) / 2
|
|
97
98
|
return 1e9 * (I_R + I_D) / 2 # = nA
|
|
@@ -101,7 +101,7 @@ class VirtualConverterModel:
|
|
|
101
101
|
|
|
102
102
|
# pulled from update_states_and_output() due to easier static init
|
|
103
103
|
self.sample_count: int = 0xFFFFFFF0
|
|
104
|
-
self.is_outputting: bool =
|
|
104
|
+
self.is_outputting: bool = False
|
|
105
105
|
self.vsource_skip_gpio_logging: bool = False
|
|
106
106
|
|
|
107
107
|
def calc_inp_power(self, input_voltage_uV: float, input_current_nA: float) -> int:
|
|
@@ -180,6 +180,7 @@ class VirtualConverterModel:
|
|
|
180
180
|
|
|
181
181
|
# TODO: add range-checks for add, sub Ops
|
|
182
182
|
def update_cap_storage(self) -> int:
|
|
183
|
+
# TODO: this calculation is wrong for everything beside boost-cnv
|
|
183
184
|
if self.enable_storage:
|
|
184
185
|
V_mid_prot_uV = max(1.0, self.V_mid_uV)
|
|
185
186
|
P_sum_fW = self.P_inp_fW - self.P_out_fW
|
|
@@ -194,22 +195,24 @@ class VirtualConverterModel:
|
|
|
194
195
|
def update_states_and_output(self) -> int:
|
|
195
196
|
self.sample_count += 1
|
|
196
197
|
check_thresholds = self.sample_count >= self._cfg.interval_check_thresholds_n
|
|
198
|
+
V_mid_uV_now = self.V_mid_uV
|
|
199
|
+
# copy avoids not enabling pwr_good (due to large dV_enable_output_uV)
|
|
197
200
|
|
|
198
201
|
if check_thresholds:
|
|
199
202
|
self.sample_count = 0
|
|
200
203
|
if self.is_outputting:
|
|
201
|
-
if
|
|
204
|
+
if V_mid_uV_now < self.V_disable_output_threshold_uV:
|
|
202
205
|
self.is_outputting = False
|
|
203
|
-
elif
|
|
206
|
+
elif V_mid_uV_now >= self.V_enable_output_threshold_uV:
|
|
204
207
|
self.is_outputting = True
|
|
205
208
|
self.V_mid_uV -= self.dV_enable_output_uV
|
|
206
209
|
|
|
207
210
|
if check_thresholds or self._cfg.immediate_pwr_good_signal:
|
|
208
211
|
# generate power-good-signal
|
|
209
212
|
if self.power_good:
|
|
210
|
-
if
|
|
213
|
+
if V_mid_uV_now <= self._cfg.V_pwr_good_disable_threshold_uV:
|
|
211
214
|
self.power_good = False
|
|
212
|
-
elif
|
|
215
|
+
elif V_mid_uV_now >= self._cfg.V_pwr_good_enable_threshold_uV:
|
|
213
216
|
self.power_good = self.is_outputting
|
|
214
217
|
# set batok pin to state ... TODO?
|
|
215
218
|
|
|
@@ -170,8 +170,9 @@ class VirtualHarvesterModel:
|
|
|
170
170
|
|
|
171
171
|
_voltage_uV, _current_nA = self.ivcurve_2_cv(_voltage_uV, _current_nA)
|
|
172
172
|
if self.interval_step < self._cfg.duration_n:
|
|
173
|
+
self.voltage_set_uV = self.voc_now
|
|
174
|
+
elif self.interval_step == self._cfg.duration_n:
|
|
173
175
|
self.voltage_set_uV = int(self.voc_now * self._cfg.setpoint_n8 / 256)
|
|
174
|
-
_current_nA = 0
|
|
175
176
|
|
|
176
177
|
return _voltage_uV, _current_nA
|
|
177
178
|
|
shepherd_core/writer.py
CHANGED
|
@@ -94,7 +94,7 @@ class Writer(Reader):
|
|
|
94
94
|
|
|
95
95
|
comp_default: int = 1
|
|
96
96
|
mode_default: str = "harvester"
|
|
97
|
-
datatype_default:
|
|
97
|
+
datatype_default: EnergyDType = EnergyDType.ivsample
|
|
98
98
|
|
|
99
99
|
_chunk_shape: tuple = (Reader.samples_per_buffer,)
|
|
100
100
|
|
|
@@ -137,79 +137,72 @@ class Writer(Reader):
|
|
|
137
137
|
self.file_path.name,
|
|
138
138
|
)
|
|
139
139
|
|
|
140
|
+
# open file
|
|
141
|
+
if self._modify:
|
|
142
|
+
self.h5file = h5py.File(self.file_path, "r+") # = rw
|
|
143
|
+
else:
|
|
144
|
+
if not self.file_path.parent.exists():
|
|
145
|
+
self.file_path.parent.mkdir(parents=True)
|
|
146
|
+
self.h5file = h5py.File(self.file_path, "w")
|
|
147
|
+
# ⤷ write, truncate if exist
|
|
148
|
+
self._create_skeleton()
|
|
149
|
+
|
|
150
|
+
# Handle Mode
|
|
140
151
|
if isinstance(mode, str) and mode not in self.mode_dtype_dict:
|
|
141
152
|
msg = f"Can't handle mode '{mode}' (choose one of {self.mode_dtype_dict})"
|
|
142
153
|
raise ValueError(msg)
|
|
143
154
|
|
|
144
|
-
|
|
155
|
+
if mode is not None:
|
|
156
|
+
self.h5file.attrs["mode"] = mode
|
|
157
|
+
if "mode" not in self.h5file.attrs:
|
|
158
|
+
self.h5file.attrs["mode"] = self.mode_default
|
|
159
|
+
|
|
160
|
+
_dtypes = self.mode_dtype_dict[self.get_mode()]
|
|
161
|
+
|
|
162
|
+
# Handle Datatype
|
|
145
163
|
if isinstance(datatype, str):
|
|
146
164
|
datatype = EnergyDType[datatype]
|
|
147
165
|
if isinstance(datatype, EnergyDType) and datatype not in _dtypes:
|
|
148
166
|
msg = f"Can't handle value '{datatype}' of datatype (choose one of {_dtypes})"
|
|
149
167
|
raise ValueError(msg)
|
|
150
168
|
|
|
151
|
-
if
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
self.
|
|
158
|
-
if not hasattr(self, "_datatype"):
|
|
159
|
-
self._datatype = self.datatype_default
|
|
160
|
-
if window_samples:
|
|
161
|
-
self._window_samples = window_samples
|
|
162
|
-
if not hasattr(self, "_window_samples"):
|
|
163
|
-
self._window_samples = 0
|
|
164
|
-
else:
|
|
165
|
-
self._mode = mode if isinstance(mode, str) else self.mode_default
|
|
166
|
-
self._datatype = (
|
|
167
|
-
datatype if isinstance(datatype, EnergyDType) else self.datatype_default
|
|
169
|
+
if isinstance(datatype, EnergyDType):
|
|
170
|
+
self.h5file["data"].attrs["datatype"] = datatype.name
|
|
171
|
+
if "datatype" not in self.h5file["data"].attrs:
|
|
172
|
+
self.h5file["data"].attrs["datatype"] = self.datatype_default.name
|
|
173
|
+
if self.get_datatype() not in _dtypes:
|
|
174
|
+
msg = (
|
|
175
|
+
f"Can't handle value '{self.get_datatype()}' of datatype (choose one of {_dtypes})"
|
|
168
176
|
)
|
|
169
|
-
|
|
177
|
+
raise ValueError(msg)
|
|
170
178
|
|
|
179
|
+
# Handle Window_samples
|
|
180
|
+
if window_samples is not None:
|
|
181
|
+
self.h5file["data"].attrs["window_samples"] = window_samples
|
|
182
|
+
if "window_samples" not in self.h5file["data"].attrs:
|
|
183
|
+
self.h5file["data"].attrs["window_samples"] = 0
|
|
184
|
+
|
|
185
|
+
if datatype == EnergyDType.ivcurve and self.get_window_samples() < 1:
|
|
186
|
+
raise ValueError("Window Size argument needed for ivcurve-Datatype")
|
|
187
|
+
|
|
188
|
+
# Handle Cal
|
|
171
189
|
if isinstance(cal_data, (CalEmu, CalHrv)):
|
|
172
|
-
|
|
173
|
-
elif isinstance(cal_data, CalSeries):
|
|
174
|
-
self._cal = cal_data
|
|
175
|
-
else:
|
|
176
|
-
self._cal = CalSeries()
|
|
190
|
+
cal_data = CalSeries.from_cal(cal_data)
|
|
177
191
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
192
|
+
if isinstance(cal_data, CalSeries):
|
|
193
|
+
for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
|
|
194
|
+
self.h5file["data"][ds].attrs[param] = cal_data[ds][param]
|
|
181
195
|
else:
|
|
182
|
-
if
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
# check if there are unset cal-values and set them to default
|
|
197
|
+
cal_data = CalSeries()
|
|
198
|
+
for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
|
|
199
|
+
if param not in self.h5file["data"][ds].attrs:
|
|
200
|
+
self.h5file["data"][ds].attrs[param] = cal_data[ds][param]
|
|
187
201
|
|
|
188
202
|
# show key parameters for h5-performance
|
|
189
203
|
settings = list(self.h5file.id.get_access_plist().get_cache())
|
|
190
204
|
self._logger.debug("H5Py Cache_setting=%s (_mdc, _nslots, _nbytes, _w0)", settings)
|
|
191
205
|
|
|
192
|
-
# Store the mode in order to allow user to differentiate harvesting vs emulation data
|
|
193
|
-
if isinstance(self._mode, str) and self._mode in self.mode_dtype_dict:
|
|
194
|
-
self.h5file.attrs["mode"] = self._mode
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
isinstance(self._datatype, EnergyDType)
|
|
198
|
-
and self._datatype in self.mode_dtype_dict[self.get_mode()]
|
|
199
|
-
):
|
|
200
|
-
self.h5file["data"].attrs["datatype"] = self._datatype.name
|
|
201
|
-
elif not self._modify:
|
|
202
|
-
self._logger.error("datatype invalid? '%s' not written", self._datatype)
|
|
203
|
-
|
|
204
|
-
if isinstance(self._window_samples, int):
|
|
205
|
-
self.h5file["data"].attrs["window_samples"] = self._window_samples
|
|
206
|
-
if datatype == EnergyDType.ivcurve and (self._window_samples in {None, 0}):
|
|
207
|
-
raise ValueError("Window Size argument needed for ivcurve-Datatype")
|
|
208
|
-
|
|
209
|
-
# include cal-data
|
|
210
|
-
for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
|
|
211
|
-
self.h5file["data"][ds].attrs[param] = self._cal[ds][param]
|
|
212
|
-
|
|
213
206
|
super().__init__(file_path=None, verbose=verbose)
|
|
214
207
|
|
|
215
208
|
def __enter__(self) -> Self:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: shepherd_core
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.11.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>
|
|
@@ -3,8 +3,8 @@ shepherd_core/calibration_hw_def.py,sha256=_nMzgNzSnYyqcLnVCGd4tfA2e0avUXbccjmNp
|
|
|
3
3
|
shepherd_core/commons.py,sha256=vymKXWcy_1bz7ChzzEATUkJ4p3czCzjIdsSehVjJOY8,218
|
|
4
4
|
shepherd_core/logger.py,sha256=4Q4hTI-nccOZ1_A68fo4UEctfu3pJx3IeHfa9VuDDEo,1804
|
|
5
5
|
shepherd_core/reader.py,sha256=Sg7s5UfV01CejI3_nolG7qrSDUBenmt1WPo2BPJee8o,27058
|
|
6
|
-
shepherd_core/version.py,sha256=
|
|
7
|
-
shepherd_core/writer.py,sha256=
|
|
6
|
+
shepherd_core/version.py,sha256=_cAEEjp9MalkLrnbibrPNp6zEr3U5KIC-gmZvPG5QqA,76
|
|
7
|
+
shepherd_core/writer.py,sha256=GMR-7vkOgpTNPoknBWsRsC7-b7iGMtT60-KtSKunNe8,14636
|
|
8
8
|
shepherd_core/data_models/__init__.py,sha256=IVjKbT2Ilz5bev325EvAuuhd9LfQgQ1u7qKo6dhVA2k,1866
|
|
9
9
|
shepherd_core/data_models/readme.md,sha256=1bdfEypY_0NMhXLxOPRnLAsFca0HuHdq7_01yEWxvUs,2470
|
|
10
10
|
shepherd_core/data_models/virtual_source_doc.txt,sha256=KizMcfGKj7BnHIbaJHT7KeTF01SV__UXv01qV_DGHSs,6057
|
|
@@ -24,7 +24,7 @@ shepherd_core/data_models/content/firmware_datatype.py,sha256=XPU9LOoT3h5qFOlE8W
|
|
|
24
24
|
shepherd_core/data_models/content/virtual_harvester.py,sha256=MXmSJ_nRp1mSzxfTNk60o9h5Yrp2lFMbLphUVSnNeNc,9999
|
|
25
25
|
shepherd_core/data_models/content/virtual_harvester_fixture.yaml,sha256=LZe5ue1xYhXZwB3a32sva-L4uKhkQA5AtG9JzW4B2hQ,4564
|
|
26
26
|
shepherd_core/data_models/content/virtual_source.py,sha256=PPAphxEXvgMM7OVZ2dBkYAvJQkmj5Kb2BYFogVUs7B8,15354
|
|
27
|
-
shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=
|
|
27
|
+
shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=1o-31mGgn7eyCNidKoOUp9vZh3K4Al0kJgmz54Q2DAE,11191
|
|
28
28
|
shepherd_core/data_models/experiment/__init__.py,sha256=9TE9_aSnCNRhagsIWLTE8XkyjyMGB7kEGdswl-296v0,645
|
|
29
29
|
shepherd_core/data_models/experiment/experiment.py,sha256=wnn6T3czuh4rz6OSYtMltCTbRpPX55TLVAtQcKO7Uhg,4044
|
|
30
30
|
shepherd_core/data_models/experiment/observer_features.py,sha256=qxnb7anuQz9ZW5IUlPdUXYPIl5U7O9uXkJqZtMnAb0Y,5156
|
|
@@ -67,14 +67,14 @@ shepherd_core/testbed_client/client_web.py,sha256=iMh5T91152uugbFsqr2vvxLser0KIo
|
|
|
67
67
|
shepherd_core/testbed_client/fixtures.py,sha256=4Uk583R4r6I5IB78HxOn-9UNH3sbFha7OPEdcSXvMCU,9939
|
|
68
68
|
shepherd_core/testbed_client/user_model.py,sha256=5M3vWkAGBwdGDUYAanAjrZwpzMBlh3XLOVvNYWiLmms,2107
|
|
69
69
|
shepherd_core/vsource/__init__.py,sha256=GVB-FwuO2mvM15mGX9EQC1lbUmHMLmUEFGYkGmIngPM,771
|
|
70
|
-
shepherd_core/vsource/target_model.py,sha256=
|
|
71
|
-
shepherd_core/vsource/virtual_converter_model.py,sha256=
|
|
72
|
-
shepherd_core/vsource/virtual_harvester_model.py,sha256=
|
|
70
|
+
shepherd_core/vsource/target_model.py,sha256=LaB5ppi2-IIpIepDqDvOliR-BupzccJl44yRxjlF-ms,5113
|
|
71
|
+
shepherd_core/vsource/virtual_converter_model.py,sha256=3TyxphUMunoGhMda7AWCHZQU8pjRSvxB-9R8lfZFnok,11592
|
|
72
|
+
shepherd_core/vsource/virtual_harvester_model.py,sha256=GyA0uGl3r42t5c4roYtEaj22b0-b5DAHUr2e9DuNn-c,9765
|
|
73
73
|
shepherd_core/vsource/virtual_harvester_simulation.py,sha256=EiBrvmc6D2N7Z0DqFBWPdRJK6hR8Q3iQaj7EYP9pLA0,2405
|
|
74
74
|
shepherd_core/vsource/virtual_source_model.py,sha256=-JSYUfsnYlNo5RfPBhx2G33fo5AjSeFSf2O6unroyFw,2945
|
|
75
75
|
shepherd_core/vsource/virtual_source_simulation.py,sha256=k1v2zpNdJTqiO9uY8TXaq-IUKK6m5l-LEWebYva0skk,5088
|
|
76
|
-
shepherd_core-2024.
|
|
77
|
-
shepherd_core-2024.
|
|
78
|
-
shepherd_core-2024.
|
|
79
|
-
shepherd_core-2024.
|
|
80
|
-
shepherd_core-2024.
|
|
76
|
+
shepherd_core-2024.11.1.dist-info/METADATA,sha256=TPLadz0PyPjY4RxradpDtestEq_6U2ILu9tVNIIG7q0,7818
|
|
77
|
+
shepherd_core-2024.11.1.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
78
|
+
shepherd_core-2024.11.1.dist-info/top_level.txt,sha256=wy-t7HRBrKARZxa-Y8_j8d49oVHnulh-95K9ikxVhew,14
|
|
79
|
+
shepherd_core-2024.11.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
80
|
+
shepherd_core-2024.11.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|