forked from r-downing/AutoPID
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include "AutoPID.h" | ||
|
||
AutoPID::AutoPID(double *input, double *setpoint, double *output, double outputMin, double outputMax, | ||
double Kp, double Ki, double Kd) { | ||
_input = input; | ||
_setpoint = setpoint; | ||
_output = output; | ||
_outputMin = outputMin; | ||
_outputMax = outputMax; | ||
setGains(Kp, Ki, Kd); | ||
_timeStep = 1000; | ||
}//AutoPID::AutoPID | ||
|
||
void AutoPID::setGains(double Kp, double Ki, double Kd) { | ||
_Kp = Kp; | ||
_Ki = Ki; | ||
_Kd = Kd; | ||
}//AutoPID::setControllerParams | ||
|
||
void AutoPID::setBangBang(double bangOn, double bangOff) { | ||
_bangOn = bangOn; | ||
_bangOff = bangOff; | ||
}//void AutoPID::setBangBang | ||
|
||
void AutoPID::setBangBang(double bangRange) { | ||
setBangBang(bangRange, bangRange); | ||
}//void AutoPID::setBangBang | ||
|
||
void AutoPID::setOutputRange(double outputMin, double outputMax) { | ||
_outputMin = outputMin; | ||
_outputMax = outputMax; | ||
}//void AutoPID::setOutputRange | ||
|
||
void AutoPID::setTimeStep(unsigned long timeStep){ | ||
_timeStep = timeStep; | ||
} | ||
|
||
|
||
bool AutoPID::atSetPoint(double threshold) { | ||
return abs(*_setpoint - *_input) <= threshold; | ||
}//bool AutoPID::atSetPoint | ||
|
||
void AutoPID::run() { | ||
if (_stopped) { | ||
_stopped = false; | ||
reset(); | ||
} | ||
//if bang thresholds are defined and we're outside of them, use bang-bang control | ||
if (_bangOn && ((*_setpoint - *_input) > _bangOn)) { | ||
*_output = _outputMax; | ||
_lastStep = millis(); | ||
} else if (_bangOff && ((*_input - *_setpoint) > _bangOff)) { | ||
*_output = _outputMin; | ||
_lastStep = millis(); | ||
} else { //otherwise use PID control | ||
unsigned long _dT = millis() - _lastStep; //calculate time since last update | ||
if (_dT >= _timeStep) { //if long enough, do PID calculations | ||
_lastStep = millis(); | ||
double _error = *_setpoint - *_input; | ||
_integral += (_error + _previousError) / 2 * _dT / 1000.0; //Riemann sum integral | ||
//_integral = constrain(_integral, _outputMin/_Ki, _outputMax/_Ki); | ||
double _dError = (_error - _previousError) / _dT / 1000.0; //derivative | ||
_previousError = _error; | ||
double PID = (_Kp * _error) + (_Ki * _integral) + (_Kd * _dError); | ||
//*_output = _outputMin + (constrain(PID, 0, 1) * (_outputMax - _outputMin)); | ||
*_output = constrain(PID, _outputMin, _outputMax); | ||
} | ||
} | ||
}//void AutoPID::run | ||
|
||
void AutoPID::stop() { | ||
_stopped = true; | ||
reset(); | ||
} | ||
void AutoPID::reset() { | ||
_lastStep = millis(); | ||
_integral = 0; | ||
_previousError = 0; | ||
} | ||
|
||
bool AutoPID::isStopped(){ | ||
return _stopped; | ||
} | ||
|
||
void AutoPIDRelay::run() { | ||
AutoPID::run(); | ||
while ((millis() - _lastPulseTime) > _pulseWidth) _lastPulseTime += _pulseWidth; | ||
*_relayState = ((millis() - _lastPulseTime) < (_pulseValue * _pulseWidth)); | ||
} | ||
|
||
|
||
double AutoPIDRelay::getPulseValue(){ | ||
return (isStopped()?0:_pulseValue); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#ifndef AUTOPID_H | ||
#define AUTOPID_H | ||
#include <Arduino.h> | ||
|
||
class AutoPID { | ||
|
||
public: | ||
// Constructor - takes pointer inputs for control variales, so they are updated automatically | ||
AutoPID(double *input, double *setpoint, double *output, double outputMin, double outputMax, | ||
double Kp, double Ki, double Kd); | ||
// Allows manual adjustment of gains | ||
void setGains(double Kp, double Ki, double Kd); | ||
// Sets bang-bang control ranges, separate upper and lower offsets, zero for off | ||
void setBangBang(double bangOn, double bangOff); | ||
// Sets bang-bang control range +-single offset | ||
void setBangBang(double bangRange); | ||
// Allows manual readjustment of output range | ||
void setOutputRange(double outputMin, double outputMax); | ||
// Allows manual adjustment of time step (default 1000ms) | ||
void setTimeStep(unsigned long timeStep); | ||
// Returns true when at set point (+-threshold) | ||
bool atSetPoint(double threshold); | ||
// Runs PID calculations when needed. Should be called repeatedly in loop. | ||
// Automatically reads input and sets output via pointers | ||
void run(); | ||
// Stops PID functionality, output sets to | ||
void stop(); | ||
void reset(); | ||
bool isStopped(); | ||
|
||
private: | ||
double _Kp, _Ki, _Kd; | ||
double _integral, _previousError; | ||
double _bangOn, _bangOff; | ||
double *_input, *_setpoint, *_output; | ||
double _outputMin, _outputMax; | ||
unsigned long _timeStep, _lastStep; | ||
bool _stopped; | ||
|
||
};//class AutoPID | ||
|
||
class AutoPIDRelay : public AutoPID { | ||
public: | ||
|
||
AutoPIDRelay(double *input, double *setpoint, bool *relayState, double pulseWidth, double Kp, double Ki, double Kd) | ||
: AutoPID(input, setpoint, &_pulseValue, 0, 1.0, Kp, Ki, Kd) { | ||
_relayState = relayState; | ||
_pulseWidth = pulseWidth; | ||
}; | ||
|
||
void run(); | ||
|
||
double getPulseValue(); | ||
|
||
private: | ||
bool * _relayState; | ||
unsigned long _pulseWidth, _lastPulseTime; | ||
double _pulseValue; | ||
};//class AutoPIDRelay | ||
|
||
#endif |