initial commit

This commit is contained in:
bmy
2024-04-25 22:31:01 +08:00
commit 200b5703f9
119 changed files with 52620 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Majid Derhambakhsh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,164 @@
![Banner](Banner.png)
# PID-Library (C Version)
PID Controller library for ARM Cortex M (STM32)
> #### Download Arduino Library : [Arduino-PID-Library](https://github.com/br3ttb/Arduino-PID-Library)
## Release
- #### Version : 1.0.0
- #### Type : Embedded Software.
- #### Support :
- ARM STM32 series
- #### Program Language : C/C++
- #### Properties :
- #### Changes :
- #### Required Library/Driver :
## Overview
### Initialization and de-initialization functions:
```c++
void PID(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection);
void PID2(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDCD_TypeDef ControllerDirection);
```
### Operation functions:
```c++
/* ::::::::::: Computing ::::::::::: */
uint8_t PID_Compute(PID_TypeDef *uPID);
/* ::::::::::: PID Mode :::::::::::: */
void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode);
PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID);
/* :::::::::: PID Limits ::::::::::: */
void PID_SetOutputLimits(PID_TypeDef *uPID, float Min, float Max);
/* :::::::::: PID Tunings :::::::::: */
void PID_SetTunings(PID_TypeDef *uPID, float Kp, float Ki, float Kd);
void PID_SetTunings2(PID_TypeDef *uPID, float Kp, float Ki, float Kd, PIDPON_TypeDef POn);
/* ::::::::: PID Direction ::::::::: */
void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction);
PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID);
/* ::::::::: PID Sampling :::::::::: */
void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime);
/* ::::::: Get Tunings Param ::::::: */
float PID_GetKp(PID_TypeDef *uPID);
float PID_GetKi(PID_TypeDef *uPID);
float PID_GetKd(PID_TypeDef *uPID);
```
### Macros:
```diff
non
```
## Guide
#### This library can be used as follows:
#### 1. Add pid.h header
#### 2. Create PID struct and initialize it, for example:
* Initializer:
```c++
PID(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection);
```
* Parameters:
* uPID : Pointer to pid struct
* Input : The variable we're trying to control (float)
* Output : The variable that will be adjusted by the pid (float)
* Setpoint : The value we want to Input to maintain (float)
* Kp,Ki,Kd : Tuning Parameters. these affect how the pid will change the output (float>=0)
* POn : Either P_ON_E (Default) or P_ON_M. Allows Proportional on Measurement to be specified.
* ControllerDirection : Either DIRECT or REVERSE. determines which direction the output will move when faced with a given error. DIRECT is most common
* Example:
```c++
PID_TypeDef TPID;
float Temp, PIDOut, TempSetpoint;
PID(&TPID, &Temp, &PIDOut, &TempSetpoint, 2, 5, 1, _PID_P_ON_E, _PID_CD_DIRECT);
```
#### 3. Set 'mode', 'sample time' and 'output limit', for example:
* Functions:
```c++
void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode);
void PID_SetOutputLimits(PID_TypeDef *uPID, float Min, float Max);
void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime);
```
* Parameters:
* uPID : Pointer to pid struct
* Mode : _PID_MODE_AUTOMATIC or _PID_MODE_MANUAL
* Min : Low end of the range. must be < max (float)
* Max : High end of the range. must be > min (float)
* NewSampleTime : How often, in milliseconds, the PID will be evaluated. (int>0)
* Example:
```c++
PID_SetMode(&TPID, _PID_MODE_AUTOMATIC);
PID_SetSampleTime(&TPID, 500);
PID_SetOutputLimits(&TPID, 1, 100);
```
#### 4. Using Compute function, for example:
```c++
PID_Compute(&TPID);
```
## Examples
#### Example 1: PID Compute for temperature
```c++
#include "main.h"
#include "pid.h"
PID_TypeDef TPID;
char OutBuf[50];
float Temp, PIDOut, TempSetpoint;
int main(void)
{
HW_Init();
PID(&TPID, &Temp, &PIDOut, &TempSetpoint, 2, 5, 1, _PID_P_ON_E, _PID_CD_DIRECT);
PID_SetMode(&TPID, _PID_MODE_AUTOMATIC);
PID_SetSampleTime(&TPID, 500);
PID_SetOutputLimits(&TPID, 1, 100);
while (1)
{
Temp = GetTemp();
PID_Compute(&TPID);
sprintf(OutBuf, "Temp%3.2f : %u\n", Temp, (uint16_t)PIDOut);
UART_Transmit((uint8_t *)OutBuf, strlen(OutBuf));
Delay_ms(500);
}
}
```
## Tests performed:
- [x] Run on STM32 Fx cores
## Developers:
- ### Majid Derhambakhsh

