]> git.basschouten.com Git - openhab-addons.git/blob
a93f89af4152e933b0f47671a71c6177c498d5d6
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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     private double output;
32
33     private double kp;
34     private double ki;
35     private double kd;
36     private double derivativeTimeConstantSec;
37     private double iMinResult;
38     private double iMaxResult;
39
40     public PIDController(double kpAdjuster, double kiAdjuster, double kdAdjuster, double derivativeTimeConstantSec,
41             double iMinValue, double iMaxValue) {
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 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         }
58     }
59
60     public PIDOutputDTO calculate(double input, double setpoint, long lastInvocationMs, int loopTimeMs) {
61         final double lastInvocationSec = lastInvocationMs / 1000d;
62         final double error = setpoint - input;
63
64         // derivative T1 calculation
65         final double timeQuotient = lastInvocationSec / derivativeTimeConstantSec;
66         if (derivativeTimeConstantSec != 0) {
67             derivativeResult = LowpassFilter.calculate(derivativeResult, error - previousError, timeQuotient);
68             previousError = error;
69         }
70
71         // integral calculation
72         integralResult += error * lastInvocationMs / loopTimeMs;
73         if (Double.isFinite(iMinResult)) {
74             integralResult = Math.max(integralResult, iMinResult);
75         }
76         if (Double.isFinite(iMaxResult)) {
77             integralResult = Math.min(integralResult, iMaxResult);
78         }
79
80         // calculate parts
81         final double proportionalPart = kp * error;
82
83         double integralPart = ki * integralResult;
84
85         final double derivativePart = kd * derivativeResult;
86
87         output = proportionalPart + integralPart + derivativePart;
88
89         return new PIDOutputDTO(output, proportionalPart, integralPart, derivativePart, error);
90     }
91
92     public void setIntegralResult(double integralResult) {
93         this.integralResult = integralResult;
94     }
95
96     public void setDerivativeResult(double derivativeResult) {
97         this.derivativeResult = derivativeResult;
98     }
99 }