├── Banner.png ├── Example Source Code └── ARM Example │ ├── PID Example - Temperutur Control with PWM (c version).rar │ └── Guide.txt ├── LICENSE ├── README.md ├── PID (c version) ├── pid.c └── pid.h └── PID (cpp version) ├── pid.cpp └── pid.h /Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Majid-Derhambakhsh/PID-Library/HEAD/Banner.png -------------------------------------------------------------------------------- /Example Source Code/ARM Example/PID Example - Temperutur Control with PWM (c version).rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Majid-Derhambakhsh/PID-Library/HEAD/Example Source Code/ARM Example/PID Example - Temperutur Control with PWM (c version).rar -------------------------------------------------------------------------------- /Example Source Code/ARM Example/Guide.txt: -------------------------------------------------------------------------------- 1 | ~ Author : Majid Derhambakhsh 2 | ~ Created : 11/28/2021 3 | ~ Support : Majid.Derhambakhsh@outlook.com 4 | ~ Github ID: Majid-Derhambakhsh 5 | 6 | - MCU : STM32F103C8T 7 | - Compiler : STM32CubeIDE. 8 | - Library : HAL Library. 9 | - Programming language : C -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Majid Derhambakhsh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Banner](Banner.png) 2 | 3 | # PID-Library (C Version) 4 | PID Controller library for ARM Cortex M (STM32) 5 | 6 | > #### Download Arduino Library : [Arduino-PID-Library](https://github.com/br3ttb/Arduino-PID-Library) 7 | 8 | ## Release 9 | - #### Version : 1.0.0 10 | 11 | - #### Type : Embedded Software. 12 | 13 | - #### Support : 14 | - ARM STM32 series 15 | 16 | - #### Program Language : C/C++ 17 | 18 | - #### Properties : 19 | 20 | - #### Changes : 21 | 22 | - #### Required Library/Driver : 23 | 24 | 25 | ## Overview 26 | ### Initialization and de-initialization functions: 27 | ```c++ 28 | void PID(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); 29 | void PID2(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection); 30 | ``` 31 | 32 | ### Operation functions: 33 | ```c++ 34 | /* ::::::::::: Computing ::::::::::: */ 35 | uint8_t PID_Compute(PID_TypeDef *uPID); 36 | 37 | /* ::::::::::: PID Mode :::::::::::: */ 38 | void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode); 39 | PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID); 40 | 41 | /* :::::::::: PID Limits ::::::::::: */ 42 | void PID_SetOutputLimits(PID_TypeDef *uPID, double Min, double Max); 43 | 44 | /* :::::::::: PID Tunings :::::::::: */ 45 | void PID_SetTunings(PID_TypeDef *uPID, double Kp, double Ki, double Kd); 46 | void PID_SetTunings2(PID_TypeDef *uPID, double Kp, double Ki, double Kd, PIDPON_TypeDef POn); 47 | 48 | /* ::::::::: PID Direction ::::::::: */ 49 | void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction); 50 | PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID); 51 | 52 | /* ::::::::: PID Sampling :::::::::: */ 53 | void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime); 54 | 55 | /* ::::::: Get Tunings Param ::::::: */ 56 | double PID_GetKp(PID_TypeDef *uPID); 57 | double PID_GetKi(PID_TypeDef *uPID); 58 | double PID_GetKd(PID_TypeDef *uPID); 59 | ``` 60 | 61 | ### Macros: 62 | ```diff 63 | non 64 | ``` 65 | 66 | ## Guide 67 | 68 | #### This library can be used as follows: 69 | #### 1. Add pid.h header 70 | #### 2. Create PID struct and initialize it, for example: 71 | * Initializer: 72 | ```c++ 73 | PID(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); 74 | ``` 75 | * Parameters: 76 | * uPID : Pointer to pid struct 77 | * Input : The variable we're trying to control (double) 78 | * Output : The variable that will be adjusted by the pid (double) 79 | * Setpoint : The value we want to Input to maintain (double) 80 | * Kp,Ki,Kd : Tuning Parameters. these affect how the pid will change the output (double>=0) 81 | * POn : Either P_ON_E (Default) or P_ON_M. Allows Proportional on Measurement to be specified. 82 | * ControllerDirection : Either DIRECT or REVERSE. determines which direction the output will move when faced with a given error. DIRECT is most common 83 | 84 | 85 | * Example: 86 | ```c++ 87 | PID_TypeDef TPID; 88 | 89 | double Temp, PIDOut, TempSetpoint; 90 | 91 | PID(&TPID, &Temp, &PIDOut, &TempSetpoint, 2, 5, 1, _PID_P_ON_E, _PID_CD_DIRECT); 92 | ``` 93 | #### 3. Set 'mode', 'sample time' and 'output limit', for example: 94 | * Functions: 95 | ```c++ 96 | void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode); 97 | void PID_SetOutputLimits(PID_TypeDef *uPID, double Min, double Max); 98 | void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime); 99 | ``` 100 | * Parameters: 101 | * uPID : Pointer to pid struct 102 | * Mode : _PID_MODE_AUTOMATIC or _PID_MODE_MANUAL 103 | * Min : Low end of the range. must be < max (double) 104 | * Max : High end of the range. must be > min (double) 105 | * NewSampleTime : How often, in milliseconds, the PID will be evaluated. (int>0) 106 | 107 | * Example: 108 | ```c++ 109 | PID_SetMode(&TPID, _PID_MODE_AUTOMATIC); 110 | PID_SetSampleTime(&TPID, 500); 111 | PID_SetOutputLimits(&TPID, 1, 100); 112 | ``` 113 | 114 | #### 4. Using Compute function, for example: 115 | 116 | ```c++ 117 | PID_Compute(&TPID); 118 | ``` 119 | 120 | ## Examples 121 | 122 | #### Example 1: PID Compute for temperature 123 | ```c++ 124 | #include "main.h" 125 | #include "pid.h" 126 | 127 | PID_TypeDef TPID; 128 | 129 | char OutBuf[50]; 130 | double Temp, PIDOut, TempSetpoint; 131 | 132 | int main(void) 133 | { 134 | 135 | HW_Init(); 136 | 137 | PID(&TPID, &Temp, &PIDOut, &TempSetpoint, 2, 5, 1, _PID_P_ON_E, _PID_CD_DIRECT); 138 | 139 | PID_SetMode(&TPID, _PID_MODE_AUTOMATIC); 140 | PID_SetSampleTime(&TPID, 500); 141 | PID_SetOutputLimits(&TPID, 1, 100); 142 | 143 | while (1) 144 | { 145 | 146 | Temp = GetTemp(); 147 | PID_Compute(&TPID); 148 | 149 | sprintf(OutBuf, "Temp%3.2f : %u\n", Temp, (uint16_t)PIDOut); 150 | UART_Transmit((uint8_t *)OutBuf, strlen(OutBuf)); 151 | 152 | Delay_ms(500); 153 | 154 | } 155 | } 156 | 157 | ``` 158 | 159 | ## Tests performed: 160 | - [x] Run on STM32 Fx cores 161 | 162 | ## Developers: 163 | - ### Majid Derhambakhsh 164 | 165 | -------------------------------------------------------------------------------- /PID (c version)/pid.c: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | ~ File : pid.c 4 | ~ Author : Majid Derhambakhsh 5 | ~ Version: V1.0.0 6 | ~ Created: 02/11/2021 03:43:00 AM 7 | ~ Brief : 8 | ~ Support: 9 | E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support) 10 | 11 | Github : https://github.com/Majid-Derhambakhsh 12 | ------------------------------------------------------------------------------ 13 | ~ Description: 14 | 15 | ~ Attention : 16 | 17 | ~ Changes : 18 | ------------------------------------------------------------------------------ 19 | */ 20 | 21 | #include "pid.h" 22 | 23 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 24 | /* ~~~~~~~~~~~~~~~~~ Initialize ~~~~~~~~~~~~~~~~ */ 25 | void PID_Init(PID_TypeDef *uPID) 26 | { 27 | /* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */ 28 | uPID->OutputSum = *uPID->MyOutput; 29 | uPID->LastInput = *uPID->MyInput; 30 | 31 | if (uPID->OutputSum > uPID->OutMax) 32 | { 33 | uPID->OutputSum = uPID->OutMax; 34 | } 35 | else if (uPID->OutputSum < uPID->OutMin) 36 | { 37 | uPID->OutputSum = uPID->OutMin; 38 | } 39 | else { } 40 | 41 | } 42 | 43 | void PID(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection) 44 | { 45 | /* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */ 46 | uPID->MyOutput = Output; 47 | uPID->MyInput = Input; 48 | uPID->MySetpoint = Setpoint; 49 | uPID->InAuto = (PIDMode_TypeDef)_FALSE; 50 | 51 | PID_SetOutputLimits(uPID, 0, _PID_8BIT_PWM_MAX); 52 | 53 | uPID->SampleTime = _PID_SAMPLE_TIME_MS_DEF; /* default Controller Sample Time is 0.1 seconds */ 54 | 55 | PID_SetControllerDirection(uPID, ControllerDirection); 56 | PID_SetTunings2(uPID, Kp, Ki, Kd, POn); 57 | 58 | uPID->LastTime = GetTime() - uPID->SampleTime; 59 | 60 | } 61 | 62 | void PID2(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection) 63 | { 64 | PID(uPID, Input, Output, Setpoint, Kp, Ki, Kd, _PID_P_ON_E, ControllerDirection); 65 | } 66 | 67 | /* ~~~~~~~~~~~~~~~~~ Computing ~~~~~~~~~~~~~~~~~ */ 68 | uint8_t PID_Compute(PID_TypeDef *uPID) 69 | { 70 | 71 | uint32_t now; 72 | uint32_t timeChange; 73 | 74 | double input; 75 | double error; 76 | double dInput; 77 | double output; 78 | 79 | /* ~~~~~~~~~~ Check PID mode ~~~~~~~~~~ */ 80 | if (!uPID->InAuto) 81 | { 82 | return _FALSE; 83 | } 84 | 85 | /* ~~~~~~~~~~ Calculate time ~~~~~~~~~~ */ 86 | now = GetTime(); 87 | timeChange = (now - uPID->LastTime); 88 | 89 | if (timeChange >= uPID->SampleTime) 90 | { 91 | /* ..... Compute all the working error variables ..... */ 92 | input = *uPID->MyInput; 93 | error = *uPID->MySetpoint - input; 94 | dInput = (input - uPID->LastInput); 95 | 96 | uPID->OutputSum += (uPID->Ki * error); 97 | 98 | /* ..... Add Proportional on Measurement, if P_ON_M is specified ..... */ 99 | if (!uPID->POnE) 100 | { 101 | uPID->OutputSum -= uPID->Kp * dInput; 102 | } 103 | 104 | if (uPID->OutputSum > uPID->OutMax) 105 | { 106 | uPID->OutputSum = uPID->OutMax; 107 | } 108 | else if (uPID->OutputSum < uPID->OutMin) 109 | { 110 | uPID->OutputSum = uPID->OutMin; 111 | } 112 | else { } 113 | 114 | /* ..... Add Proportional on Error, if P_ON_E is specified ..... */ 115 | if (uPID->POnE) 116 | { 117 | output = uPID->Kp * error; 118 | } 119 | else 120 | { 121 | output = 0; 122 | } 123 | 124 | /* ..... Compute Rest of PID Output ..... */ 125 | output += uPID->OutputSum - uPID->Kd * dInput; 126 | 127 | if (output > uPID->OutMax) 128 | { 129 | output = uPID->OutMax; 130 | } 131 | else if (output < uPID->OutMin) 132 | { 133 | output = uPID->OutMin; 134 | } 135 | else { } 136 | 137 | *uPID->MyOutput = output; 138 | 139 | /* ..... Remember some variables for next time ..... */ 140 | uPID->LastInput = input; 141 | uPID->LastTime = now; 142 | 143 | return _TRUE; 144 | 145 | } 146 | else 147 | { 148 | return _FALSE; 149 | } 150 | 151 | } 152 | 153 | /* ~~~~~~~~~~~~~~~~~ PID Mode ~~~~~~~~~~~~~~~~~~ */ 154 | void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode) 155 | { 156 | 157 | uint8_t newAuto = (Mode == _PID_MODE_AUTOMATIC); 158 | 159 | /* ~~~~~~~~~~ Initialize the PID ~~~~~~~~~~ */ 160 | if (newAuto && !uPID->InAuto) 161 | { 162 | PID_Init(uPID); 163 | } 164 | 165 | uPID->InAuto = (PIDMode_TypeDef)newAuto; 166 | 167 | } 168 | PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID) 169 | { 170 | return uPID->InAuto ? _PID_MODE_AUTOMATIC : _PID_MODE_MANUAL; 171 | } 172 | 173 | /* ~~~~~~~~~~~~~~~~ PID Limits ~~~~~~~~~~~~~~~~~ */ 174 | void PID_SetOutputLimits(PID_TypeDef *uPID, double Min, double Max) 175 | { 176 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 177 | if (Min >= Max) 178 | { 179 | return; 180 | } 181 | 182 | uPID->OutMin = Min; 183 | uPID->OutMax = Max; 184 | 185 | /* ~~~~~~~~~~ Check PID Mode ~~~~~~~~~~ */ 186 | if (uPID->InAuto) 187 | { 188 | 189 | /* ..... Check out value ..... */ 190 | if (*uPID->MyOutput > uPID->OutMax) 191 | { 192 | *uPID->MyOutput = uPID->OutMax; 193 | } 194 | else if (*uPID->MyOutput < uPID->OutMin) 195 | { 196 | *uPID->MyOutput = uPID->OutMin; 197 | } 198 | else { } 199 | 200 | /* ..... Check out value ..... */ 201 | if (uPID->OutputSum > uPID->OutMax) 202 | { 203 | uPID->OutputSum = uPID->OutMax; 204 | } 205 | else if (uPID->OutputSum < uPID->OutMin) 206 | { 207 | uPID->OutputSum = uPID->OutMin; 208 | } 209 | else { } 210 | 211 | } 212 | 213 | } 214 | 215 | /* ~~~~~~~~~~~~~~~~ PID Tunings ~~~~~~~~~~~~~~~~ */ 216 | void PID_SetTunings(PID_TypeDef *uPID, double Kp, double Ki, double Kd) 217 | { 218 | PID_SetTunings2(uPID, Kp, Ki, Kd, uPID->POn); 219 | } 220 | void PID_SetTunings2(PID_TypeDef *uPID, double Kp, double Ki, double Kd, PIDPON_TypeDef POn) 221 | { 222 | 223 | double SampleTimeInSec; 224 | 225 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 226 | if (Kp < 0 || Ki < 0 || Kd < 0) 227 | { 228 | return; 229 | } 230 | 231 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 232 | uPID->POn = POn; 233 | uPID->POnE = (PIDPON_TypeDef)(POn == _PID_P_ON_E); 234 | 235 | uPID->DispKp = Kp; 236 | uPID->DispKi = Ki; 237 | uPID->DispKd = Kd; 238 | 239 | /* ~~~~~~~~~ Calculate time ~~~~~~~~ */ 240 | SampleTimeInSec = ((double)uPID->SampleTime) / 1000; 241 | 242 | uPID->Kp = Kp; 243 | uPID->Ki = Ki * SampleTimeInSec; 244 | uPID->Kd = Kd / SampleTimeInSec; 245 | 246 | /* ~~~~~~~~ Check direction ~~~~~~~~ */ 247 | if (uPID->ControllerDirection == _PID_CD_REVERSE) 248 | { 249 | 250 | uPID->Kp = (0 - uPID->Kp); 251 | uPID->Ki = (0 - uPID->Ki); 252 | uPID->Kd = (0 - uPID->Kd); 253 | 254 | } 255 | 256 | } 257 | 258 | /* ~~~~~~~~~~~~~~~ PID Direction ~~~~~~~~~~~~~~~ */ 259 | void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction) 260 | { 261 | /* ~~~~~~~~~~ Check parameters ~~~~~~~~~~ */ 262 | if ((uPID->InAuto) && (Direction !=uPID->ControllerDirection)) 263 | { 264 | 265 | uPID->Kp = (0 - uPID->Kp); 266 | uPID->Ki = (0 - uPID->Ki); 267 | uPID->Kd = (0 - uPID->Kd); 268 | 269 | } 270 | 271 | uPID->ControllerDirection = Direction; 272 | 273 | } 274 | PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID) 275 | { 276 | return uPID->ControllerDirection; 277 | } 278 | 279 | /* ~~~~~~~~~~~~~~~ PID Sampling ~~~~~~~~~~~~~~~~ */ 280 | void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime) 281 | { 282 | 283 | double ratio; 284 | 285 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 286 | if (NewSampleTime > 0) 287 | { 288 | 289 | ratio = (double)NewSampleTime / (double)uPID->SampleTime; 290 | 291 | uPID->Ki *= ratio; 292 | uPID->Kd /= ratio; 293 | uPID->SampleTime = (uint32_t)NewSampleTime; 294 | 295 | } 296 | 297 | } 298 | 299 | /* ~~~~~~~~~~~~~ Get Tunings Param ~~~~~~~~~~~~~ */ 300 | double PID_GetKp(PID_TypeDef *uPID) 301 | { 302 | return uPID->DispKp; 303 | } 304 | double PID_GetKi(PID_TypeDef *uPID) 305 | { 306 | return uPID->DispKi; 307 | } 308 | double PID_GetKd(PID_TypeDef *uPID) 309 | { 310 | return uPID->DispKd; 311 | } 312 | -------------------------------------------------------------------------------- /PID (cpp version)/pid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | ~ File : pid.cpp 4 | ~ Author : Majid Derhambakhsh 5 | ~ Version: V1.0.0 6 | ~ Created: 06/12/2021 05:00:00 PM 7 | ~ Brief : 8 | ~ Support: 9 | E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support) 10 | 11 | Github : https://github.com/Majid-Derhambakhsh 12 | ------------------------------------------------------------------------------ 13 | ~ Description: CPP version 14 | 15 | ~ Attention : 16 | 17 | ~ Changes : 18 | ------------------------------------------------------------------------------ 19 | */ 20 | 21 | #include "pid.h" 22 | 23 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 24 | /* ~~~~~~~~~~~~~~~~ Constructor ~~~~~~~~~~~~~~~~ */ 25 | PID::PID() { } 26 | 27 | PID::PID(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection) 28 | { 29 | /* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */ 30 | _myOutput = Output; 31 | _myInput = Input; 32 | _mySetpoint = Setpoint; 33 | _inAuto = (PIDMode_TypeDef)_FALSE; 34 | 35 | PID::SetOutputLimits(0, _PID_8BIT_PWM_MAX); 36 | 37 | _sampleTime = _PID_SAMPLE_TIME_MS_DEF; /* default Controller Sample Time is 0.1 seconds */ 38 | 39 | PID::SetControllerDirection(ControllerDirection); 40 | PID::SetTunings(Kp, Ki, Kd, POn); 41 | 42 | _lastTime = GetTime() - _sampleTime; 43 | 44 | } 45 | 46 | PID::PID(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection) : PID::PID(Input, Output, Setpoint, Kp, Ki, Kd, _PID_P_ON_E, ControllerDirection){ } 47 | 48 | /* ~~~~~~~~~~~~~~~~~ Initialize ~~~~~~~~~~~~~~~~ */ 49 | void PID::Init(void) 50 | { 51 | /* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */ 52 | _outputSum = *_myOutput; 53 | _lastInput = *_myInput; 54 | 55 | if (_outputSum > _outMax) 56 | { 57 | _outputSum = _outMax; 58 | } 59 | else if (_outputSum < _outMin) 60 | { 61 | _outputSum = _outMin; 62 | } 63 | else { } 64 | 65 | } 66 | 67 | void PID::Init(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection) 68 | { 69 | /* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */ 70 | _myOutput = Output; 71 | _myInput = Input; 72 | _mySetpoint = Setpoint; 73 | _inAuto = (PIDMode_TypeDef)_FALSE; 74 | 75 | PID::SetOutputLimits(0, _PID_8BIT_PWM_MAX); 76 | 77 | _sampleTime = _PID_SAMPLE_TIME_MS_DEF; /* default Controller Sample Time is 0.1 seconds */ 78 | 79 | PID::SetControllerDirection(ControllerDirection); 80 | PID::SetTunings(Kp, Ki, Kd, POn); 81 | 82 | _lastTime = GetTime() - _sampleTime; 83 | 84 | } 85 | 86 | void PID::Init(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection) 87 | { 88 | PID::Init(Input, Output, Setpoint, Kp, Ki, Kd, _PID_P_ON_E, ControllerDirection); 89 | } 90 | 91 | /* ~~~~~~~~~~~~~~~~~ Computing ~~~~~~~~~~~~~~~~~ */ 92 | uint8_t PID::Compute(void) 93 | { 94 | 95 | uint32_t now; 96 | uint32_t timeChange; 97 | 98 | double input; 99 | double error; 100 | double dInput; 101 | double output; 102 | 103 | /* ~~~~~~~~~~ Check PID mode ~~~~~~~~~~ */ 104 | if (!_inAuto) 105 | { 106 | return _FALSE; 107 | } 108 | 109 | /* ~~~~~~~~~~ Calculate time ~~~~~~~~~~ */ 110 | now = GetTime(); 111 | timeChange = (now - _lastTime); 112 | 113 | if (timeChange >= _sampleTime) 114 | { 115 | /* ..... Compute all the working error variables ..... */ 116 | input = *_myInput; 117 | error = *_mySetpoint - input; 118 | dInput = (input - _lastInput); 119 | 120 | _outputSum += (_ki * error); 121 | 122 | /* ..... Add Proportional on Measurement, if P_ON_M is specified ..... */ 123 | if (!_pOnE) 124 | { 125 | _outputSum -= _kp * dInput; 126 | } 127 | 128 | if (_outputSum > _outMax) 129 | { 130 | _outputSum = _outMax; 131 | } 132 | else if (_outputSum < _outMin) 133 | { 134 | _outputSum = _outMin; 135 | } 136 | else { } 137 | 138 | /* ..... Add Proportional on Error, if P_ON_E is specified ..... */ 139 | if (_pOnE) 140 | { 141 | output = _kp * error; 142 | } 143 | else 144 | { 145 | output = 0; 146 | } 147 | 148 | /* ..... Compute Rest of PID Output ..... */ 149 | output += _outputSum - _kd * dInput; 150 | 151 | if (output > _outMax) 152 | { 153 | output = _outMax; 154 | } 155 | else if (output < _outMin) 156 | { 157 | output = _outMin; 158 | } 159 | else { } 160 | 161 | *_myOutput = output; 162 | 163 | /* ..... Remember some variables for next time ..... */ 164 | _lastInput = input; 165 | _lastTime = now; 166 | 167 | return _TRUE; 168 | 169 | } 170 | else 171 | { 172 | return _FALSE; 173 | } 174 | 175 | } 176 | 177 | /* ~~~~~~~~~~~~~~~~~ PID Mode ~~~~~~~~~~~~~~~~~~ */ 178 | void PID::SetMode(PIDMode_TypeDef Mode) 179 | { 180 | 181 | uint8_t newAuto = (Mode == _PID_MODE_AUTOMATIC); 182 | 183 | /* ~~~~~~~~~~ Initialize the PID ~~~~~~~~~~ */ 184 | if (newAuto && !_inAuto) 185 | { 186 | Init(); 187 | } 188 | 189 | _inAuto = (PIDMode_TypeDef)newAuto; 190 | 191 | } 192 | PIDMode_TypeDef PID::GetMode(void) 193 | { 194 | return _inAuto ? _PID_MODE_AUTOMATIC : _PID_MODE_MANUAL; 195 | } 196 | 197 | /* ~~~~~~~~~~~~~~~~ PID Limits ~~~~~~~~~~~~~~~~~ */ 198 | void PID::SetOutputLimits(double Min, double Max) 199 | { 200 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 201 | if (Min >= Max) 202 | { 203 | return; 204 | } 205 | 206 | _outMin = Min; 207 | _outMax = Max; 208 | 209 | /* ~~~~~~~~~~ Check PID Mode ~~~~~~~~~~ */ 210 | if (_inAuto) 211 | { 212 | 213 | /* ..... Check out value ..... */ 214 | if (*_myOutput > _outMax) 215 | { 216 | *_myOutput = _outMax; 217 | } 218 | else if (*_myOutput < _outMin) 219 | { 220 | *_myOutput = _outMin; 221 | } 222 | else { } 223 | 224 | /* ..... Check out value ..... */ 225 | if (_outputSum > _outMax) 226 | { 227 | _outputSum = _outMax; 228 | } 229 | else if (_outputSum < _outMin) 230 | { 231 | _outputSum = _outMin; 232 | } 233 | else { } 234 | 235 | } 236 | 237 | } 238 | 239 | /* ~~~~~~~~~~~~~~~~ PID Tunings ~~~~~~~~~~~~~~~~ */ 240 | void PID::SetTunings(double Kp, double Ki, double Kd) 241 | { 242 | PID::SetTunings(Kp, Ki, Kd, _pOn); 243 | } 244 | void PID::SetTunings(double Kp, double Ki, double Kd, PIDPON_TypeDef POn) 245 | { 246 | 247 | double SampleTimeInSec; 248 | 249 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 250 | if (Kp < 0 || Ki < 0 || Kd < 0) 251 | { 252 | return; 253 | } 254 | 255 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 256 | _pOn = POn; 257 | _pOnE = (PIDPON_TypeDef)(POn == _PID_P_ON_E); 258 | 259 | _dispKp = Kp; 260 | _dispKi = Ki; 261 | _dispKd = Kd; 262 | 263 | /* ~~~~~~~~~ Calculate time ~~~~~~~~ */ 264 | SampleTimeInSec = ((double)_sampleTime) / 1000; 265 | 266 | _kp = Kp; 267 | _ki = Ki * SampleTimeInSec; 268 | _kd = Kd / SampleTimeInSec; 269 | 270 | /* ~~~~~~~~ Check direction ~~~~~~~~ */ 271 | if (_controllerDirection == _PID_CD_REVERSE) 272 | { 273 | 274 | _kp = (0 - _kp); 275 | _ki = (0 - _ki); 276 | _kd = (0 - _kd); 277 | 278 | } 279 | 280 | } 281 | 282 | /* ~~~~~~~~~~~~~~~ PID Direction ~~~~~~~~~~~~~~~ */ 283 | void PID::SetControllerDirection(PIDCD_TypeDef Direction) 284 | { 285 | /* ~~~~~~~~~~ Check parameters ~~~~~~~~~~ */ 286 | if ((_inAuto) && (Direction != _controllerDirection)) 287 | { 288 | 289 | _kp = (0 - _kp); 290 | _ki = (0 - _ki); 291 | _kd = (0 - _kd); 292 | 293 | } 294 | 295 | _controllerDirection = Direction; 296 | 297 | } 298 | PIDCD_TypeDef PID::GetDirection(void) 299 | { 300 | return _controllerDirection; 301 | } 302 | 303 | /* ~~~~~~~~~~~~~~~ PID Sampling ~~~~~~~~~~~~~~~~ */ 304 | void PID::SetSampleTime(int32_t NewSampleTime) 305 | { 306 | 307 | double ratio; 308 | 309 | /* ~~~~~~~~~~ Check value ~~~~~~~~~~ */ 310 | if (NewSampleTime > 0) 311 | { 312 | 313 | ratio = (double)NewSampleTime / (double)_sampleTime; 314 | 315 | _ki *= ratio; 316 | _kd /= ratio; 317 | _sampleTime = (uint32_t)NewSampleTime; 318 | 319 | } 320 | 321 | } 322 | 323 | /* ~~~~~~~~~~~~~ Get Tunings Param ~~~~~~~~~~~~~ */ 324 | double PID::GetKp(void) 325 | { 326 | return _dispKp; 327 | } 328 | double PID::GetKi(void) 329 | { 330 | return _dispKi; 331 | } 332 | double PID::GetKd(void) 333 | { 334 | return _dispKd; 335 | } 336 | -------------------------------------------------------------------------------- /PID (cpp version)/pid.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | ~ File : pid.h 4 | ~ Author : Majid Derhambakhsh 5 | ~ Version: V1.0.0 6 | ~ Created: 06/12/2021 05:00:00 PM 7 | ~ Brief : 8 | ~ Support: 9 | E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support) 10 | 11 | Github : https://github.com/Majid-Derhambakhsh 12 | ------------------------------------------------------------------------------ 13 | ~ Description: CPP version 14 | 15 | ~ Attention : 16 | 17 | ~ Changes : 18 | ------------------------------------------------------------------------------ 19 | */ 20 | 21 | #ifndef __PID_H_ 22 | #define __PID_H_ 23 | 24 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Include ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 25 | #include 26 | #include 27 | 28 | /* ------------------------------------------------------------------ */ 29 | 30 | #ifdef __CODEVISIONAVR__ /* Check compiler */ 31 | 32 | #pragma warn_unref_func- /* Disable 'unused function' warning */ 33 | 34 | /* ------------------------------------------------------------------ */ 35 | 36 | #elif defined(__GNUC__) && !defined(USE_HAL_DRIVER) /* Check compiler */ 37 | 38 | #pragma GCC diagnostic ignored "-Wunused-function" /* Disable 'unused function' warning */ 39 | 40 | /* ------------------------------------------------------------------ */ 41 | 42 | #elif defined(USE_HAL_DRIVER) /* Check driver */ 43 | 44 | #include "main.h" 45 | 46 | /* --------------- Check Mainstream series --------------- */ 47 | 48 | #ifdef STM32F0 49 | #include "stm32f0xx_hal.h" /* Import HAL library */ 50 | #elif defined(STM32F1) 51 | #include "stm32f1xx_hal.h" /* Import HAL library */ 52 | #elif defined(STM32F2) 53 | #include "stm32f2xx_hal.h" /* Import HAL library */ 54 | #elif defined(STM32F3) 55 | #include "stm32f3xx_hal.h" /* Import HAL library */ 56 | #elif defined(STM32F4) 57 | #include "stm32f4xx_hal.h" /* Import HAL library */ 58 | #elif defined(STM32F7) 59 | #include "stm32f7xx_hal.h" /* Import HAL library */ 60 | #elif defined(STM32G0) 61 | #include "stm32g0xx_hal.h" /* Import HAL library */ 62 | #elif defined(STM32G4) 63 | #include "stm32g4xx_hal.h" /* Import HAL library */ 64 | 65 | /* ------------ Check High Performance series ------------ */ 66 | 67 | #elif defined(STM32H7) 68 | #include "stm32h7xx_hal.h" /* Import HAL library */ 69 | 70 | /* ------------ Check Ultra low power series ------------- */ 71 | 72 | #elif defined(STM32L0) 73 | #include "stm32l0xx_hal.h" /* Import HAL library */ 74 | #elif defined(STM32L1) 75 | #include "stm32l1xx_hal.h" /* Import HAL library */ 76 | #elif defined(STM32L5) 77 | #include "stm32l5xx_hal.h" /* Import HAL library */ 78 | #elif defined(STM32L4) 79 | #include "stm32l4xx_hal.h" /* Import HAL library */ 80 | #elif defined(STM32H7) 81 | #include "stm32h7xx_hal.h" /* Import HAL library */ 82 | #else 83 | #endif /* STM32F1 */ 84 | 85 | /* ------------------------------------------------------- */ 86 | 87 | #if defined ( __ICCARM__ ) /* ICCARM Compiler */ 88 | 89 | #pragma diag_suppress=Pe177 /* Disable 'unused function' warning */ 90 | 91 | #elif defined ( __GNUC__ ) /* GNU Compiler */ 92 | 93 | #pragma diag_suppress 177 /* Disable 'unused function' warning */ 94 | 95 | #endif /* __ICCARM__ */ 96 | 97 | /* ------------------------------------------------------------------ */ 98 | 99 | #else /* Compiler not found */ 100 | 101 | #error Chip or Library not supported /* Send error */ 102 | 103 | #endif /* __CODEVISIONAVR__ */ 104 | 105 | /* ------------------------------------------------------------------ */ 106 | 107 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Defines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 108 | /* ------------------------ Library ------------------------ */ 109 | #define _PID_LIBRARY_VERSION 1.0.0 110 | 111 | /* ------------------------ Public ------------------------- */ 112 | #define _PID_8BIT_PWM_MAX UINT8_MAX 113 | #define _PID_SAMPLE_TIME_MS_DEF 100 114 | 115 | #ifndef _FALSE 116 | 117 | #define _FALSE 0 118 | 119 | #endif 120 | 121 | #ifndef _TRUE 122 | 123 | #define _TRUE 1 124 | 125 | #endif 126 | 127 | /* ---------------------- By compiler ---------------------- */ 128 | #ifndef GetTime 129 | 130 | /* ---------------------- By compiler ---------------------- */ 131 | 132 | #ifdef __CODEVISIONAVR__ /* Check compiler */ 133 | 134 | #define GetTime() 0 135 | 136 | /* ------------------------------------------------------------------ */ 137 | 138 | #elif defined(__GNUC__) && !defined(USE_HAL_DRIVER) /* Check compiler */ 139 | 140 | #define GetTime() 0 141 | 142 | /* ------------------------------------------------------------------ */ 143 | 144 | #elif defined(USE_HAL_DRIVER) /* Check driver */ 145 | 146 | #define GetTime() HAL_GetTick() 147 | 148 | /* ------------------------------------------------------------------ */ 149 | 150 | #else 151 | #endif /* __CODEVISIONAVR__ */ 152 | /* ------------------------------------------------------------------ */ 153 | 154 | #endif 155 | 156 | /* --------------------------------------------------------- */ 157 | 158 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 159 | /* PID Mode */ 160 | typedef enum 161 | { 162 | 163 | _PID_MODE_MANUAL = 0, 164 | _PID_MODE_AUTOMATIC = 1 165 | 166 | }PIDMode_TypeDef; 167 | 168 | /* PID P On x */ 169 | typedef enum 170 | { 171 | 172 | _PID_P_ON_M = 0, /* Proportional on Measurement */ 173 | _PID_P_ON_E = 1 174 | 175 | }PIDPON_TypeDef; 176 | 177 | /* PID Control direction */ 178 | typedef enum 179 | { 180 | 181 | _PID_CD_DIRECT = 0, 182 | _PID_CD_REVERSE = 1 183 | 184 | }PIDCD_TypeDef; 185 | 186 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 187 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enum ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 188 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Struct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 189 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 190 | class PID 191 | { 192 | 193 | private: 194 | 195 | PIDPON_TypeDef _pOnE; 196 | PIDMode_TypeDef _inAuto; 197 | 198 | PIDPON_TypeDef _pOn; 199 | PIDCD_TypeDef _controllerDirection; 200 | 201 | uint32_t _lastTime; 202 | uint32_t _sampleTime; 203 | 204 | double _dispKp; 205 | double _dispKi; 206 | double _dispKd; 207 | 208 | double _kp; 209 | double _ki; 210 | double _kd; 211 | 212 | double *_myInput; 213 | double *_myOutput; 214 | double *_mySetpoint; 215 | 216 | double _outputSum; 217 | double _lastInput; 218 | 219 | double _outMin; 220 | double _outMax; 221 | 222 | public: 223 | 224 | /* :::::::::: Constructor :::::::::: */ 225 | PID(); 226 | PID(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); 227 | PID(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection); 228 | 229 | /* :::::::::::::: Init ::::::::::::: */ 230 | void Init(void); 231 | void Init(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); 232 | void Init(double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection); 233 | 234 | /* ::::::::::: Computing ::::::::::: */ 235 | uint8_t Compute(void); 236 | 237 | /* ::::::::::: PID Mode :::::::::::: */ 238 | void SetMode(PIDMode_TypeDef Mode); 239 | PIDMode_TypeDef GetMode(void); 240 | 241 | /* :::::::::: PID Limits ::::::::::: */ 242 | void SetOutputLimits(double Min, double Max); 243 | 244 | /* :::::::::: PID Tunings :::::::::: */ 245 | void SetTunings(double Kp, double Ki, double Kd); 246 | void SetTunings(double Kp, double Ki, double Kd, PIDPON_TypeDef POn); 247 | 248 | /* ::::::::: PID Direction ::::::::: */ 249 | void SetControllerDirection(PIDCD_TypeDef Direction); 250 | PIDCD_TypeDef GetDirection(void); 251 | 252 | /* ::::::::: PID Sampling :::::::::: */ 253 | void SetSampleTime(int32_t NewSampleTime); 254 | 255 | /* ::::::: Get Tunings Param ::::::: */ 256 | double GetKp(void); 257 | double GetKi(void); 258 | double GetKd(void); 259 | 260 | }; 261 | 262 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End of the program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 263 | 264 | #endif /* __PID_H_ */ 265 | -------------------------------------------------------------------------------- /PID (c version)/pid.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | ~ File : pid.h 4 | ~ Author : Majid Derhambakhsh 5 | ~ Version: V1.0.0 6 | ~ Created: 02/11/2021 03:43:00 AM 7 | ~ Brief : 8 | ~ Support: 9 | E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support) 10 | 11 | Github : https://github.com/Majid-Derhambakhsh 12 | ------------------------------------------------------------------------------ 13 | ~ Description: 14 | 15 | ~ Attention : 16 | 17 | ~ Changes : 18 | ------------------------------------------------------------------------------ 19 | */ 20 | 21 | #ifndef __PID_H_ 22 | #define __PID_H_ 23 | 24 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Include ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 25 | #include 26 | #include 27 | 28 | /* ------------------------------------------------------------------ */ 29 | 30 | #ifdef __CODEVISIONAVR__ /* Check compiler */ 31 | 32 | #pragma warn_unref_func- /* Disable 'unused function' warning */ 33 | 34 | /* ------------------------------------------------------------------ */ 35 | 36 | #elif defined(__GNUC__) && !defined(USE_HAL_DRIVER) /* Check compiler */ 37 | 38 | #pragma GCC diagnostic ignored "-Wunused-function" /* Disable 'unused function' warning */ 39 | 40 | /* ------------------------------------------------------------------ */ 41 | 42 | #elif defined(USE_HAL_DRIVER) /* Check driver */ 43 | 44 | #include "main.h" 45 | 46 | /* --------------- Check Mainstream series --------------- */ 47 | 48 | #ifdef STM32F0 49 | #include "stm32f0xx_hal.h" /* Import HAL library */ 50 | #elif defined(STM32F1) 51 | #include "stm32f1xx_hal.h" /* Import HAL library */ 52 | #elif defined(STM32F2) 53 | #include "stm32f2xx_hal.h" /* Import HAL library */ 54 | #elif defined(STM32F3) 55 | #include "stm32f3xx_hal.h" /* Import HAL library */ 56 | #elif defined(STM32F4) 57 | #include "stm32f4xx_hal.h" /* Import HAL library */ 58 | #elif defined(STM32F7) 59 | #include "stm32f7xx_hal.h" /* Import HAL library */ 60 | #elif defined(STM32G0) 61 | #include "stm32g0xx_hal.h" /* Import HAL library */ 62 | #elif defined(STM32G4) 63 | #include "stm32g4xx_hal.h" /* Import HAL library */ 64 | 65 | /* ------------ Check High Performance series ------------ */ 66 | 67 | #elif defined(STM32H7) 68 | #include "stm32h7xx_hal.h" /* Import HAL library */ 69 | 70 | /* ------------ Check Ultra low power series ------------- */ 71 | 72 | #elif defined(STM32L0) 73 | #include "stm32l0xx_hal.h" /* Import HAL library */ 74 | #elif defined(STM32L1) 75 | #include "stm32l1xx_hal.h" /* Import HAL library */ 76 | #elif defined(STM32L5) 77 | #include "stm32l5xx_hal.h" /* Import HAL library */ 78 | #elif defined(STM32L4) 79 | #include "stm32l4xx_hal.h" /* Import HAL library */ 80 | #elif defined(STM32H7) 81 | #include "stm32h7xx_hal.h" /* Import HAL library */ 82 | #else 83 | #endif /* STM32F1 */ 84 | 85 | /* ------------------------------------------------------- */ 86 | 87 | #if defined ( __ICCARM__ ) /* ICCARM Compiler */ 88 | 89 | #pragma diag_suppress=Pe177 /* Disable 'unused function' warning */ 90 | 91 | #elif defined ( __GNUC__ ) /* GNU Compiler */ 92 | 93 | #pragma diag_suppress 177 /* Disable 'unused function' warning */ 94 | 95 | #endif /* __ICCARM__ */ 96 | 97 | /* ------------------------------------------------------------------ */ 98 | 99 | #else /* Compiler not found */ 100 | 101 | #error Chip or Library not supported /* Send error */ 102 | 103 | #endif /* __CODEVISIONAVR__ */ 104 | 105 | /* ------------------------------------------------------------------ */ 106 | 107 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Defines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 108 | /* ------------------------ Library ------------------------ */ 109 | #define _PID_LIBRARY_VERSION 1.0.0 110 | 111 | /* ------------------------ Public ------------------------- */ 112 | #define _PID_8BIT_PWM_MAX UINT8_MAX 113 | #define _PID_SAMPLE_TIME_MS_DEF 100 114 | 115 | #ifndef _FALSE 116 | 117 | #define _FALSE 0 118 | 119 | #endif 120 | 121 | #ifndef _TRUE 122 | 123 | #define _TRUE 1 124 | 125 | #endif 126 | 127 | /* ---------------------- By compiler ---------------------- */ 128 | #ifndef GetTime 129 | 130 | /* ---------------------- By compiler ---------------------- */ 131 | 132 | #ifdef __CODEVISIONAVR__ /* Check compiler */ 133 | 134 | #define GetTime() 0 135 | 136 | /* ------------------------------------------------------------------ */ 137 | 138 | #elif defined(__GNUC__) && !defined(USE_HAL_DRIVER) /* Check compiler */ 139 | 140 | #define GetTime() 0 141 | 142 | /* ------------------------------------------------------------------ */ 143 | 144 | #elif defined(USE_HAL_DRIVER) /* Check driver */ 145 | 146 | #define GetTime() HAL_GetTick() 147 | 148 | /* ------------------------------------------------------------------ */ 149 | 150 | #else 151 | #endif /* __CODEVISIONAVR__ */ 152 | /* ------------------------------------------------------------------ */ 153 | 154 | #endif 155 | 156 | /* --------------------------------------------------------- */ 157 | 158 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 159 | /* PID Mode */ 160 | typedef enum 161 | { 162 | 163 | _PID_MODE_MANUAL = 0, 164 | _PID_MODE_AUTOMATIC = 1 165 | 166 | }PIDMode_TypeDef; 167 | 168 | /* PID P On x */ 169 | typedef enum 170 | { 171 | 172 | _PID_P_ON_M = 0, /* Proportional on Measurement */ 173 | _PID_P_ON_E = 1 174 | 175 | }PIDPON_TypeDef; 176 | 177 | /* PID Control direction */ 178 | typedef enum 179 | { 180 | 181 | _PID_CD_DIRECT = 0, 182 | _PID_CD_REVERSE = 1 183 | 184 | }PIDCD_TypeDef; 185 | 186 | /* PID Structure */ 187 | typedef struct 188 | { 189 | 190 | PIDPON_TypeDef POnE; 191 | PIDMode_TypeDef InAuto; 192 | 193 | PIDPON_TypeDef POn; 194 | PIDCD_TypeDef ControllerDirection; 195 | 196 | uint32_t LastTime; 197 | uint32_t SampleTime; 198 | 199 | double DispKp; 200 | double DispKi; 201 | double DispKd; 202 | 203 | double Kp; 204 | double Ki; 205 | double Kd; 206 | 207 | double *MyInput; 208 | double *MyOutput; 209 | double *MySetpoint; 210 | 211 | double OutputSum; 212 | double LastInput; 213 | 214 | double OutMin; 215 | double OutMax; 216 | 217 | }PID_TypeDef; 218 | 219 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 220 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enum ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 221 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Struct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 222 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 223 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prototype ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 224 | /* :::::::::::::: Init ::::::::::::: */ 225 | void PID_Init(PID_TypeDef *uPID); 226 | 227 | void PID(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); 228 | void PID2(PID_TypeDef *uPID, double *Input, double *Output, double *Setpoint, double Kp, double Ki, double Kd, PIDCD_TypeDef ControllerDirection); 229 | 230 | /* ::::::::::: Computing ::::::::::: */ 231 | uint8_t PID_Compute(PID_TypeDef *uPID); 232 | 233 | /* ::::::::::: PID Mode :::::::::::: */ 234 | void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode); 235 | PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID); 236 | 237 | /* :::::::::: PID Limits ::::::::::: */ 238 | void PID_SetOutputLimits(PID_TypeDef *uPID, double Min, double Max); 239 | 240 | /* :::::::::: PID Tunings :::::::::: */ 241 | void PID_SetTunings(PID_TypeDef *uPID, double Kp, double Ki, double Kd); 242 | void PID_SetTunings2(PID_TypeDef *uPID, double Kp, double Ki, double Kd, PIDPON_TypeDef POn); 243 | 244 | /* ::::::::: PID Direction ::::::::: */ 245 | void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction); 246 | PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID); 247 | 248 | /* ::::::::: PID Sampling :::::::::: */ 249 | void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime); 250 | 251 | /* ::::::: Get Tunings Param ::::::: */ 252 | double PID_GetKp(PID_TypeDef *uPID); 253 | double PID_GetKi(PID_TypeDef *uPID); 254 | double PID_GetKd(PID_TypeDef *uPID); 255 | 256 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End of the program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 257 | 258 | #endif /* __PID_H_ */ 259 | --------------------------------------------------------------------------------