292
3rd-part/PID-Library/pid.c Normal file
View File

@@ -0,0 +1,292 @@
 /*
------------------------------------------------------------------------------
~ File : pid.c
~ Author : Majid Derhambakhsh
~ Version: V1.0.0
~ Created: 02/11/2021 03:43:00 AM
~ Brief :
~ Support:
E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support)
Github : https://github.com/Majid-Derhambakhsh
------------------------------------------------------------------------------
~ Description:
~ Attention :
~ Changes :
------------------------------------------------------------------------------
*/
#include "pid.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~ Initialize ~~~~~~~~~~~~~~~~ */
void PID_Init(PID_TypeDef *uPID)
{
/* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */
uPID->OutputSum = *uPID->MyOutput;
uPID->LastInput = *uPID->MyInput;
if (uPID->OutputSum > uPID->OutMax)
{
uPID->OutputSum = uPID->OutMax;
}
else if (uPID->OutputSum < uPID->OutMin)
{
uPID->OutputSum = uPID->OutMin;
}
}
void PID(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection)
{
/* ~~~~~~~~~~ Set parameter ~~~~~~~~~~ */
uPID->MyOutput = Output;
uPID->MyInput = Input;
uPID->MySetpoint = Setpoint;
uPID->InAuto = (PIDMode_TypeDef)_FALSE;
PID_SetOutputLimits(uPID, 0, _PID_8BIT_PWM_MAX);
uPID->SampleTime = _PID_SAMPLE_TIME_MS_DEF; /* default Controller Sample Time is 0.1 seconds */
PID_SetControllerDirection(uPID, ControllerDirection);
PID_SetTunings2(uPID, Kp, Ki, Kd, POn);
}
void PID2(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDCD_TypeDef ControllerDirection)
{
PID(uPID, Input, Output, Setpoint, Kp, Ki, Kd, _PID_P_ON_E, ControllerDirection);
}
/* ~~~~~~~~~~~~~~~~~ Computing ~~~~~~~~~~~~~~~~~ */
uint8_t PID_Compute(PID_TypeDef *uPID)
{
float input=0;
float error=0;
float dInput=0;
float output=0;
/* ~~~~~~~~~~ Check PID mode ~~~~~~~~~~ */
if (!uPID->InAuto)
{
return _FALSE;
}
/* ..... Compute all the working error variables ..... */
input = *uPID->MyInput;
error = *uPID->MySetpoint - input;
dInput = (input - uPID->LastInput);
uPID->OutputSum += (uPID->Ki * error);
/* ..... Add Proportional on Measurement, if P_ON_M is specified ..... */
if (!uPID->POnE)
{
uPID->OutputSum -= uPID->Kp * dInput;
}
if (uPID->OutputSum > uPID->OutMax)
{
uPID->OutputSum = uPID->OutMax;
}
else if (uPID->OutputSum < uPID->OutMin)
{
uPID->OutputSum = uPID->OutMin;
}
else { }
/* ..... Add Proportional on Error, if P_ON_E is specified ..... */
if (uPID->POnE)
{
output = uPID->Kp * error;
}
else
{
output = 0;
}
/* ..... Compute Rest of PID Output ..... */
output += uPID->OutputSum - uPID->Kd * dInput;
if (output > uPID->OutMax)
{
output = uPID->OutMax;
}
else if (output < uPID->OutMin)
{
output = uPID->OutMin;
}
else { }
*uPID->MyOutput = output;
/* ..... Remember some variables for next time ..... */
uPID->LastInput = input;
return _TRUE;
}
/* ~~~~~~~~~~~~~~~~~ PID Mode ~~~~~~~~~~~~~~~~~~ */
void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode)
{
uint8_t newAuto = (Mode == _PID_MODE_AUTOMATIC);
/* ~~~~~~~~~~ Initialize the PID ~~~~~~~~~~ */
if (newAuto && !uPID->InAuto)
{
PID_Init(uPID);
}
uPID->InAuto = (PIDMode_TypeDef)newAuto;
}
PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID)
{
return uPID->InAuto ? _PID_MODE_AUTOMATIC : _PID_MODE_MANUAL;
}
/* ~~~~~~~~~~~~~~~~ PID Limits ~~~~~~~~~~~~~~~~~ */
void PID_SetOutputLimits(PID_TypeDef *uPID, float Min, float Max)
{
/* ~~~~~~~~~~ Check value ~~~~~~~~~~ */
if (Min >= Max)
{
return;
}
uPID->OutMin = Min;
uPID->OutMax = Max;
/* ~~~~~~~~~~ Check PID Mode ~~~~~~~~~~ */
if (uPID->InAuto)
{
/* ..... Check out value ..... */
if (*uPID->MyOutput > uPID->OutMax)
{
*uPID->MyOutput = uPID->OutMax;
}
else if (*uPID->MyOutput < uPID->OutMin)
{
*uPID->MyOutput = uPID->OutMin;
}
else { }
/* ..... Check out value ..... */
if (uPID->OutputSum > uPID->OutMax)
{
uPID->OutputSum = uPID->OutMax;
}
else if (uPID->OutputSum < uPID->OutMin)
{
uPID->OutputSum = uPID->OutMin;
}
else { }
}
}
/* ~~~~~~~~~~~~~~~~ PID Tunings ~~~~~~~~~~~~~~~~ */
void PID_SetTunings(PID_TypeDef *uPID, float Kp, float Ki, float Kd)
{
PID_SetTunings2(uPID, Kp, Ki, Kd, uPID->POn);
}
void PID_SetTunings2(PID_TypeDef *uPID, float Kp, float Ki, float Kd, PIDPON_TypeDef POn)
{
float SampleTimeInSec;
/* ~~~~~~~~~~ Check value ~~~~~~~~~~ */
if (Kp < 0 || Ki < 0 || Kd < 0)
{
return;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
uPID->POn = POn;
uPID->POnE = (PIDPON_TypeDef)(POn == _PID_P_ON_E);
uPID->DispKp = Kp;
uPID->DispKi = Ki;
uPID->DispKd = Kd;
/* ~~~~~~~~~ Calculate time ~~~~~~~~ */
SampleTimeInSec = ((float)uPID->SampleTime) / 1000;
uPID->Kp = Kp;
uPID->Ki = Ki * SampleTimeInSec;
uPID->Kd = Kd / SampleTimeInSec;
/* ~~~~~~~~ Check direction ~~~~~~~~ */
if (uPID->ControllerDirection == _PID_CD_REVERSE)
{
uPID->Kp = (0 - uPID->Kp);
uPID->Ki = (0 - uPID->Ki);
uPID->Kd = (0 - uPID->Kd);
}
}
/* ~~~~~~~~~~~~~~~ PID Direction ~~~~~~~~~~~~~~~ */
void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction)
{
/* ~~~~~~~~~~ Check parameters ~~~~~~~~~~ */
if ((uPID->InAuto) && (Direction !=uPID->ControllerDirection))
{
uPID->Kp = (0 - uPID->Kp);
uPID->Ki = (0 - uPID->Ki);
uPID->Kd = (0 - uPID->Kd);
}
uPID->ControllerDirection = Direction;
}
PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID)
{
return uPID->ControllerDirection;
}
/* ~~~~~~~~~~~~~~~ PID Sampling ~~~~~~~~~~~~~~~~ */
void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime)
{
float ratio;
/* ~~~~~~~~~~ Check value ~~~~~~~~~~ */
if (NewSampleTime > 0)
{
ratio = (float)NewSampleTime / (float)uPID->SampleTime;
uPID->Ki *= ratio;
uPID->Kd /= ratio;
uPID->SampleTime = (uint32_t)NewSampleTime;
}
}
/* ~~~~~~~~~~~~~ Get Tunings Param ~~~~~~~~~~~~~ */
float PID_GetKp(PID_TypeDef *uPID)
{
return uPID->DispKp;
}
float PID_GetKi(PID_TypeDef *uPID)
{
return uPID->DispKi;
}
float PID_GetKd(PID_TypeDef *uPID)
{
return uPID->DispKd;
}

