]> git.basschouten.com Git - openhab-addons.git/blob
36e5d84b37de665d7b991930e0220af6605a987a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.automation.pidcontroller.internal.handler;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.automation.pidcontroller.internal.LowpassFilter;
17
18 /**
19  * The {@link PIDController} provides the necessary methods for retrieving part(s) of the PID calculations
20  * and it provides the method for the overall PID calculations. It also resets the PID controller
21  *
22  * @author George Erhan - Initial contribution
23  * @author Hilbrand Bouwkamp - Adapted for new rule engine
24  * @author Fabian Wolter - Add T1 to D part, add debugging ability for PID values
25  */
26 @NonNullByDefault
27 class PIDController {
28     private final double outputLowerLimit;
29     private final double outputUpperLimit;
30
31     private double integralResult;
32     private double derivativeResult;
33     private double previousError;
34     private double output;
35
36     private double kp;
37     private double ki;
38     private double kd;
39     private double derivativeTimeConstantSec;
40
41     public PIDController(double outputLowerLimit, double outputUpperLimit, double kpAdjuster, double kiAdjuster,
42             double kdAdjuster, double derivativeTimeConstantSec) {
43         this.outputLowerLimit = outputLowerLimit;
44         this.outputUpperLimit = outputUpperLimit;
45         this.kp = kpAdjuster;
46         this.ki = kiAdjuster;
47         this.kd = kdAdjuster;
48         this.derivativeTimeConstantSec = derivativeTimeConstantSec;
49     }
50
51     public PIDOutputDTO calculate(double input, double setpoint, long lastInvocationMs) {
52         final double lastInvocationSec = lastInvocationMs / 1000d;
53         final double error = setpoint - input;
54
55         // derivative T1 calculation
56         final double timeQuotient = lastInvocationSec / derivativeTimeConstantSec;
57         if (derivativeTimeConstantSec != 0) {
58             derivativeResult = LowpassFilter.calculate(derivativeResult, error - previousError, timeQuotient);
59             previousError = error;
60         }
61
62         // integral calculation
63         integralResult += error * lastInvocationSec;
64         // limit to output limits
65         if (ki != 0) {
66             final double maxIntegral = outputUpperLimit / ki;
67             final double minIntegral = outputLowerLimit / ki;
68             integralResult = Math.min(maxIntegral, Math.max(minIntegral, integralResult));
69         }
70
71         // calculate parts
72         final double proportionalPart = kp * error;
73         final double integralPart = ki * integralResult;
74         final double derivativePart = kd * derivativeResult;
75         output = proportionalPart + integralPart + derivativePart;
76
77         // limit output value
78         output = Math.min(outputUpperLimit, Math.max(outputLowerLimit, output));
79
80         return new PIDOutputDTO(output, proportionalPart, integralPart, derivativePart, error);
81     }
82 }