pid-max设置多少合适之原理

本文揭示了PID_MAX内核参数的误解,它不仅受CPU核心数影响,还取决于long类型字节大小。当配置不同,其默认最大值可在32768至4194304之间变化,理解这一概念对于系统优化至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前我读源码可能不仔细,“当时认为主机内核的pid-max是不需要修改的,因为已经是最大值了,这个值改大了也没有用,和主机的cpu物理核数有关,这个值是系统在开机的时候会帮我们设置成最大值。因为每核最大值是1024,比如我们32核的机器就是1024*32,也就是系统会设置成32768,40核机器就是40960,所以不需要修改,改小可以,改大改了也没有效果。”

但是,

刚仔细看了下代码,这个要看long字节大小 ,也就是操作系统版本,如果long是大于4字节的,就可以到2^22

/*
 * This controls the default maximum pid allocated to a process
 * 大致意思就是,如果在编译内核时指定或者为CONFIG_BASE_SMALl赋值了,那么默认值就是4096,反而就是32768
 */
#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)

/*
 * A maximum of 4 million PIDs should be enough for a while.
 * [NOTE: PID/TIDs are limited to 2^30 ~= 1 billion, see FUTEX_TID_MASK.] 
 * 如果CONFIG_BASE_SMALL被赋值了,则最大值就是32768,如果条件不成立,则判断long的类型通常应该是操作系统版本,
 * 如果大于4字节,取值范围大约就是4 million,精确计算就是4,194,304,如果条件还不成立则只能取值最被设置的PID_MAX_DEFAULT的值
 */

