File size: 3,023 Bytes
96a5049
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once
#include "Arduino.h"

class PIDController {
private:
    double kp;
    double ki;
    double kd;
    
    double input;
    double output;
    double setpoint;
    
    unsigned long lastTime;
    double outputSum;
    double lastInput;
    
    double outMin;
    double outMax;
    int sampleTime;
    bool inAuto;

public:
    PIDController(double Kp, double Ki, double Kd) :
        kp(Kp),
        ki(Ki),
        kd(Kd),
        input(0),
        output(0),
        setpoint(0),
        lastTime(0),
        outputSum(0),
        lastInput(0),
        outMin(0),
        outMax(255),
        sampleTime(100),
        inAuto(false)
    {
    }
    
    bool Compute() {
        if(!inAuto) return false;
        
        unsigned long now = millis();
        unsigned long timeChange = (now - lastTime);
        if(timeChange >= sampleTime) {
            double error = setpoint - input;
            
            outputSum += (ki * error);
            if(outputSum > outMax) outputSum = outMax;
            else if(outputSum < outMin) outputSum = outMin;
            
            double dInput = (input - lastInput);
            
            output = kp * error + outputSum - kd * dInput;
            
            if(output > outMax) output = outMax;
            else if(output < outMin) output = outMin;
            
            lastInput = input;
            lastTime = now;
            
            return true;
        }
        return false;
    }
    
    void SetTunings(double Kp, double Ki, double Kd) {
        if (Kp < 0 || Ki < 0 || Kd < 0) return;
        
        double SampleTimeInSec = ((double)sampleTime)/1000;
        kp = Kp;
        ki = Ki * SampleTimeInSec;
        kd = Kd / SampleTimeInSec;
    }
    
    void SetSampleTime(int NewSampleTime) {
        if (NewSampleTime > 0) {
            double ratio = (double)NewSampleTime / (double)sampleTime;
            ki *= ratio;
            kd /= ratio;
            sampleTime = (unsigned long)NewSampleTime;
        }
    }
    
    void SetOutputLimits(double Min, double Max) {
        if(Min >= Max) return;
        outMin = Min;
        outMax = Max;
        
        if(inAuto) {
            if(output > outMax) output = outMax;
            else if(output < outMin) output = outMin;
            
            if(outputSum > outMax) outputSum = outMax;
            else if(outputSum < outMin) outputSum = outMin;
        }
    }
    
    void SetMode(bool Mode) {
        bool newAuto = Mode;
        if(newAuto && !inAuto) {
            Initialize();
        }
        inAuto = newAuto;
    }
    
    void Initialize() {
        outputSum = output;
        lastInput = input;
        if(outputSum > outMax) outputSum = outMax;
        else if(outputSum < outMin) outputSum = outMin;
    }

    // Методы для установки и получения значений
    void SetInput(double val) { input = val; }
    void SetSetpoint(double val) { setpoint = val; }
    double GetOutput() const { return output; }
};