├── .gitignore ├── ElectricVehicles.py ├── LICENSE.md ├── README.md ├── bev_parameters.csv ├── evse_class.py └── test_run.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac 2 | .DS_Store 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | *.py,cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | cover/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | .pybuilder/ 79 | target/ 80 | 81 | # Jupyter Notebook 82 | .ipynb_checkpoints 83 | 84 | # IPython 85 | profile_default/ 86 | ipython_config.py 87 | 88 | # pyenv 89 | # For a library or package, you might want to ignore these files since the code is 90 | # intended to run in multiple environments; otherwise, check them in: 91 | # .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | env/ 114 | venv/ 115 | ENV/ 116 | env.bak/ 117 | venv.bak/ 118 | 119 | # Spyder project settings 120 | .spyderproject 121 | .spyproject 122 | 123 | # Rope project settings 124 | .ropeproject 125 | 126 | # mkdocs documentation 127 | /site 128 | 129 | # mypy 130 | .mypy_cache/ 131 | .dmypy.json 132 | dmypy.json 133 | 134 | # Pyre type checker 135 | .pyre/ 136 | 137 | # pytype static type analyzer 138 | .pytype/ 139 | 140 | # Cython debug symbols 141 | cython_debug/ 142 | -------------------------------------------------------------------------------- /ElectricVehicles.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Feb 23 09:32:13 2022 4 | 5 | @author: pmishra 6 | """ 7 | 8 | import os 9 | import pandas as pd 10 | import numpy as np 11 | from scipy import interpolate 12 | import math 13 | 14 | class ElectricVehicles: 15 | def __init__(self, **kwargs): 16 | # load EV parameters 17 | kwargs = {k.lower(): v for k, v in kwargs.items()} 18 | if 'vehicle_type' in kwargs: 19 | self.evtype = kwargs['vehicle_type'] 20 | else: 21 | self.evtype = 'bev' 22 | 23 | self.arrivaltime = kwargs['arrival_time'] 24 | self.initialsoc = kwargs['initial_soc'] 25 | self.modelparameters = self.load_ev_file(**kwargs) 26 | if 'batterycapacity_kwh' in kwargs: 27 | self.modelparameters['ev_packcapacity'] = kwargs['batterycapacity_kwh'] 28 | self.soc = self.initialsoc 29 | self.timestamp_soc = self.arrivaltime 30 | self.packvoltage = self.getocv(self.soc, **kwargs)[0] 31 | self.packpower = 0.0 32 | self.packcurrent = 0.0 33 | self.pluggedin = False 34 | self.readytocharge = False 35 | self.chargecomplete = False 36 | if 'target_soc' in kwargs: 37 | self.targetsoc = kwargs['target_soc'] 38 | else: 39 | self.targetsoc = 1.0 # if target SOC is not provided, set it as 1.0 40 | if 'departure_time' in kwargs: 41 | self.departuretime = kwargs['departure_time'] 42 | else: 43 | self.departuretime = self.arrivaltime + 24.0*3600 # if departure time is not provided, set it as 24 hours later than arrival time 44 | self.evse_id = np.nan 45 | 46 | 47 | 48 | 49 | def isvehiclepluggedin(self,simulationtime): 50 | # method to check if a vehicle is plugged in or not 51 | if (simulationtime >= self.arrivaltime) and (simulationtime < self.arrivaltime + self.modelparameters['ev_setuptime']) and (simulationtime <= self.departuretime): 52 | self.pluggedin = True 53 | self.readytocharge = False 54 | 55 | elif (simulationtime >= self.arrivaltime + self.modelparameters['ev_setuptime']) and (simulationtime <= self.departuretime): 56 | self.pluggedin = True 57 | self.readytocharge = True 58 | else: 59 | self.pluggedin = False 60 | self.readytocharge = False 61 | 62 | 63 | def assign_evse(self,evse_id): 64 | self.evse_id = evse_id 65 | 66 | def ischargecomplete(self, simulationtime, **kwargs): 67 | if simulationtime >= self.departuretime or self.soc >= self.targetsoc: 68 | self.chargecomplete = True 69 | else: 70 | self.chargecomplete = False 71 | 72 | 73 | def load_ev_file(self, **kwargs): 74 | # loads model paramaters either from a CSV file or defines default values 75 | if 'input_path' in kwargs: 76 | ev_parameters_file = os.path.join(kwargs['input_path'], 'evtype', '{}_parameters.csv'.format(self.evtype)) 77 | 78 | params = pd.read_csv(ev_parameters_file, index_col = 'Parameter Name') 79 | params = params['Parameter Value'].astype(float).to_dict() 80 | else: 81 | print('Warning: Cannot find EV parameter file. Using default values for fixed parameters') 82 | params = {'ev_crate': 1.0, #1/hr 83 | 'ev_cellcapacity': 26.0, #Ah 84 | 'ev_packcapacity': 100.0, #kWh 85 | 'ev_nominalvoltage': 350.0, #V 86 | 'ev_setuptime': 30.0, #s 87 | 'ev_batterychemistry': 'nmc', 88 | 'ev_chargingprotocol':'cc-cv', 89 | } 90 | 91 | return params 92 | 93 | def getocv(self,soc, **kwargs): 94 | # computes pack level open circuit voltage 95 | # get cell level ocv-soc curve based on battery chemistry 96 | if self.modelparameters['ev_batterychemistry'] == 'nmc': 97 | ocvpts = np.array([3.067,3.477,3.560,3.616,3.650,3.690,3.754,3.854,3.954,4.067,4.192]) 98 | socpts = np.linspace(0.0, 1.0, num = ocvpts.size) 99 | rohmpts = np.array([0.00172,0.00154,0.00147,0.00141,0.001395,0.00137,0.00140,0.00150,0.00148,0.00145,0.00144]) 100 | 101 | elif self.modelparameters['ev_batterychemistry'] =='lfp': # Data is for a 10Ah cell 102 | ocvpts = np.array([2.1434, 3.2048, 3.2593, 3.2927, 3.3068, 3.3119, 3.3223, 3.3386, 3.3447, 3.3486,3.5291]) 103 | socpts = np.linspace(0.0, 1.0, num = ocvpts.size) 104 | rohmpts = np.array([3.1092,2.6633,1.8337,1.6094,1.5160,1.4196,1.3201,1.2206,1.2115,1.1838,1.2777])*1.0e-3 105 | # Data Source: % Source: L.Lu, X. Han, J. Li, J. Hua, M. Ouyang, 106 | # "A review on the key issues for lithium-ion battery management in electric vehicles",Journal of Power Sources, 2013, 226, 272-288 107 | 108 | elif self.modelparameters['ev_batterychemistry'] =='lto': 109 | ocvpts = np.array([1.8219,2.1321,2.1633,2.1844,2.2058,2.2343,2.2726,2.3253,2.3995,2.4874,2.8158]) 110 | socpts = np.linspace(0.0, 1.0, num = ocvpts.size) 111 | rohmpts = np.array([5.6123,3.0693,2.3927,2.1543,2.0235,2.0338,2.1051,2.0431,2.1884,2.3383,2.5148])*1.0e-3 112 | # Data source: A.I. Stroe, J. Meng, D.I Stroe et al., "Influence of Battery Parametric Uncertainties on the State-of-Charge 113 | # Estimation of Lithium Titanate Oxide-Based Batteries", Energies 114 | # 2018, 11, 795. 115 | else: 116 | ocvpts = np.array([3.067,3.477,3.560,3.616,3.650,3.690,3.754,3.854,3.954,4.067,4.192]) 117 | socpts = np.linspace(0.0, 1.0, num = ocvpts.size) 118 | rohmpts = np.array([1.7359,1.6166,1.5263,1.4793,1.6639,1.6109,1.6389,1.5716,1.6222,1.0595,0.4736])*1.0e-3 119 | 120 | # Calculate battery configuration xSyP 121 | Ns = round(self.modelparameters['ev_nominalvoltage']/interpolate.pchip_interpolate(socpts, ocvpts, 0.5)) 122 | Np = math.ceil((self.modelparameters['ev_packcapacity']*1.0e3)/(self.modelparameters['ev_nominalvoltage']*self.modelparameters['ev_cellcapacity'])) 123 | packocv = Ns*interpolate.pchip_interpolate(socpts, ocvpts, soc) 124 | packresistance = Ns*interpolate.pchip_interpolate(socpts, rohmpts, soc)/Np 125 | return packocv, packresistance, Ns, Np, ocvpts, socpts, rohmpts 126 | 127 | def getvehiclestate(self): 128 | # obtains the vehicle states 129 | vehiclestate = {'soc': self.soc, 130 | 'packpower': self.packpower, 131 | 'packcurrent': self.packcurrent, 132 | 'packvoltage': self.packvoltage, 133 | 'pluginsignal': self.pluggedin, 134 | 'chargecompletesignal': self.chargecomplete, 135 | 'timestamp_soc': self.timestamp_soc} 136 | return vehiclestate 137 | 138 | def chargevehicle(self, simulationtime, **kwargs): 139 | self.isvehiclepluggedin(simulationtime) 140 | self.ischargecomplete(simulationtime) 141 | dt = kwargs['dt'] # in seconds 142 | 143 | if self.readytocharge and ~np.isnan(self.evse_id) and (not self.chargecomplete): 144 | # vehicle is ready to charge and assigned to an EVSE 145 | packocv, packresistance, Ns, Np, ocvpts, socpts, rohmpts = self.getocv(self.soc) 146 | CVvolt = Ns*interpolate.pchip_interpolate(socpts,ocvpts,0.95) 147 | CCcurr = Np*self.modelparameters['ev_crate']*self.modelparameters['ev_cellcapacity'] 148 | # assuming that EVSE will communicate a power with kW in the keyword 149 | power = [keyval for key, keyval in kwargs.items() if 'kw' in key.lower()] 150 | if not power: 151 | current = CCcurr 152 | else: 153 | tempcurrent = (-packocv + math.sqrt(packocv**2 + 4.0*packresistance*power[0]*1.0e3))/(2.0*packresistance) 154 | if power[0] >= 0.0: # i.e. charging 155 | current = min(CCcurr, tempcurrent) 156 | else: 157 | current = max(CCcurr, tempcurrent) 158 | socnow = self.soc 159 | Vtemp = packocv + current*packresistance 160 | if Vtemp <= CVvolt: 161 | self.packcurrent = current 162 | self.packvoltage = packocv + current*packresistance 163 | self.packpower = self.packcurrent*self.packvoltage 164 | self.soc = socnow + (dt/3600.0)*current/(Np*self.modelparameters['ev_cellcapacity']) 165 | self.timestamp_soc = simulationtime + dt 166 | else: 167 | CVcurr = (CVvolt - packocv)/packresistance 168 | self.soc = socnow + (dt/3600.0)*CVcurr/(Np*self.modelparameters['ev_cellcapacity']) 169 | self.timestamp_soc = simulationtime + dt 170 | self.packcurrent = CVcurr 171 | self.packvoltage = CVvolt 172 | self.packpower = CVcurr*CVvolt 173 | 174 | else: 175 | # don't charge yet 176 | self.soc = self.soc 177 | self.packcurrent = 0.0 178 | self.packpower = 0.0 179 | self.packvoltage = self.packvoltage 180 | self.timestamp_soc = simulationtime + dt 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Alliance for Sustainable Energy, LLC 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyChargeModel 2 | The PyChargeModel repository includes two Python classes: (i) ElectricVehicles.py that models the charging and discharging behavior of an electric vehicle (EV), (ii) EVSE_class.py that emulates an electric vehicle supply equipment (EVSE) or the charging port. These classes can be instantiated with required parameter values to generate multiple "electric vehicle" agents and "EVSE" agents that can interact with each other through built-in methods. The "test_run.py" script in this repository provide a simple example demonstrating the use of these two classes to emulate the charging of an EV at a charging port. This readme file explains the steps in "test_run.py" while providing details about these classes during the process. 3 | 4 | ## Step 1: Loading and initializing the classes 5 | Load: 6 | 7 | `from evse_class import EVSE_class` 8 | 9 | `from ElectricVehicles import ElectricVehicles` 10 | 11 | Initialize: 12 | 13 | `ev1 = ElectricVehicles(departure_time=1*60*60, vehicle_type='bev', arrival_time=1*60, initial_soc=0.1, target_soc=0.15, batterycapacity_kWh = 120.0)` 14 | 15 | `evse_instance = EVSE_class(efficiency=0.99, Prated_kW=6.6, evse_id=1)` 16 | 17 | An EV agent or object can be instantiated by providing the following key-value pairs: 18 | 1. `arrival_time` : relative time of arrival of the vehicle in seconds [reqd.] 19 | 2. `initial_soc` : state of charge (SOC) of the EV at the time of arrival as a fraction between 0.0 and 1.0 [reqd.] 20 | 3. `batterycapacity_kWh` : capacity of the EV battery pack in killowatt-hours, default = 100 kWh [opt. but highly suggested] 21 | 4. `vehicle_type` : vehicle type to define the class of the vehicle, default = 'bev' [opt.] 22 | 5. `departure_time` : relative time of departure of the vehicle in seconds, default = arrival_time + 24 hours [opt.] 23 | 6. `target_soc` : target SOC for the vehicle to be charged up to, default = 1.0 [opt.] 24 | 25 | There are other default parameters that can be further modified by providing a CSV file name and its input path where such parameter values can be listed. An example of such a file is included in this repo. 26 | 27 | Similarly, an EVSE agent or object can be instantiated by providing the following key-value pairs: 28 | 1. `evse_id` : A numerical EVSE ID [reqd.] 29 | 2. `efficiency` : Efficiency of the EVSE as a fraction between 0 and 1 [reqd.] 30 | 3. `Prated_kW` : Rated power capacity of the EVSE in kW [reqd.] 31 | The EVSE model is also compatible for smart charge management application. The power dispensed by the EVSE can be controlled by setting: 32 | `evse_instance.server_setpoint = 5.0` 33 | 34 | ## Step 2: Assign the EV to an EVSE 35 | An EVSE object is assigned to an EV object using the `assign_evse` method and passing on the EVSE ID: 36 | 37 | `ev1.assign_evse(evse_instance.evse_id)` 38 | 39 | ## Step 3: Charge the EV 40 | EV charging behavior is emulated by calling the `chargevehicle` method for each of the EV objects. The `chargevehicle` method is called at each time step during the simulation time. Thus this method updates the state of the EV over a single time step. In order to get a temporal profile of the vehicle charging power, SOC etc., this method needs to be called throughout the simulation time. In the `test_run.py` script, the EV is charged over the simulation period by running a for-loop: 41 | 42 | `t0 = 0 #start of simulation time [s]` 43 | 44 | `tf = 1.1*60*60 # end of simulation time [s]` 45 | 46 | `dt = 1 # time step [s]` 47 | 48 | `Pmax = 0.0 # maximum power to charge with [kW]` 49 | 50 | `### Start simulation` 51 | 52 | `for t in np.arange(t0, tf, dt):` 53 | `ev1.chargevehicle(t, dt=dt, evsePower_kW=Pmax)` 54 | 55 | The `chargevehicle` method takes the following inputs: 56 | 1. t : simulation time in seconds as a numerical value 57 | 2. dt = x.x : timestep of simulation in seconds 58 | 3. evsePower_kW = x.xx : power to charge the vehicle with in kW [opt.] 59 | 60 | Power setpoint by the EVSE (here `evsePower_kW`) is optional - without this input, the charging power requested by the EV is based on its power rating (i.e. rated C-rate). The model is also capable of handling charging and discharging behavior and this can be achieved by providing a positive or negative power setpoint while calling the `chargevehicle` method. 61 | 62 | ## Step 4: Logging data 63 | 64 | Throughout the simulation, various states of the EV object gets updated and these states can be accessed using the `getvehiclestate` method. Calling this method using `ev1.getvehiclestate()` returns a dictionary with the following keys: 65 | 66 | 1. `soc` : current state of charge of the EV [0-1] 67 | 2. `packpower` : power consumption at the battery pack terminals [W] 68 | 3. `packvoltage` : terminal voltage of the battery pack [V] 69 | 4. `packcurrent` : current drawn at the battery pack terminals [A] 70 | 5. `pluginsignal` : boolean indicating EV is plugged-in 71 | 6. `chargecompletesignal` : boolean indicating whether a charging session is completed or not 72 | 7. `timestamp_soc` : relative timestamps associated with the SOC of the battery pack [s] 73 | -------------------------------------------------------------------------------- /bev_parameters.csv: -------------------------------------------------------------------------------- 1 | Parameter Name,Parameter Value,Comment 2 | ev_crate,1.0,C-rate that the battery pack can accept [1/hr] 3 | ev_cellcapacity,26.0,capacity of the individual cells that are in the battery pack [A-hr] 4 | ev_packcapacity,100.0,capacity of the battery pack [kWh] 5 | ev_nominalvoltage,350.0,nominal voltage of the battery pack at 50% state of charge [V] 6 | ev_setuptime,30.0,time to plug in the vehicle and perform handshake with the EVSE once it arrives at the port [s] 7 | ev_batterychemistry,nmc,lithium-ion chemistry of the battery pack 8 | ev_chargingprotocol,cc-cv,"constant current constant voltage protocol to be applied for charging, other protocols can be modeled too" 9 | ,, 10 | ,, 11 | ,, 12 | ,, 13 | ,, 14 | ,, 15 | ,, 16 | ,, 17 | ,, 18 | ,, 19 | ,, 20 | -------------------------------------------------------------------------------- /evse_class.py: -------------------------------------------------------------------------------- 1 | class EVSE_class(): 2 | def __init__(self, efficiency, Prated_kW, evse_id): 3 | self.efficiency = efficiency 4 | self.Prated_kW = Prated_kW 5 | self.evse_id = evse_id 6 | 7 | self.ev_voltage = 0.0 8 | self.ev_power = 0.0 9 | self.ev_soc = 0.0 10 | self.ev_plugged = False 11 | self.state = 'A' 12 | 13 | self.server_setpoint = 0.0 14 | 15 | 16 | def receive_from_ev(self, Vbatt, Pbatt_kW, soc, plugged, ready): 17 | ### receive Vbatt, Pbatt, SOC, plugged via TCP or something if there needs a connection 18 | self.ev_voltage = Vbatt 19 | self.ev_power = Pbatt_kW 20 | self.ev_soc = soc 21 | self.ev_plugged = plugged 22 | self.ev_ready = ready 23 | 24 | if self.ev_plugged and self.ev_power < 0.1: 25 | self.state = 'B' 26 | if self.ev_plugged and self.ev_power >= 0.1: 27 | self.state = 'C' 28 | if not self.ev_plugged: 29 | self.state = 'A' 30 | 31 | 32 | def send_to_ev(self): 33 | if self.ev_ready: 34 | Pmax = min(self.server_setpoint, self.Prated_kW)*self.efficiency 35 | else: 36 | Pmax = 0.0 37 | 38 | ### send Pmax via TCP or something if there needs a connection 39 | return Pmax 40 | 41 | 42 | def receive_from_server(self, setpoint_kW): 43 | self.server_setpoint = setpoint_kW 44 | 45 | 46 | def send_to_server(self): 47 | Vbatt = self.ev_voltage 48 | Pbatt_kW = self.ev_power 49 | soc = self.ev_soc 50 | 51 | return [Vbatt, Pbatt_kW, soc] 52 | 53 | -------------------------------------------------------------------------------- /test_run.py: -------------------------------------------------------------------------------- 1 | from evse_class import EVSE_class 2 | from ElectricVehicles import ElectricVehicles 3 | 4 | import numpy as np 5 | 6 | #################################################################### 7 | ### Initialization 8 | #################################################################### 9 | ev1 = ElectricVehicles(departure_time=1*60*60, vehicle_type='bev', arrival_time=1*60, initial_soc=0.1, target_soc=0.15, batterycapacity_kWh = 120.0) 10 | evse_instance = EVSE_class(efficiency=0.99, Prated_kW=6.6, evse_id=1) 11 | evse_instance.server_setpoint = 10 12 | 13 | ev1.assign_evse(evse_instance.evse_id) 14 | 15 | t0 = 0 16 | tf = 1.1*60*60 17 | dt = 1 18 | 19 | Pmax = 0.0 20 | 21 | #################################################################### 22 | ### Start simulation 23 | #################################################################### 24 | for t in np.arange(t0, tf, dt): 25 | ev1.chargevehicle(t, dt=dt, evsePower_kW=Pmax) 26 | 27 | ### EV -> EVSE 28 | evse_instance.receive_from_ev(ev1.packvoltage, ev1.packpower, 29 | ev1.soc, ev1.pluggedin, ev1.readytocharge) 30 | 31 | 32 | ### EVSE -> EV 33 | Pmax = evse_instance.send_to_ev() 34 | 35 | print('t:{0}, soc:{1}, plugged:{2}, Pmax [kW]:{3}, Pevse from grid [W]:{4}, Pevse to EV [W]:{5}'.format( 36 | t, ev1.soc, ev1.pluggedin, Pmax, evse_instance.ev_power/evse_instance.efficiency, evse_instance.ev_power)) 37 | --------------------------------------------------------------------------------