#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
    (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
float Speed_Low_Filter(float new_Spe,encoder_t *encoder) { float sum = 0.0f; uint32_t test_Speed = new_Spe; for(uint8_t i=SPEED_RECORD_NUM-1;i>0;i--) { encoder->speed_Record[i] = encoder->speed_Record[i-1]; sum += encoder->speed_Record[i-1]; } encoder->speed_Record[0] = new_Spe; sum += new_Spe; test_Speed = sum/SPEED_RECORD_NUM; return sum/SPEED_RECORD_NUM; } motor_t motor_l; motor_t motor_r; void motor_Init() { DL_TimerG_startCounter(PWM_0_INST); //pwm初始化 /*使能编码器输入捕获中断*/ NVIC_EnableIRQ(ENCODER1A_INST_INT_IRQN); DL_TimerA_startCounter(ENCODER1A_INST); NVIC_EnableIRQ(ENCODER2A_INST_INT_IRQN); DL_TimerG_startCounter(ENCODER2A_INST); /*使能时钟定时器中断*/ NVIC_EnableIRQ(CLOCK_INST_INT_IRQN); DL_TimerA_startCounter(CLOCK_INST); /*motor_l init*/ motor_l.pwmDuty=0; motor_l.speed=0; motor_l.timer_index=DL_TIMER_CC_0_INDEX; motor_l.forward_GPIO_PORT=GPIO_MOTOR_AIN1_PORT; motor_l.reverse_GPIO_PORT=GPIO_MOTOR_AIN2_PORT; motor_l.forward_GPIO_PIN=GPIO_MOTOR_AIN1_PIN; motor_l.reverse_GPIO_PIN=GPIO_MOTOR_AIN2_PIN; motor_l.speed_pid.kp=0; motor_l.speed_pid.ki=0; motor_l.speed_pid.kd=0; motor_l.speed_pid.max_integral=1000; motor_l.speed_pid.maxoutput=1000; motor_l.speed_pid.dead_zone=0; motor_l.pos_pid.kp=0; motor_l.pos_pid.ki=0; motor_l.pos_pid.kd=0; motor_l.pos_pid.max_integral=1000; motor_l.pos_pid.maxoutput=1000; motor_l.pos_pid.dead_zone=0; /*motor_r init*/ motor_r.pwmDuty=0; motor_r.speed=0; motor_r.timer_index=DL_TIMER_CC_1_INDEX; motor_r.forward_GPIO_PORT=GPIO_MOTOR_BIN1_PORT; motor_r.reverse_GPIO_PORT=GPIO_MOTOR_BIN2_PORT; motor_r.forward_GPIO_PIN=GPIO_MOTOR_BIN1_PIN; motor_r.reverse_GPIO_PIN=GPIO_MOTOR_BIN2_PIN; motor_r.speed_pid.kp=0; motor_r.speed_pid.ki=0; motor_r.speed_pid.kd=0; motor_r.speed_pid.max_integral=1000; motor_r.speed_pid.maxoutput=1000; motor_r.speed_pid.dead_zone=0; motor_r.pos_pid.kp=0; motor_r.pos_pid.ki=0; motor_r.pos_pid.kd=0; motor_r.pos_pid.max_integral=1000; motor_r.pos_pid.maxoutput=1000; motor_r.pos_pid.dead_zone=0; } /*左电机的编码器测速*/ void TIMA0_IRQHandler(void) { switch (DL_TimerA_getPendingInterrupt(ENCODER1A_INST)) { case DL_TIMERA_IIDX_CC0_DN: motor_l.encoder.dierct = DL_GPIO_readPins(GPIO_ENCODER_PORT, GPIO_ENCODER_ENCODER1B_PIN);//读取IO电平获取电机旋转方向 motor_l.encoder.countnum= motor_l.encoder.dierct? (motor_l.encoder.countnum + 1) : (motor_l.encoder.countnum - 1);//通过判断旋转方向来决定countnum增加还是减少 break; default: break; } } /*右电机的编码器测速*/ void TIMG6_IRQHandler(void) { switch (DL_TimerG_getPendingInterrupt(ENCODER2A_INST)) { case DL_TIMERG_IIDX_CC0_DN: motor_r.encoder.dierct= DL_GPIO_readPins(GPIO_ENCODER_PORT, GPIO_ENCODER_ENCODER2B_PIN);//读取IO电平获取电机旋转方向 motor_r.encoder.countnum = motor_r.encoder.dierct ? ( motor_r.encoder.countnum + 1) : ( motor_r.encoder.countnum- 1);//通过判断旋转方向来决定countnum增加还是减少 break; default: break; } } /*period 100Hz*/ void CLOCK_INST_IRQHandler(void) { DL_TimerA_clearInterruptStatus(CLOCK_INST, DL_TIMER_IIDX_ZERO); motor_l.encoder.speed = (float)(motor_l.encoder.countnum - motor_l.encoder.lastcount) * 6000 / PULSE_PER_CYCLE; // rpm motor_r.encoder.speed = (float)(motor_r.encoder.countnum - motor_r.encoder.lastcount) * 6000 / PULSE_PER_CYCLE; // rpm motor_l.encoder.speed = Speed_Low_Filter(motor_l.encoder.speed, &motor_l.encoder); motor_r.encoder.speed = Speed_Low_Filter(motor_r.encoder.speed, &motor_r.encoder); motor_l.encoder.lastcount = motor_l.encoder.countnum; motor_r.encoder.lastcount = motor_r.encoder.countnum; } float PID_Realize(pid_t* pid,float target,float feedback) { pid->err = target - feedback; if(pid->err < pid->dead_zone && pid->err > -pid->dead_zone) pid->err = 0;//pid死区 pid->integral += pid->err; if(pid->ki * pid->integral < -pid->max_integral) pid->integral = -pid->max_integral / pid->ki;//积分限幅 else if(pid->ki * pid->integral > pid->max_integral) pid->integral = pid->max_integral / pid->ki; pid->output = (pid->kp * pid->err) + (pid->ki * pid->integral) + (pid->kd * (pid->err - pid->last_err)); //输出限幅 if(pid->output > pid->maxoutput) pid->output = pid->maxoutput; else if(pid->output < -pid->maxoutput) pid->output = -pid->maxoutput; pid->last_err = pid->err; return pid->output; } void Motor_Set_Duty(motor_t *motor){ if (motor->pwmDuty>=0){//正转 DL_TimerG_setCaptureCompareValue(PWM_0_INST,motor->pwmDuty,motor->timer_index); DL_GPIO_setPins(motor->forward_GPIO_PORT, motor->forward_GPIO_PIN); DL_GPIO_clearPins(motor->reverse_GPIO_PORT, motor->reverse_GPIO_PIN); } else if(motor->pwmDuty<0){//反转 DL_TimerG_setCaptureCompareValue(PWM_0_INST,-motor->pwmDuty,motor->timer_index); DL_GPIO_setPins(motor->reverse_GPIO_PORT, motor->reverse_GPIO_PIN); DL_GPIO_clearPins(motor->forward_GPIO_PORT, motor->forward_GPIO_PIN); } } void Motor_Set_Speed(motor_t *motor){ motor->pwmDuty=PID_Realize(&motor->speed_pid,motor->speed,motor->encoder.speed); Motor_Set_Duty(motor); } void Motor_Set_Position(motor_t *motor){ motor->pos_pulse=(int)((motor->pos*PULSE_PER_CYCLE)/(LINE_SPEED_C)); motor->speed=PID_Realize(&motor->pos_pid, motor->pos_pulse, motor->encoder.countnum); Motor_Set_Speed(motor); } void Motor_Stop(motor_t *motor){ motor->speed=0; Motor_Set_Speed(motor); if(motor->encoder.speed==0){ motor->encoder.countnum=0; motor->encoder.lastcount=0; motor->speed_pid.integral=0; } }解释一下这些代码
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值