首页 > 其他分享 >PID多环处理,例如速度位置环

PID多环处理,例如速度位置环

时间:2024-02-19 11:44:16浏览次数:22  
标签:多环 ctrl float PID setpoint 位置 pid pos motor


例如
typedef struct { float Kp, Ki, Kd; float integral_term; float last_error; float pwm_output; } PID_Controller; void init_PID(PID_Controller *pid, float kp, float ki, float kd) { pid->Kp = kp; pid->Ki = ki; pid->Kd = kd; pid->integral_term = 0.0f; pid->last_error = 0.0f; } float pid_update(PID_Controller *pid, float setpoint, float current_value, float dt) { float error = setpoint - current_value; pid->integral_term += error * dt; float derivative = (error - pid->last_error) / dt; pid->last_error = error; float output = pid->Kp * error + pid->Ki * pid->integral_term + pid->Kd * derivative; // 这里仅作为示例,实际应用中应根据需求限制输出范围 return constrain(output, -100.0f, 100.0f); } // 假设的编码器位置读取函数 float read_encoder() { // 实际代码需要替换为读取编码器数据的逻辑 return 0.0f; } // 假设的当前速度读取函数 float read_motor_speed() { // 实际代码需要替换为读取电机当前速度的逻辑 return 0.0f; } // 假设的PWM信号更新函数 void update_motor_pwm(float pwm_signal) { // 实际代码需要替换为向电机驱动电路发送PWM信号的逻辑 } // 主程序 int main() { MotorController motor_ctrl; PID_Controller pos_pid, speed_pid; init_PID(&pos_pid, KP_POS, KI_POS, KD_POS); init_PID(&speed_pid, KP_SPEED, KI_SPEED, KD_SPEED); motor_ctrl.setpoint_pos = DESIRED_POSITION; while (1) { motor_ctrl.current_pos = read_encoder(); float pos_error = motor_ctrl.setpoint_pos - motor_ctrl.current_pos; float desired_speed_change = pid_update(&pos_pid, 0, pos_error, COMPUTATION_INTERVAL_SECONDS);//重点利用让位置的误差往0处理,算出每次增加的目标速度多少 // 更新速度设定值并约束在合理范围内 motor_ctrl.speed_pid.setpoint += desired_speed_change; motor_ctrl.speed_pid.setpoint = constrain(motor_ctrl.speed_pid.setpoint, MIN_SPEED, MAX_SPEED);//约束最大值,最小值 motor_ctrl.current_speed = read_motor_speed(); float speed_error = motor_ctrl.speed_pid.setpoint - motor_ctrl.current_speed; float pwm_signal = pid_update(&speed_pid, motor_ctrl.speed_pid.setpoint, motor_ctrl.current_speed, COMPUTATION_INTERVAL_SECONDS); update_motor_pwm(pwm_signal); delay(COMPUTATION_INTERVAL_SECONDS); if (abs(motor_ctrl.current_pos - motor_ctrl.setpoint_pos) < POSITION_TOLERANCE) { // 到达目标位置后的处理(如停止或进入位置保持模式) break; } } stop_motor(); }


位置保持模式例子

typedef struct {
    PID_Controller pos_pid;
    float setpoint_pos;
    float current_pos;
    bool is_in_position_hold_mode;
    float position_hold_pid_params[Kp, Ki, Kd]; // 位置保持模式下的PID参数
} MotorController;

void enter_position_hold_mode(MotorController *mc) {
    mc->is_in_position_hold_mode = true;
    mc->pos_pid.Kp = mc->position_hold_pid_params[Kp];
    mc->pos_pid.Ki = mc->position_hold_pid_params[Ki];
    mc->pos_pid.Kd = mc->position_hold_pid_params[Kd];
}

void exit_position_hold_mode(MotorController *mc) {
    mc->is_in_position_hold_mode = false;
    // 恢复正常位置跟踪时的PID参数
    // ... 这里根据实际情况设置 ...
}

bool new_position_command_arrived() {
    // 实际代码需要替换为检查是否有新位置命令到来的逻辑
    static uint32_t last_check_time = 0;
    if (millis() - last_check_time > NEW_POSITION_CHECK_INTERVAL) {
        last_check_time = millis();
        // 检查新位置命令是否存在并返回结果
        return check_new_position_command(); // 实际调用获取新位置命令的方法
    }
    return false;
}

float get_new_setpoint_position() {
    // 实际代码需要替换为获取新位置设定点的逻辑
    return retrieve_new_setpoint_position(); // 实际调用获取新位置设定点的方法
}

int main() {
    MotorController motor_ctrl;
    init_MotorController(&motor_ctrl, KP_POS, KI_POS, KD_POS);
    motor_ctrl.setpoint_pos = DESIRED_POSITION;
    
    while (1) {
        motor_ctrl.current_pos = read_encoder();

        if (!motor_ctrl.is_in_position_hold_mode) {
            // 在未进入位置保持模式下,执行正常的位置跟踪控制
            float pos_error = motor_ctrl.setpoint_pos - motor_ctrl.current_pos;
            float pwm_signal = pid_update(&motor_ctrl.pos_pid, pos_error, COMPUTATION_INTERVAL_SECONDS);

            update_motor_pwm(pwm_signal);
            
            if (abs(motor_ctrl.current_pos - motor_ctrl.setpoint_pos) < POSITION_HOLD_TOLERANCE) {
                enter_position_hold_mode(&motor_ctrl);
            }
        } else {
            // 在位置保持模式下,仅使用比例或比例微分控制
            float pos_error = motor_ctrl.setpoint_pos - motor_ctrl.current_pos;
            float pwm_signal = pid_update(&motor_ctrl.pos_pid, pos_error, 0.0f /* 不使用速度反馈 */, COMPUTATION_INTERVAL_SECONDS);

            update_motor_pwm(pwm_signal);

            if (new_position_command_arrived() || abs(pos_error) > POSITION_HOLD_EXIT_THRESHOLD) {
                motor_ctrl.setpoint_pos = get_new_setpoint_position();
                exit_position_hold_mode(&motor_ctrl);
            }
        }

        delay(COMPUTATION_INTERVAL_SECONDS);
    }

    stop_motor();
}

 



 

标签:多环,ctrl,float,PID,setpoint,位置,pid,pos,motor
From: https://www.cnblogs.com/mokongking/p/18020756

相关文章

  • 刷新后记忆上一次的查询参数、页面位置
    需求目前页面缓存机制是keep-alive,即点击之前页签,页面不刷新。这会导致:数据不是最新的,即在页签A操作数据后,点击之前打开的页签B,页签B的数据仍然是旧的。需求:再次点击页签B时,根据之前的查询参数(包括页码)、树节点、屏幕高度(下文统称为“查询数据”)刷新页面,即实现静默刷新......
  • 如何将桌面文件从C盘改到其他位置
    1、打开此电脑,找到左侧的桌面并点击鼠标右键 2、点击属性 3、点击上方的位置,然后点击下方的移动按钮,选择需要存放的文件地址 4、点击应用就完成了  ......
  • Qt实用技巧:QCustomPlot做北斗GPS显示绝对位置运动轨迹和相对位置运动轨迹图的时,使图按
    需求  使用QCustomPlot绘制多个目标的北斗运行轨迹图,包括累计绝对位置图和记录时刻的相对位置图。  当前绘制存在问题:    交付客户前,公司内部自测流程发现的问题。  实际预期效果为:   原因  QCustomPlot加入数据是按照x轴排列,也可以按照y轴排列,使用图层......
  • PID 控制 |(搬运)教程与 python 代码
    因为完全没有自动化和控制基础,所以找了很多博客都没看懂;干货|通俗易懂讲解PID,这是看的最懂的一篇()PID控制的python代码:[TBC]或许可以直接调用的python包:https://github.com/m-lundberg/simple-pid......
  • 连续性区间位置查询——链式并查集
    目录问题概述思路分析参考代码做题总结问题概述这里给出两个题目,一个是上一篇的新春漫步(其实当时给的官方题解就是链式并查集的写法,但是当时我懒得写了,emmm),二是最近vp的一场cf_div3_923场的d题,准确来说,就是因为这个我才准备写这个的,题目大概就是给出一个长度为n的数组和q组询......
  • s.insert(位置,“元素”)
    `include<bits/stdc++.h>usingnamespacestd;intmain(){strings;getline(cin,s);\需要处理空格时使用getline()intn=s.length();for(inti=n-4;i>=0;i--){\i的初位置if(s[i]''&&s[i+1]'i'&&s[i+2]'s'&&s[i+......
  • 小程序右上角的小圆圈和三个点的位置获取
    constsystemInfo=wx.getSystemInfoSync()Page({data:{statusBarStyle:'',navigationBarStyle:'',navigationStyle:'',menuStyle:''},onLoad(){this.setData({statusBarStyle:......
  • 无符号数 高低字节变换位置
     //两个字节换位quint16exchangeByte(unsignedshortval){unsignedcharh=val>>8;unsignedcharl=val&0xFF;unsignedshortret=l;ret<<=8;ret|=h;returnret;}//val变为从高到低,如0x11223344变为0x44332211quint......
  • NTFS文件系统支持硬链接和符号链接,这两种链接机制都可以让不同的文件指向同一个物理位
    NTFS文件系统支持硬链接和符号链接,这两种链接机制都可以让不同的文件指向同一个物理位置,从而节省磁盘空间和提高文件系统的效率。虽然它们的用途相似,但是硬链接和符号链接有一些不同之处。硬链接:硬链接(HardLink)是指将多个文件名链接到同一个物理位置的一种机制。它可以让多个文......
  • 微信支付普通商户与AppID账号关联管理-授权
     微信支付普通商户与AppID账号关联管理二、名词解释名词释义微信支付普通商户公司企业、政府机关、事业单位、社会组织、个体工商户、个人卖家、小微商户。(微信支付商户接入指引)AppID已通过微信认证的服务号,订阅号*[1],小程序,企业微信*[2],移动应用*[3]......