# PV + Battery Simulink Model > **Markdown report consolidating two non-markdown sources plus one duplicate markdown file.** > > | | | > |---|---| > | **Sources** | `Shift Matlab Drive/.../Simulations/PV+Battery Simulink/PV+Battery.docx`
`Shift Matlab Drive/.../Simulations/PV+Battery Simulink/PVBatteryRead.mlx`
`Shift Matlab Drive/.../Simulations/PV+Battery Simulink/Constants.mlx` | > | **Also duplicated as** | `PV+Battery.md` at the repository root — **retired to [`superseded/`](../../superseded/)** | > | **Owner** | Simulations cluster | > | **Status** | Current — **model has a known unresolved bug** (see [Known issue](#known-issue--model-is-not-time-dependent)) | > | **Report generated** | 2026-07-25 | ## What this is The Simulations cluster's first end-to-end vertical slice: read real profile data out of a spreadsheet, hand it to Simulink, and run coupled PV and battery models against it. It is a methodology trial as much as a model — the closing question in the source is *"Discuss if this is a good standard for all parts."* ## Components ### 1. Profiles SHIFT (spreadsheet) - A new tab has been added to the existing Excel data sheet. - Quick-search data has been filled in for fast experimentation with the Simulink models. See [Generation Profiles Workbook](generation-profiles-workbook.md) for the sheet contents. ### 2. `PVBatteryRead.mlx` - Code developed with large assistance from ChatGPT. - Originally intended to read *everything* off the spreadsheet; it currently reads **dynamic data** and prepares it for Simulink use. - The constants reading would not function, for reasons not established — so constants are set in `Constants.mlx` instead. **What the script actually does**, step by step: | Step | Behaviour | |---|---| | File settings | Reads `Profiles SHIFT(Generators Factors + Battery).xlsx`, sheet **`Fake Simulink Data`**, with `HeaderLines = 1` and `VariableNamingRule = 'preserve'` | | 1 — Type conversion | Converts cell-text numbers to double, **replacing `,` with `.`** for decimal commas; converts `duration` columns to hours | | 2 — Trim | Detects the last valid signal row (any non-NaN numeric, and a date after 2000-01-01) and truncates the table there | | 3 — Extract | Parses variable names out of headers of the form `Name - var (unit)` via the regex `-\s*(.*?)\s*\(`, then `matlab.lang.makeValidName`. Time (`t`) is converted to **seconds** — a max ≤ 1 is treated as fraction-of-day, otherwise as hours. A column whose values are all identical becomes a **constant**; otherwise a time series | | 4 — Simulink signals | For every numeric variable of the same length as `t`, creates `_simulink = [t, values]` in the base workspace — the two-column `[time, data]` format Simulink's *From Workspace* block expects | > The sheet name is literally **`Fake Simulink Data`** — placeholder data for wiring up the > pipeline, not a real profile. ### 3. `Constants.mlx` Remember to run this **and** `PVBatteryRead.mlx` before attempting to run the Simulink models. ```matlab A_PV = 3060; % PV Area (m2) mu_PV = 0.2; % Panel Efficiency (%) V_PV = 24; % PV Voltage (V) P_ele = 1500000; % Electrolyzer Power Consumption (W) E_t0 = 0; % Initial Battery Energy (Wh) E_rated = 170000; % Battery Rated Energy (W) Q_rated = 100000; % Battery Rated Charge Capacity (W) Charge_max = 1; % Maximum Charge (%) Disharge_max = 2; % Maximum Discharge (%) SoC_max = 1; % SoC limit (%) SoC_t0 = 0; % Initial SoC (%) P_B_int = 0; % Initial Battery power (W) I_B_int = 0; % Initial Battery current (A) ``` **Parameter cross-check against the project spec:** | Constant | Value here | Project spec | Comment | |---|---|---|---| | `A_PV` | 3060 m² | **2,300 m²** ([Simulator I/O §1.4](../02-specifications/simulator-io-interface.md#14-pv)) | 33% larger than spec | | `mu_PV` | 0.2 | — | Reasonable for commercial silicon | | `P_ele` | 1.5 MW | — | Large relative to a 2,300 m² × 20% array (~460 kW peak) | | `E_rated` | 170000, commented **W** | Rated energy capacity in **Wh** | Unit comment is wrong; should be Wh | | `Q_rated` | 100000, commented **W** | Rated charge capacity in **Ah** | Unit comment is wrong; should be Ah | | `Disharge_max` | 2 | — | Commented "%" but a discharge *limit* of 2 with `SoC_max = 1` is dimensionally inconsistent. Also a typo for `Discharge_max` | | `SoC_t0` | 0 | — | Starting from an empty battery | None of these break the model — they are annotation errors and a not-yet-calibrated parameter set — but they should be reconciled with the simulator contract before results are quoted. ### 4. `SolarPanel.slx` + `Battery.slx` (and `SolarPanel_n_Battery.slx`) - Two individual models using the equations from *paper 1* to derive the desired outputs over time. - **Both do this in two different ways**, using different variables, to compare consistency. - Most SoC-related quantities are handled in **%**. The dynamic data found is likely in another unit — that is what `Q_rated` and `E_rated` are for, to be used according to paper 1. ## Known issue — model is not time-dependent > *"An issue was encountered where this code does not appear to be time dependant despite > drawing the appropriate `_simulink` matrices from the workspace. This is most likely some > kind of conversion issue between time in seconds in code and time measured in the simulinks > themselves."* This is unresolved and is the first item on the to-do list. The author's diagnosis is consistent with what `PVBatteryRead.mlx` does: it converts `t` to **seconds** in step 3, so any Simulink block configured in hours — or a solver whose stop time is set in hours — will see a signal that appears constant across the run because the simulated interval covers only the first few samples. **Where to look first:** the `[t, values]` matrices are built with `t` in seconds; check the Simulink model's configured stop time and the *From Workspace* block's sample-time interpretation match that unit. ## To be continued Carried forward verbatim from the source: - Fix the aforementioned time-dependency issue. - Test and see if these values make sense. Compare the two versions for both. - Discuss if this is a good standard for all parts. ## File locations All of these files were submitted on MATLAB Drive and ClickUp under *Simulations → PV+Battery Simulink*. In this repository: | File | Size | Note | |---|---|---| | `PV+Battery.docx` | 1.6 kB | Source of this report | | `PVBatteryRead.mlx` | — | Data import script | | `Constants.mlx` | — | Parameter definitions | | `SolarPanel.slx` | — | PV model | | `Battery.slx` | — | Battery model | | `SolarPanel_n_Battery.slx` | — | Combined model | | `SolarPanel.slxc` | — | Simulink cache — build artefact | | `Profiles SHIFT(Generators Factors + Battery).xlsx` | — | Byte-identical to the copy in `Current Framework/` | | `slprj/` | — | Simulink build cache — machine-generated | ## Duplicate source note The repository root contained `PV+Battery.md`, a markdown transcription of `PV+Battery.docx` with the same content. Since this report supersedes both, the root markdown copy is retired to [`superseded/`](../../superseded/) and the `.docx` remains in place as the original. ## Related - [Generation Profiles Workbook](generation-profiles-workbook.md) — the spreadsheet this reads - [MATLAB Live Scripts](matlab-live-scripts.md) — inventory of all `.mlx` files - [Simulink Model Inventory](simulink-model-inventory.md) — all `.slx` files and their lineage - [Simulator I/O Interface §1.4–1.5](../02-specifications/simulator-io-interface.md#14-pv) — the parameter spec these constants should match