PID控制C源程序,可以参考一下
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 121 122 123 124 125 126 127 128 129 130 131 132 133 | struct _pid { int pv; /*integer that contains the process value*/ int sp; /*integer that contains the set point*/ float integral; float pgain; float igain; float dgain; int deadband; int last_error; }; struct _pid warm, *pid; int process_point, set_point, dead_band; float p_gain, i_gain, d_gain, integral_val, new_integ;; /*------------------------------------------------------------------------ pid_init DESCRIPTION This function initializes the pointers in the _pid structure to the process variable and the setpoint. *pv and *sp are integer pointers. ------------------------------------------------------------------------*/ void pid_init( struct _pid *warm, int process_point, int set_point) { struct _pid *pid; pid = warm; pid->pv = process_point; pid->sp = set_point; } /*------------------------------------------------------------------------ pid_tune DESCRIPTION Sets the proportional gain (p_gain), integral gain (i_gain), derivitive gain (d_gain), and the dead band (dead_band) of a pid control structure _pid. ------------------------------------------------------------------------*/ void pid_tune( struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band) { pid->pgain = p_gain; pid->igain = i_gain; pid->dgain = d_gain; pid->deadband = dead_band; pid->integral = integral_val; pid->last_error = 0; } /*------------------------------------------------------------------------ pid_setinteg DESCRIPTION Set a new value for the integral term of the pid equation. This is useful for setting the initial output of the pid controller at start up. ------------------------------------------------------------------------*/ void pid_setinteg( struct _pid *pid, float new_integ) { pid->integral = new_integ; pid->last_error = 0; } /*------------------------------------------------------------------------ pid_bumpless DESCRIPTION Bumpless transfer algorithim. When suddenly changing setpoints, or when restarting the PID equation after an extended pause, the derivative of the equation can cause a bump in the controller output. This function will help smooth out that bump. The process value in *pv should be the updated just before this function is used. ------------------------------------------------------------------------*/ void pid_bumpless( struct _pid *pid) { pid->last_error = (pid->sp) - (pid->pv); } /*------------------------------------------------------------------------ pid_calc DESCRIPTION Performs PID calculations for the _pid structure *a. This function uses the positional form of the pid equation, and incorporates an integral windup prevention algorithim. Rectangular integration is used, so this function must be repeated on a consistent time basis for accurate control. RETURN VALUE The new output value for the pid loop. USAGE #include "control.h"*/ float pid_calc( struct _pid *pid) { int err; float pterm, dterm, result, ferror ; err = (pid->sp) - (pid->pv); if ( abs (err) > pid->deadband) { ferror = ( float ) err; /*do integer to float conversion only once*/ pterm = pid->pgain * ferror ; if (pterm > 100 || pterm < -100) { pid->integral = 0.0; } else { pid->integral += pid->igain * ferror ; if (pid->integral > 100.0) { pid->integral = 100.0; } else if (pid->integral < 0.0) { pid->integral = 0.0; } } dterm = (( float )(err - pid->last_error)) * pid->dgain; result = pterm + pid->integral + dterm; } else { result = pid->integral; } pid->last_error = err; return (result); } void main( void ) { float display_value; int count = 0; pid = &warm; // printf("Enter the values of Process point, Set point, P gain, I gain, D gain \n"); // scanf("%d%d%f%f%f", &process_point, &set_point, &p_gain, &i_gain, &d_gain); process_point = 30; set_point = 40; p_gain = ( float )(5.2); i_gain = ( float )(0.77); d_gain = ( float )(0.18); dead_band = 2; integral_val = ( float )(0.01); printf ( "The values of Process point, Set point, P gain, I gain, D gain \n" ); printf ( " %6d %6d %4f %4f %4f\n" , process_point, set_point, p_gain, i_gain, d_gain); printf ( "Enter the values of Process point\n" ); while (count <= 20) { scanf ( "%d" , &process_point); pid_init(&warm, process_point, set_point); pid_tune(&warm, p_gain, i_gain, d_gain, dead_band); pid_setinteg(&warm, 0.0); //pid_setinteg(&warm,30.0); //Get input value for process point pid_bumpless(&warm); // how to display output display_value = pid_calc(&warm); printf ( "%f\n" , display_value); //printf("\n%f%f%f%f",warm.pv,warm.sp,warm.igain,warm.dgain); count++; } } |