Aqueduct PID Controller API Documentation

The Python API allows you to set up PID controllers, change their setpoints, and control their status. You can use the Python API in the context of an Aqueduct Recipe or as a script to create one or more controllers.

Import Required Modules

Start by importing all necessary modules from the Aqueduct library.

Note: The PID API is available on version 0.0.5 and later of aqueduct-py.

from aqueduct.core.aq import Aqueduct, InitParams
from aqueduct.core.pid import ScheduleParameters, ScheduleConstraints, Pid, Schedule

# your specific device types may differ based on application
from aqueduct.devices.pump.peristaltic import PeristalticPump
from aqueduct.devices.ph import PhProbe

Retrieve Device Instances

Fetch instances of the PeristalticPump and pH Probe devices from the system. We'll use these devices' accessors to create the Process Value and Control Output.

pump: PeristalticPump = aq.devices.get(PUMP_NAME)
ph_probe: PhProbe = aq.devices.get(PH_PROBE_NAME)

Process and Control Value Initialization

After initializing your devices, link them to either a Process Value or a Control Output.

# Generate process and control data for PID controllers.
# Index specifies the node to associate with the accessor. 
# (e.g., index=1 would be pH probe node 1)
process_value = ph_probe.to_pid_process_value(index=0)
control_output = pump.to_pid_control_output(index=0)

Create Schedule with Constraints and Parameters

Set up one or more Schedules for the PID controller, including constraints and parameters like kp, ki, kd, etc.

# create a `ScheduleParameters` instance with default values
params = ScheduleParameters()
# change the Bias term
#params.bias = None
# change the Kp term
params.kp = 1
# change the Ki term
params.ki = .025
# change the Kd term
params.kd = .55
# Error values within this range around the setpoint will not activate the controller
params.dead_zone = 0.001 
# Integral term will be accumulated when the error is within this limit
params.integral_valid = 0.3 
# Change the linearity factor
#params.linearity = 1.0
# Change the beta factor
#params.beta = 1.0
# Change the setpoint range weighting
#params.setpoint_range = 1.0
# Change the limit on the proportional term
#params.p_limit = None
# Change the limit on the integral term
#params.i_limit = None
# Change the limit on the derivative term
#params.d_limit = None
# Change the limit on the maximum change in output
#params.delta_limit = None

constraints = ScheduleConstraints()  # You can add schedule constraints here
# change the process constraints
#constraints.process = (0, 0.35)
# change the error constraints
#constraints.error = (0, 0.35)
# change the control constraints
#constraints.control = (0, 0.35)

# create the schedule
sched = Schedule(params, constraints)

Create PID Instance and Add Schedule

Initialize a PID instance and add the created schedule to it.

p = Pid(8)  # Initialize PID with a setpoint of 8
# Add the schedule to the PID controller
# Since this is the first schedule added, it will
# have the highest priority
p.add_schedule(sched)  

Set Output Limits

Define the output limits for the PID controller.

p.output_limits = (0.0, 1)  # Output will be constrained within these limits

Create PID Controller Instance

Once you've created your controller, register it with the application using the Aqueduct class's pid_controller method. Here, the name Controller has been assigned to this controller.

pid = aq.pid_controller("Controller", process_value, control_output, p)

Change the Setpoint

Once you've created the controller, you can update the setpoint from the Python API.

pid.change_setpoint(7.5)  # Update setpoint to 7.5

Enable or Disable Controller

Control the operational status of the PID controller.

pid.enable()  # Turns the PID controller on
pid.disable()  # Turns the PID controller off

Modify Schedule Parameters

If you want to alter the PID parameters for the first schedule, you can access it via the index from the controllers pid.schedule accessor.

# Update kp to 2 and kd to 0.8 for the first schedule
pid.pid.schedule[0].change_parameters(kp=2, kd=.8) 

Complete Code

Here's the complete code from this demo:

from aqueduct.core.aq import Aqueduct, InitParams
from aqueduct.core.pid import ScheduleParameters, ScheduleConstraints, Pid, Schedule

# your specific device types may differ based on application
from aqueduct.devices.pump.peristaltic import PeristalticPump
from aqueduct.devices.ph import PhProbe

# Parse the initialization parameters from the command line
params = InitParams.parse()

# Initialize the Aqueduct instance with the provided parameters
aq = Aqueduct(params.user_id, params.ip_address, params.port)

# Perform system initialization if specified
aq.initialize(params.init)

pump: PeristalticPump = aq.devices.get(PUMP_NAME)
ph_probe: PhProbe = aq.devices.get(PH_PROBE_NAME)

# Generate process and control data for PID controllers.
# Index specifies the node to associate with the accessor. 
# (e.g., index=1 would be pH probe node 1)
process_value = ph_probe.to_pid_process_value(index=0)
control_output = pump.to_pid_control_output(index=0)

# create a `ScheduleParameters` instance with default values
params = ScheduleParameters()
# change the Bias term
#params.bias = None
# change the Kp term
params.kp = 1
# change the Ki term
params.ki = .025
# change the Kd term
params.kd = .55
# Error values within this range around the setpoint will not activate the controller
params.dead_zone = 0.001 
# Integral term will be accumulated when the error is within this limit
params.integral_valid = 0.3 
# Change the linearity factor
#params.linearity = 1.0
# Change the beta factor
#params.beta = 1.0
# Change the setpoint range weighting
#params.setpoint_range = 1.0
# Change the limit on the proportional term
#params.p_limit = None
# Change the limit on the integral term
#params.i_limit = None
# Change the limit on the derivative term
#params.d_limit = None
# Change the limit on the maximum change in output
#params.delta_limit = None

constraints = ScheduleConstraints()  # You can add schedule constraints here
# change the process constraints
#constraints.process = (0, 0.35)
# change the error constraints
#constraints.error = (0, 0.35)
# change the control constraints
#constraints.control = (0, 0.35)

# create the schedule
sched = Schedule(params, constraints)

p = Pid(8)  # Initialize PID with a setpoint of 8
# Add the schedule to the PID controller
# Since this is the first schedule added, it will
# have the highest priority
p.add_schedule(sched)  

p.output_limits = (0.0, 1)  # Output will be constrained within these limits

pid = aq.pid_controller("Controller", process_value, control_output, p)