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_typeto the type of modbus registryaddressto the address in the modbus serverencodeto 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.pyupdatefrom_csvwith the linecurrent_l2_out: 'historic_battery_data'dictionary. Note that the key, in this casecurrent_l2_outrefers to a column in the csv table and not the simulation field. - in
simulations/simulation.pyadd a method which overrides the method in thesimulation_superclass:
def get_current_l2_out(self):
current_l2_out = self.csv_reader.get_from_csv('current_l2_out')
return current_l2_outNote 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.pyadd a method which overrides the method in thesimulation_superclass:
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.1Note 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.pyupdatefieldswith your new field. If we want the field to be constant we can make use of theinitto provide a constant value. - To provide a relation we can add a new method to
simulations/simulationslike for example the sine of the time elapsed:
def get_custom(self):
return sin(self.time_elapsed)- Add the method to the
update_customfunction method, so thatcustomfield 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.