Simulation of battery for Greener Power Solutions with a modbus server. A software engineering project for Rijksuniversiteit Groningen.
The software requires Python 3.5
To use this project you need to clone the repo:
git clone https://github.com/SjoerdHilhorst/power-simulation.git
Install the required python packages in requirements.txt with pip
pip install -r requirements.txt
- Navigate to
config/env.py
- Input the device information, and simulation parameters
- Update the fields dictionary to match your own battery setup
reg_type
to the type of modbus registryaddress
to the address in the modbus serverencode
to the type of encoding used for the field (see encoding for more details)init
(optional) to fill a register with a initial value
The simulation has predefined relations for every relational field.
Field | Relation |
---|---|
active_power_converter | active_power_in - active_power_out |
reactive_power_converter | reactive_power_in - reactive_power_out |
soc | previous SoC + [(active_power_converter) / (Some configurable max battery capacity, say 330 kWh)] * 3600. |
voltage_l1_l2_in | Gaussian distribution centered around 400, deviation 3 |
voltage_l2_l3_in | Gaussian distribution centered around 400, deviation 3 |
voltage_l3_l1_in | Gaussian distribution centered around 400, deviation 3 |
current_l1_in | active_power_in / (sqrt(3) * voltage_l1_l2_in * power_factor_in) |
current_l2_in | active_power_in / (sqrt(3) * voltage_l2_l3_in * power_factor_in) |
current_l3_in | active_power_in / (sqrt(3) * voltage_l3_l1_in * power_factor_in) |
frequency_in | Gaussian distribution centered around 50, deviation 0.01 |
voltage_l1_l2_out | Gaussian distribution centered around 400, deviation 3 |
voltage_l2_l3_out | Gaussian distribution centered around 400, deviation 3 |
voltage_l3_l1_out | Gaussian distribution centered around 400, deviation 3 |
current_l1_out | active_power_out / (sqrt(3) * voltage_l1_l2_out * power_factor_out) |
current_l2_out | active_power_out / (sqrt(3) * voltage_l2_l3_out * power_factor_out) |
current_l3_out | active_power_out / (sqrt(3) * voltage_l3_l1_out * power_factor_out) |
frequency_out | Gaussian distribution centered around 50, deviation 0.01 |
Active power in, active power out, reactive power in, and reactive power out are fields from input and have to be provided by the user. For every depended field (see table), it also is possible change the relations.
The user can define or redefine the input in the following 2 ways:
Suppose we want current_l2_out
from historic_battery_data.csv
instead of the predefined relation.
- in
config/env.py
updatefrom_csv
with the linecurrent_l2_out: 'historic_battery_data'
dictionary. Note that the key, in this casecurrent_l2_out
refers to a column in the csv table and not the simulation field. - in
simulations/simulation.py
add a method which overrides the method in thesimulation_super
class:
def get_current_l2_out(self):
current_l2_out = self.csv_reader.get_from_csv('current_l2_out')
return current_l2_out
Note that the method name get_current_l2_out
has to be the same as in the simulation_super
class
Suppose now we want active_power_converter
to be (active_power_in - active_power_out) * 0.1)
instead of the predefined relation.
- in
simulations/simulation.py
add a method which overrides the method in thesimulation_super
class:
def get_activer_power_converter(self):
apc = self.battery.get_value(self.fields['active_power_in']) - self.battery.get_value(self.fields['active_power_out'])
return apc * 0.1
Note that the method name get_active_power_converter
has to be the same as in the simulation_super
class
Suppose now we want to add a new field custom
to our simulation
- in
config/env.py
updatefields
with your new field. If we want the field to be constant we can make use of theinit
to provide a constant value. - To provide a relation we can add a new method to
simulations/simulations
like for example the sine of the time elapsed:
def get_custom(self):
return sin(self.time_elapsed)
- Add the method to the
update_custom
function method, so thatcustom
field will get updated every iteration
def update_custom(self):
self.battery.set_value(self.fields['custom'], self.get_custom())
To enable/disable the graph and/or add new fields to the plot, update graph
in config/env.py
To enable/disable the Database, update database
in config/env.py
. Note that enabling the database will hinder performance of the program.
Now you're all setup, run
python3 main.py
Huge thanks to Jasper Clarijs from Greener Power Solutions for setting us up with the project and answering questions and Alex Tutea our TA For guiding us through the software engineering course.