]> git.basschouten.com Git - openhab-addons.git/blob
71d0bd4eebccd421328dda1b880dcd8ec0d5aa85
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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 double integralResult;
29     private double derivativeResult;
30     private double previousError;
31
32     private double kp;
33     private double ki;
34     private double kd;
35     private double derivativeTimeConstantSec;
36     private double iMinResult;
37     private double iMaxResult;
38
39     public PIDController(double kpAdjuster, double kiAdjuster, double kdAdjuster, double derivativeTimeConstantSec,
40             double iMinValue, double iMaxValue, double previousIntegralPart, double previousDerivativePart,
41             double previousError) {
42         this.kp = kpAdjuster;
43         this.ki = kiAdjuster;
44         this.kd = kdAdjuster;
45         this.derivativeTimeConstantSec = derivativeTimeConstantSec;
46         this.iMinResult = Double.NaN;
47         this.iMaxResult = Double.NaN;
48
49         // prepare min/max, restore previous state for the integral result accumulator
50         if (Double.isFinite(kiAdjuster) && Math.abs(kiAdjuster) > 0.0) {
51             if (Double.isFinite(iMinValue)) {
52                 this.iMinResult = iMinValue / kiAdjuster;
53             }
54             if (Double.isFinite(iMaxValue)) {
55                 this.iMaxResult = iMaxValue / kiAdjuster;
56             }
57             if (Double.isFinite(previousIntegralPart)) {
58                 this.integralResult = previousIntegralPart / kiAdjuster;
59             }
60         }
61
62         // restore previous state for the derivative result accumulator
63         if (Double.isFinite(kdAdjuster) && Math.abs(kdAdjuster) > 0.0) {
64             if (Double.isFinite(previousDerivativePart)) {
65                 this.derivativeResult = previousDerivativePart / kdAdjuster;
66             }
67         }
68
69         // restore previous state for the previous error variable
70         if (Double.isFinite(previousError)) {
71             this.previousError = previousError;
72         }
73     }
74
75     public PIDOutputDTO calculate(double input, double setpoint, long lastInvocationMs, int loopTimeMs) {
76         final double lastInvocationSec = lastInvocationMs / 1000d;
77         final double error = setpoint - input;
78
79         // derivative T1 calculation
80         final double timeQuotient = lastInvocationSec / derivativeTimeConstantSec;
81         if (derivativeTimeConstantSec != 0) {
82             derivativeResult = LowpassFilter.calculate(derivativeResult, error - previousError, timeQuotient);
83             previousError = error;
84         }
85
86         // integral calculation
87         integralResult += error * lastInvocationMs / loopTimeMs;
88         if (Double.isFinite(iMinResult)) {
89             integralResult = Math.max(integralResult, iMinResult);
90         }
91         if (Double.isFinite(iMaxResult)) {
92             integralResult = Math.min(integralResult, iMaxResult);
93         }
94
95         // calculate parts
96         final double proportionalPart = kp * error;
97
98         double integralPart = ki * integralResult;
99
100         final double derivativePart = kd * derivativeResult;
101
102         final double output = proportionalPart + integralPart + derivativePart;
103
104         return new PIDOutputDTO(output, proportionalPart, integralPart, derivativePart, error);
105     }
106
107     public void setIntegralResult(double integralResult) {
108         this.integralResult = integralResult;
109     }
110
111     public void setDerivativeResult(double derivativeResult) {
112         this.derivativeResult = derivativeResult;
113     }
114 }