175
3rd-part/PID-Library/pid.h Normal file
View File

@@ -0,0 +1,175 @@
/*
------------------------------------------------------------------------------
~ File : pid.h
~ Author : Majid Derhambakhsh
~ Version: V1.0.0
~ Created: 02/11/2021 03:43:00 AM
~ Brief :
~ Support:
E-Mail : Majid.do16@gmail.com (subject : Embedded Library Support)
Github : https://github.com/Majid-Derhambakhsh
------------------------------------------------------------------------------
~ Description:
~ Attention :
~ Changes :
------------------------------------------------------------------------------
*/
#ifndef __PID_H_
#define __PID_H_
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Include ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
#include <stdint.h>
#include <string.h>
// #include "zf_common_headfile.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Defines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ------------------------ Library ------------------------ */
#define _PID_LIBRARY_VERSION 1.0.0
/* ------------------------ Public ------------------------- */
#define _PID_8BIT_PWM_MAX UINT8_MAX
#define _PID_SAMPLE_TIME_MS_DEF 100
#ifndef _FALSE
#define _FALSE 0
#endif
#ifndef _TRUE
#define _TRUE 1
#endif
/* ---------------------- By compiler ---------------------- */
#ifndef GetTime
/* ---------------------- By compiler ---------------------- */
#ifdef __CODEVISIONAVR__ /* Check compiler */
#define GetTime() 0
/* ------------------------------------------------------------------ */
#elif defined(__GNUC__) /* Check compiler */
#define GetTime() 0
/* ------------------------------------------------------------------ */
#else
#endif /* __CODEVISIONAVR__ */
/* ------------------------------------------------------------------ */
#endif
/* --------------------------------------------------------- */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* PID Mode */
typedef enum
{
_PID_MODE_MANUAL = 0,
_PID_MODE_AUTOMATIC = 1
}PIDMode_TypeDef;
/* PID P On x */
typedef enum
{
_PID_P_ON_M = 0, /* Proportional on Measurement */
_PID_P_ON_E = 1
}PIDPON_TypeDef;
/* PID Control direction */
typedef enum
{
_PID_CD_DIRECT = 0,
_PID_CD_REVERSE = 1
}PIDCD_TypeDef;
/* PID Structure */
typedef struct
{
PIDPON_TypeDef POnE;
PIDMode_TypeDef InAuto;
PIDPON_TypeDef POn;
PIDCD_TypeDef ControllerDirection;
uint32_t LastTime;
uint32_t SampleTime;
float DispKp;
float DispKi;
float DispKd;
float Kp;
float Ki;
float Kd;
float *MyInput;
float *MyOutput;
float *MySetpoint;
float OutputSum;
float LastInput;
float OutMin;
float OutMax;
}PID_TypeDef;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enum ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Struct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prototype ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* :::::::::::::: Init ::::::::::::: */
void PID_Init(PID_TypeDef *uPID);
void PID(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection);
void PID2(PID_TypeDef *uPID, float *Input, float *Output, float *Setpoint, float Kp, float Ki, float Kd, PIDCD_TypeDef ControllerDirection);
/* ::::::::::: Computing ::::::::::: */
uint8_t PID_Compute(PID_TypeDef *uPID);
/* ::::::::::: PID Mode :::::::::::: */
void PID_SetMode(PID_TypeDef *uPID, PIDMode_TypeDef Mode);
PIDMode_TypeDef PID_GetMode(PID_TypeDef *uPID);
/* :::::::::: PID Limits ::::::::::: */
void PID_SetOutputLimits(PID_TypeDef *uPID, float Min, float Max);
/* :::::::::: PID Tunings :::::::::: */
void PID_SetTunings(PID_TypeDef *uPID, float Kp, float Ki, float Kd);
void PID_SetTunings2(PID_TypeDef *uPID, float Kp, float Ki, float Kd, PIDPON_TypeDef POn);
/* ::::::::: PID Direction ::::::::: */
void PID_SetControllerDirection(PID_TypeDef *uPID, PIDCD_TypeDef Direction);
PIDCD_TypeDef PID_GetDirection(PID_TypeDef *uPID);
/* ::::::::: PID Sampling :::::::::: */
void PID_SetSampleTime(PID_TypeDef *uPID, int32_t NewSampleTime);
/* ::::::: Get Tunings Param ::::::: */
float PID_GetKp(PID_TypeDef *uPID);
float PID_GetKi(PID_TypeDef *uPID);
float PID_GetKd(PID_TypeDef *uPID);
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End of the program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
#endif /* __PID_H_ */