Last active
January 2, 2016 15:39
-
-
Save saxbophone/ba13b1347bb21906fc0d to your computer and use it in GitHub Desktop.
My own attempt at implementing the PID algorithm in some (hopefully) clean, understandable C
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
/* | |
* PID Controller Implementation in C | |
* | |
* Created by Joshua Saxby (aka @saxbophone) on 1 Jan, 2016 | |
* | |
* My own attempt at implementing the PID algorithm in some (hopefully) clean, understandable C. | |
* No warranty, no patenting (LOL!), free use, yadda yadda etc, hope you find this useful and don't be evil! | |
*/ | |
#include <stdio.h> | |
#include "pid.c" | |
int main(int argc, char const *argv[]) { | |
/* | |
* DEMO MAIN FUNCTION JUST TO TEST THAT THIS WORKS! | |
*/ | |
static short true = 1; | |
// initialise a calibration for our PID controller | |
PID_Calibration calibration; | |
// dummy values | |
calibration.kp = 1.0; | |
calibration.ki = 1.0; | |
calibration.kd = 1.0; | |
// initialise the starting state of the controller | |
PID_State current_state; | |
// we need to populate all fields apart from output, as this one gets populated by the algorithm | |
// set all variables to neutral values | |
current_state.actual = 0.0; | |
current_state.target = 0.0; | |
current_state.time_delta = 1.0; // AFIAK this will make timing have no effect... | |
current_state.previous_error = 0.0; // no errors yet | |
current_state.integral = 0.0; // no errors yet | |
// get target value from user | |
printf("Enter Target Value:\t"); | |
scanf("%lf", ¤t_state.target); | |
// do several iterations of the algorithm | |
while (true) { | |
// get actual value from user | |
printf("Enter Actual Value:\t"); | |
scanf("%lf", ¤t_state.actual); | |
// run the algorithm | |
current_state = pid_iterate(calibration, current_state); | |
// output results for info | |
printf( | |
"Actual:\t%lf\tTarget:\t%lf\tOutput:\t%lf\n", | |
current_state.actual, current_state.target, current_state.output | |
); | |
} | |
return 0; | |
} |
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
/* | |
* PID Controller Implementation in C | |
* | |
* Created by Joshua Saxby (aka @saxbophone) on 1 Jan, 2016 | |
* | |
* My own attempt at implementing the PID algorithm in some (hopefully) clean, understandable C. | |
* No warranty, no patenting (LOL!), free use, yadda yadda etc, hope you find this useful and don't be evil! | |
*/ | |
typedef struct { | |
/* | |
* struct PID_Calibration | |
* | |
* Struct storing calibrated PID constants for a PID Controller | |
* These are used for tuning the algorithm and the values they take are | |
* dependent upon the application - (in other words, YMMV...) | |
*/ | |
double kp; // Proportional gain | |
double ki; // Integral gain | |
double kd; // Derivative gain | |
} PID_Calibration; | |
typedef struct { | |
/* | |
* struct PID_State | |
* | |
* Struct storing the current state of a PID Controller. | |
* This is used as the input value to the PID algorithm function, which also | |
* returns a PID_State struct reflecting the adjustments suggested by the algorithm. | |
* | |
* NOTE: The output field in this struct is set by the PID algorithm function, and | |
* is ignored in the actual calculations. | |
*/ | |
double actual; // The actual reading as measured | |
double target; // The desired reading | |
double time_delta; // Time since last sample/calculation - should be set when updating state | |
// The previously calculated error between actual and target (zero initially) | |
double previous_error; | |
double integral; // Sum of integral error over time | |
double output; // the modified output value calculated by the algorithm, to compensate for error | |
} PID_State; | |
PID_State pid_iterate(PID_Calibration calibration, PID_State state) { | |
/* | |
* PID Controller Algorithm implementation | |
* | |
* Given a PID calibration for the P, I and D values and a PID_State for the current | |
* state of the PID controller, calculate the new state for the PID Controller and set | |
* the output state to compensate for any error as defined by the algorithm | |
*/ | |
// calculate difference between desired and actual values (the error) | |
double error = state.target - state.actual; | |
// calculate and update integral | |
state.integral += (error * state.time_delta); | |
// calculate derivative | |
double derivative = (error - state.previous_error) / state.time_delta; | |
// calculate output value according to algorithm | |
state.output = ( | |
(calibration.kp * error) + (calibration.ki * state.integral) + (calibration.kd * derivative) | |
); | |
// update state.previous_error to the error value calculated on this iteration | |
state.previous_error = error; | |
// return the state struct reflecting the calculations | |
return state; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment