step 1.2
This commit is contained in:
parent
ae1fed50f3
commit
6226cd8c34
|
|
@ -1,4 +1,4 @@
|
||||||
from util import pos, clamp, soc_scaler
|
from util import pos, clamp, soc_scaler, cast_to_cm
|
||||||
import parameters
|
import parameters
|
||||||
from time import time, sleep
|
from time import time, sleep
|
||||||
import zmq
|
import zmq
|
||||||
|
|
@ -7,8 +7,8 @@ import syslab
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
# Controller Parameters
|
# Controller Parameters
|
||||||
Kp = ... # P factor for our controller.
|
Kp = 0.4 # P factor for our controller.
|
||||||
Ki = ... # I factor for our controller.
|
Ki = 0.8 # I factor for our controller.
|
||||||
|
|
||||||
### Variables
|
### Variables
|
||||||
# Target that we are trying to reach at the grid connection.
|
# Target that we are trying to reach at the grid connection.
|
||||||
|
|
@ -38,10 +38,16 @@ splitting_in_socket.subscribe(parameters.TOPIC_BATTERY_SPLITTING)
|
||||||
|
|
||||||
### Unit connections
|
### Unit connections
|
||||||
# TODO step 1.2: Set up connection to control the battery and reconstruct the pcc (remember that vswitchboard is still not working)
|
# TODO step 1.2: Set up connection to control the battery and reconstruct the pcc (remember that vswitchboard is still not working)
|
||||||
|
gaia = syslab.WindTurbine("vgaia1")
|
||||||
|
dumpload = syslab.Dumpload("vload1")
|
||||||
|
mobload1 = syslab.Dumpload("vmobload1")
|
||||||
|
pv319 = syslab.Photovoltaics("vpv319")
|
||||||
|
batt = syslab.Battery('vbatt1')
|
||||||
|
|
||||||
### Import your controller class
|
### Import your controller class
|
||||||
# TODO step 1.2: Import the controller class from "simlab_controller_d5_batt.py" or copy/paste it here and pick reasonable controller parameters
|
# TODO step 1.2: Import the controller class from "simlab_controller_d5_batt.py" or copy/paste it here and pick reasonable controller parameters
|
||||||
# Note: The controller is identical to Day 5 with the exception of incorporating the splitting factor
|
# Note: The controller is identical to Day 5 with the exception of incorporating the splitting factor
|
||||||
|
from simlab_controller_d5_batt import PIDController
|
||||||
|
|
||||||
pid = PIDController(Kp=Kp, Ki=Ki, Kd=0.0,
|
pid = PIDController(Kp=Kp, Ki=Ki, Kd=0.0,
|
||||||
u_min=parameters.MIN_BATTERY_P,
|
u_min=parameters.MIN_BATTERY_P,
|
||||||
|
|
@ -70,9 +76,15 @@ try:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Poll the grid connection to get the current grid exchange.
|
# Poll the grid connection to get the current grid exchange.
|
||||||
pcc_p = 10.0 # TODO step 1.2: Reconstruct the pcc from unit measurements
|
pcc_p = cast_to_cm(-(
|
||||||
|
gaia.getActivePower().value
|
||||||
|
+ batt.getActivePower().value
|
||||||
|
+ pv319.getACActivePower().value
|
||||||
|
- dumpload.getActivePower().value
|
||||||
|
- mobload1.getActivePower().value
|
||||||
|
))
|
||||||
# Check our own state of charge
|
# Check our own state of charge
|
||||||
battery_soc = 0.68 # TODO step 1.2: Read the true battery SOC
|
battery_soc = batt.getSOC() # TODO step 1.2: Read the true battery SOC
|
||||||
|
|
||||||
# Calculate new requests using PID controller
|
# Calculate new requests using PID controller
|
||||||
battery_setpoint = pid.update(pcc_p.value, x_batt=x_battery)
|
battery_setpoint = pid.update(pcc_p.value, x_batt=x_battery)
|
||||||
|
|
@ -82,6 +94,7 @@ try:
|
||||||
|
|
||||||
# Send the new setpoint to the battery
|
# Send the new setpoint to the battery
|
||||||
# TODO step 1.2: Send the new setpoint to the battery
|
# TODO step 1.2: Send the new setpoint to the battery
|
||||||
|
batt.setActivePower(battery_setpoint)
|
||||||
logging.info(f"Sent setpoint: {battery_setpoint}")
|
logging.info(f"Sent setpoint: {battery_setpoint}")
|
||||||
|
|
||||||
# Publish our current state of charge for the supervisory controller to see
|
# Publish our current state of charge for the supervisory controller to see
|
||||||
|
|
@ -92,5 +105,6 @@ try:
|
||||||
finally:
|
finally:
|
||||||
# Clean up by closing our sockets.
|
# Clean up by closing our sockets.
|
||||||
# TODO step 1.2: Set the setpoint of the battery to zero after use
|
# TODO step 1.2: Set the setpoint of the battery to zero after use
|
||||||
|
batt.setActivePower(0.)
|
||||||
splitting_in_socket.close()
|
splitting_in_socket.close()
|
||||||
soc_out_socket.close()
|
soc_out_socket.close()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from util import pos, clamp
|
from util import pos, clamp, cast_to_cm
|
||||||
import parameters
|
import parameters
|
||||||
from time import time, sleep
|
from time import time, sleep
|
||||||
import zmq
|
import zmq
|
||||||
|
|
@ -9,8 +9,8 @@ import logging
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
# # Parameters
|
# # Parameters
|
||||||
Kp = ... # P factor for our controller.
|
Kp = 0.4 # P factor for our controller.
|
||||||
Ki = ... # I factor for our controller.
|
Ki = 0.8 # I factor for our controller.
|
||||||
|
|
||||||
# # Variables
|
# # Variables
|
||||||
# Target that we are trying to reach at the grid connection.
|
# Target that we are trying to reach at the grid connection.
|
||||||
|
|
@ -37,10 +37,16 @@ splitting_in_socket.subscribe(parameters.TOPIC_LOAD_SPLITTING)
|
||||||
|
|
||||||
### Unit connections
|
### Unit connections
|
||||||
# TODO step 1.2: Set up connection to control the battery and reconstruct the pcc (remember that vswitchboard is still not working)
|
# TODO step 1.2: Set up connection to control the battery and reconstruct the pcc (remember that vswitchboard is still not working)
|
||||||
|
gaia = syslab.WindTurbine("vgaia1")
|
||||||
|
dumpload = syslab.Dumpload("vload1")
|
||||||
|
mobload1 = syslab.Dumpload("vmobload1")
|
||||||
|
pv319 = syslab.Photovoltaics("vpv319")
|
||||||
|
batt = syslab.Battery('vbatt1')
|
||||||
|
|
||||||
### Import your controller class
|
### Import your controller class
|
||||||
# TODO step 1.2: Import the controller class from "simlab_controller_d5_load.py" or copy/paste it here and pick reasonable controller parameters
|
# TODO step 1.2: Import the controller class from "simlab_controller_d5_load.py" or copy/paste it here and pick reasonable controller parameters
|
||||||
# Note: The controller is identical to Day 5 with the exception of incorporating the splitting factor
|
# Note: The controller is identical to Day 5 with the exception of incorporating the splitting factor
|
||||||
|
from simlab_controller_d5_load import PIDController
|
||||||
|
|
||||||
pid = PIDController(Kp=Kp, Ki=Ki, Kd=0.0,
|
pid = PIDController(Kp=Kp, Ki=Ki, Kd=0.0,
|
||||||
u_min=parameters.MIN_LOAD_P,
|
u_min=parameters.MIN_LOAD_P,
|
||||||
|
|
@ -48,10 +54,6 @@ pid = PIDController(Kp=Kp, Ki=Ki, Kd=0.0,
|
||||||
Iterm=0.0)
|
Iterm=0.0)
|
||||||
|
|
||||||
|
|
||||||
# # Unit connections
|
|
||||||
# TODO step 2.2: Set up connection to control the battery/mobile load and reconstruct the pcc (remember that vswitchboard is still not working)
|
|
||||||
|
|
||||||
|
|
||||||
# Ensure the mobile load is on before we start (The sleeps wait for the load to respond.)
|
# Ensure the mobile load is on before we start (The sleeps wait for the load to respond.)
|
||||||
while not mobload1.isLoadOn().value:
|
while not mobload1.isLoadOn().value:
|
||||||
print("Starting load")
|
print("Starting load")
|
||||||
|
|
@ -78,7 +80,13 @@ try:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Poll the grid connection to get the current grid exchange.
|
# Poll the grid connection to get the current grid exchange.
|
||||||
pcc_p = 10.0 # TODO step 1.2: Reconstruct the pcc from unit measurements
|
pcc_p = cast_to_cm(-(
|
||||||
|
gaia.getActivePower().value
|
||||||
|
+ batt.getActivePower().value
|
||||||
|
+ pv319.getACActivePower().value
|
||||||
|
- dumpload.getActivePower().value
|
||||||
|
- mobload1.getActivePower().value
|
||||||
|
))
|
||||||
|
|
||||||
# Calculate new requests using PID controller
|
# Calculate new requests using PID controller
|
||||||
mobileload_setpoint = pid.update(pcc_p.value, x_load=x_load)
|
mobileload_setpoint = pid.update(pcc_p.value, x_load=x_load)
|
||||||
|
|
@ -88,6 +96,7 @@ try:
|
||||||
|
|
||||||
# Send the new setpoint to the load
|
# Send the new setpoint to the load
|
||||||
# TODO step 1.2: Send the new setpoint to the load
|
# TODO step 1.2: Send the new setpoint to the load
|
||||||
|
mobload1.setPowerSetPoint(mobileload_setpoint)
|
||||||
logging.info(f"Sent setpoint: {mobileload_setpoint}")
|
logging.info(f"Sent setpoint: {mobileload_setpoint}")
|
||||||
|
|
||||||
# Loop once more in a second
|
# Loop once more in a second
|
||||||
|
|
@ -95,4 +104,6 @@ try:
|
||||||
finally:
|
finally:
|
||||||
# Clean up by closing our socket.
|
# Clean up by closing our socket.
|
||||||
# TODO step 1.2: Set the setpoint of the mobile load to zero and shut it down after use
|
# TODO step 1.2: Set the setpoint of the mobile load to zero and shut it down after use
|
||||||
|
mobload1.setPowerSetPoint(0.)
|
||||||
|
mobload1.stopLoad()
|
||||||
splitting_in_socket.close()
|
splitting_in_socket.close()
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,11 @@ class PIDController:
|
||||||
|
|
||||||
def _calculate_error(self, y_hat_2):
|
def _calculate_error(self, y_hat_2):
|
||||||
# TODO step 1.2: calculate and return the error between reference and measurement
|
# TODO step 1.2: calculate and return the error between reference and measurement
|
||||||
return 0.0
|
return self.r - y_hat_2
|
||||||
|
|
||||||
def _calc_Pterm(self, error):
|
def _calc_Pterm(self, error):
|
||||||
# TODO step 1.2: calculate the proportional term based on the error and self.Kp
|
# TODO step 1.2: calculate the proportional term based on the error and self.Kp
|
||||||
return 0.0
|
return error * self.Kp
|
||||||
|
|
||||||
def _calc_Iterm(self, error, delta_time):
|
def _calc_Iterm(self, error, delta_time):
|
||||||
# TODO step 1.2: calculate the integral term based on error, last error and deltaT, and self.Ki
|
# TODO step 1.2: calculate the integral term based on error, last error and deltaT, and self.Ki
|
||||||
|
|
|
||||||
|
|
@ -91,21 +91,18 @@ class PIDController:
|
||||||
# optional code to filter the input / actuation signal
|
# optional code to filter the input / actuation signal
|
||||||
return u_p
|
return u_p
|
||||||
|
|
||||||
def _calculate_error(self, r, y_hat_2):
|
|
||||||
# calculate the error between reference and measurement
|
|
||||||
return r - y_hat_2
|
|
||||||
|
|
||||||
def _calculate_error(self, y_hat_2):
|
def _calculate_error(self, y_hat_2):
|
||||||
# TODO step 1.2: calculate and return the error between reference and measurement
|
# TODO step 1.2: calculate and return the error between reference and measurement
|
||||||
return 0.0
|
return self.r - y_hat_2
|
||||||
|
|
||||||
def _calc_Pterm(self, error):
|
def _calc_Pterm(self, error):
|
||||||
# TODO step 1.2: calculate the proportional term based on the error and self.Kp
|
# TODO step 1.2: calculate the proportional term based on the error and self.Kp
|
||||||
return 0.0
|
return error * self.Kp
|
||||||
|
|
||||||
def _calc_Iterm(self, error, delta_time):
|
def _calc_Iterm(self, error, delta_time):
|
||||||
# TODO step 1.2: calculate the integral term based on error, last error and deltaT, and self.Ki
|
# TODO step 1.2: calculate the integral term based on error, last error and deltaT, and self.Ki
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def _calc_Dterm(self, error, delta_time):
|
def _calc_Dterm(self, error, delta_time):
|
||||||
# calculate the proportional term based on error, last error and deltaT
|
# calculate the proportional term based on error, last error and deltaT
|
||||||
return self.Kd * 0.0
|
return self.Kd * 0.0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue