我在写stm32直流有刷电机调速程序时,电机速度总是顶到最高转速。我移植的野火的程序,在pid调试助手上显示目标值与实际值相差很大,但pid并没有产生作用,始终运行在满转速状态下。
小助手输出结果如下(截取部分,pid参数为 0.5,0.5,0.5)
PID调试数据
通道 1 数据如下:
序号,实际值,目标值,差值
5,0,0,0
6,0,0,0
7,0,0,0
8,0,0,0
9,0,0,0
417,0,200,-200
418,0,200,-200
419,106,200,-94
420,294,200,94
421,302,200,102
422,128,200,-72
423,123,200,-77
424,305,200,105
425,277,200,77
426,84,200,-116
427,98,200,-102
428,288,200,88
429,308,200,108
430,126,200,-74
431,117,200,-83
432,299,200,99
433,282,200,82
434,84,200,-116
435,92,200,-108
436,285,200,85
437,308,200,108
438,140,200,-60
439,123,200,-77
440,308,200,108
441,274,200,74
442,64,200,-136
443,84,200,-116
444,280,200,80
445,324,200,124
446,156,200,-44
447,134,200,-66
448,316,200,116
449,266,200,66
450,-183529,200,-183729
451,64,200,-136
452,266,200,66
453,411,200,211
454,515,200,315
455,596,200,396
456,652,200,452
457,694,200,494
458,725,200,525
459,753,200,553
460,773,200,573
461,789,200,589
462,803,200,603
463,812,200,612
464,823,200,623
465,829,200,629
466,831,200,631
467,837,200,637
468,837,200,637
469,840,200,640
470,840,200,640
471,843,200,643
472,843,200,643
733,854,200,654
734,848,200,648
735,689,200,489
736,392,200,192
737,226,200,26
738,294,200,94
739,403,200,203
740,288,200,88
741,67,200,-133
742,89,200,-111
743,285,200,85
744,347,200,147
745,193,200,-7
746,117,200,-83
747,266,200,66
748,296,200,96
749,126,200,-74
750,106,200,-94
751,296,200,96
752,277,200,77
753,78,200,-122
754,84,200,-116
755,280,200,80
756,316,200,116
757,148,200,-52
758,131,200,-69
759,316,200,116
760,268,200,68
761,-183529,200,-183729
762,64,200,-136
763,266,200,66
764,411,200,211
765,526,200,326
766,602,200,402
767,658,200,458
768,705,200,505
769,733,200,533
770,761,200,561
771,784,200,584
772,803,200,603
773,815,200,615
774,823,200,623
代码如下
//pid实现
float PID_realize(float actual_val)
{
/* 计算偏差:目标值减去实际值 */
pid.err = pid.target_val - actual_val;
/* 积分项更新,加上限幅 */
pid.integral += pid.err;
/* PID输出计算 */
pid.actual_val = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * (pid.err - pid.err_last);
/* 保存上一次的偏差,用于微分项 */
pid.err_last = pid.err;
/* 返回计算出的控制量 */
return pid.actual_val;
}
//电机控制部分
#define c 1071.0f //电机转 一圈的编码值
#define t 0.02f //定时器定时
void motor_pid_control(void)
{
if (is_motor_en == 1)
{
static float cont_val = 0;
static __IO int32_t Capture_Count = 0;
int32_t actual_speed = 0;
Capture_Count = __HAL_TIM_GET_COUNTER(&htim2);
__HAL_TIM_SET_COUNTER(&htim2,0);
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2))
Capture_Count=-65535+Capture_Count;
actual_speed = (int32_t)(((float)(Capture_Count) / c / t)*60.0f);
cont_val = PID_realize((float)actual_speed);
if (cont_val > 0)
{
motor_forward();
}
else
{
cont_val = -cont_val;
motor_backward();
}
cont_val = (cont_val > 500) ? 500 : cont_val;
motor_set_speed(cont_val);
set_computer_value(SEND_FACT_CMD, CURVES_CH1, &actual_speed , 1); // ¸øͨµÀ 1 ·¢ËÍʵ¼ÊÖµ
}
}