1、这篇文章的目的

由于本人之前做过的很多项目中,基本上都用到了pid算法,发现pid用起来是真香,不仅算法简单,控制的效果也是很不错的,基本上都能够达到要求。但是随着我做过的项目多了,发现每次做一个新的项目后,总是又回过头来找寻以前写的pid函数,然后又重复的写pid函数调节pid的参数,一次又一次在宏定义上修改这么多参数,真是太麻烦了(本人太懒了)。

既然我们不是学过c语言中的结构体和函数指针吗,能不能用pid结构体保存于pid运算有关的参数数据,用结构体直接保存函数指针,然后在调pid参数和使用函数时直接修改这个结构体,这样多方便啊。

2、整理出来的可以直接使用的函数

(1) pid.c函数

#include "pid.h"//绝对值函数
#define ABS(x)      ((x>0)? x: -x) /*参数初始化--------------------------------------------------------------*/
static void pid_param_init(PID_TypeDef * pid, PID_ID   id,uint16_t maxout,uint16_t intergral_limit,float deadband,uint16_t period,int16_t  max_err,int16_t  target,float    kp, float   ki, float   kd)
{pid->id = id;      pid->ControlPeriod = period;             //没用到pid->DeadBand = deadband;pid->IntegralLimit = intergral_limit;pid->MaxOutput = maxout;pid->Max_Err = max_err;pid->target = target;pid->kp = kp;pid->ki = ki;pid->kd = kd;pid->output = 0;
}/*中途更改参数设定--------------------------------------------------------------*/
static void pid_reset(PID_TypeDef * pid, float kp, float ki, float kd)
{pid->kp = kp;pid->ki = ki;pid->kd = kd;
}/*pid计算-----------------------------------------------------------------------*/
static float pid_calculate(PID_TypeDef* pid, float measure,int16_t target)
{
//  uint32_t time,lasttime;pid->lasttime = pid->thistime;pid->thistime = HAL_GetTick();pid->dtime = pid->thistime-pid->lasttime;pid->measure = measure;pid->target = target;pid->last_err  = pid->err;pid->last_output = pid->output;pid->err = pid->target - pid->measure;//是否进入死区if((ABS(pid->err) > pid->DeadBand)){pid->pout = pid->kp * pid->err;pid->iout += (pid->ki * pid->err);pid->dout =  pid->kd * (pid->err - pid->last_err); //积分是否超出限制if(pid->iout > pid->IntegralLimit)pid->iout = pid->IntegralLimit;if(pid->iout < - pid->IntegralLimit)pid->iout = - pid->IntegralLimit;//pid输出和pid->output = pid->pout + pid->iout + pid->dout;//选择是否滤波?//pid->output = pid->output*0.7f + pid->last_output*0.3f;//输出限幅if(pid->output>pid->MaxOutput)         {pid->output = pid->MaxOutput;}if(pid->output < -(pid->MaxOutput)){pid->output = -(pid->MaxOutput);}}return pid->output;
}/*pid结构体初始化,每一个pid参数需要调用一次--------------------------------------*/
void pid_init(PID_TypeDef* pid)
{pid->f_param_init = pid_param_init;pid->f_pid_reset  = pid_reset;pid->f_cal_pid    = pid_calculate;
}

(2)pid.h函数

#ifndef _PID_H
#define _PID_H#include "stdint.h"//PID优化功能枚举
typedef enum
{PID_Position,PID_Speed
}PID_ID;typedef struct _PID_TypeDef
{PID_ID id;float target;               //目标值float lastNoneZeroTarget;float kp;float ki;float kd;float   measure;            //测量值float   err;               //误差float   last_err;           //上次误差float pout;float iout;float dout;float output;                //本次输出float last_output;            //上次输出float MaxOutput;          //输出限幅float IntegralLimit;      //积分限幅float DeadBand;               //死区(绝对值)float ControlPeriod;     //控制周期float Max_Err;                //最大误差uint32_t thistime;uint32_t lasttime;uint8_t  dtime;   void (*f_param_init)(struct _PID_TypeDef *pid,  //PID参数初始化PID_ID id,uint16_t maxOutput,uint16_t integralLimit,float deadband,uint16_t controlPeriod,int16_t max_err,     int16_t  target,float kp,float ki,float kd
);
//pid三个参数修改
void (*f_pid_reset)(struct _PID_TypeDef *pid, float kp,float ki, float kd);
//pid计算
float (*f_cal_pid)(struct _PID_TypeDef *pid, float measure);
}PID_TypeDef;void pid_init(PID_TypeDef* pid);#endif

(3)pid函数的使用

#include "pid.h"//有几个电机就用几个pid结构体
PID_TypeDef motor_pid[4];//初始化PID参数
static void motor_init(void)
{for(int i=0; i<4; i++){  pid_init(&motor_pid[i]);motor_pid[i].f_param_init(&motor_pid[i],PID_Speed,16384,5000,10,0,8000,0,1.5,0.1,0);//类型id,输出限幅,积分限幅,绝对值,控制周期,最大误差,目标值, p, i, d}
}//对四个电机同时进行pid计算
static void motor_control(int32_t set_spd1,int32_t set_spd2,int32_t set_spd3,int32_t set_spd4)
{//motor_pid[0].target = set_spd1;                                                                                             motor_pid[0].f_cal_pid(&motor_pid[0],now_speed_1,set_spd1);//PID计算                                                                                          motor_pid[1].f_cal_pid(&motor_pid[1],now_speed_2,set_spd2);//PID计算                                                                              motor_pid[2].f_cal_pid(&motor_pid[2],now_speed_3,set_spd3);//PID计算      motor_pid[3].f_cal_pid(&motor_pid[3],now_speed_4,set_spd4);//PID计算//将PID的计算结果 motor_pid[0].output 控制电机osDelay(10);      //PID控制频率100HZ
}

STM32—PID结构体使用讲解相关推荐

  1. Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解

    Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解 (1)sockaddr struct sockaddr { unsigned  short  sa_ ...

  2. c语言sockaddr_in结构体,转:sockaddr与sockaddr_in结构体详细讲解

    sockaddr与sockaddr_in结构体详细讲解 二者区别 struct sockaddr { unsigned short sa_family;     /* address family, ...

  3. STM32 把结构体存入Flash,并读取(微薄之力,已验证)

    结构体对齐原则:点击浏览 在网上有看到把结构体存入数组的说法,于是自己尝试一下,确实可以. 不过也遇到问题,就是存入数据到Flash,里面有填充0x00的情况 经过分析应该是这种情况,就是结构体对齐的 ...

  4. (摘录)sockaddr与sockaddr_in,sockaddr_un结构体详细讲解

    struct sockaddr { unsigned short sa_family;     /* address family, AF_xxx */ char sa_data[14];       ...

  5. 看了这篇c语言结构体精讲解,你难道还怕你不会吗?

    本文主要介绍结构体入门,结构体指针的教学,请读者讲此段代码复制在Devc++,以便更好阅读体验.谢谢. #include<stdio.h> //结构体教学 首先,结构体的格式是在主函数前先 ...

  6. sockaddr,sockaddr_in,sockaddr_un结构体详细讲解

    struct sockaddr {unsigned short sa_family; /* address family, AF_xxx */char sa_data[14]; /* 14 bytes ...

  7. 【Linux 内核】进程管理 task_struct 结构体 ② ( state 字段 | stack 字段 | pid 字段 | tgid 字段 | pid_links 字段 )

    文章目录 一.task_struct 结构体字段分析 1.state 字段 2.stack 字段 3.pid字段 4.tgid 字段 5.pid_links 字段 在 Linux 内核 中 , &qu ...

  8. 串口初始化结构体和固件库讲解

    串口初始化结构体和固件库讲解 常用的6个函数,结构体: USART 初始化结构体(USART_InitTypeDef) USART 时钟初始化结构体(USART_ClockInitTypeDef) 串 ...

  9. 驱动下通过进程PID获得进程名 (动态获取ImageFileName在EPROCESS结构体中的相对偏移)...

    思路 进程EPROCESS结构体中含有进程名ImageFileName(需求处ImageFileName在EPROCESS结构体中的相对偏移)-->获得进程EPROCESS-->通过进程句 ...

最新文章

  1. 从简单工厂到工厂方法
  2. 最聪明女生集结清华,挑战人工智能
  3. Daily Scrum - 11/24
  4. ArrayList、LinkedList、Vector的区别。
  5. tomcat 禁用access.log
  6. 运用shell,python自动下载linux系统运维
  7. 【Linux系统编程】进程介绍
  8. DE连接,创建数据集,数据导入以及数据导出(转载)
  9. python sqlite3
  10. 超越自我 — 实现人生价值之路
  11. 浅谈聊天机器人 ChatBot 涉及到的技术点 以及词性标注和关键字提取
  12. 【Unity3D开发小游戏】《青蛙过河》Unity开发教程
  13. Forever young
  14. Ubuntu16.04安装NVIDIA Titan Xp显卡驱动
  15. bzoj 4008 亚瑟王 - 动态规划 - 概率与期望
  16. 学习云计算前景如何?云计算成为获取人工智能主要途径
  17. 模拟键盘按键 自动输入文字
  18. 【DBCA -SILENT】静默安装之rac数据库安装
  19. Java 面试 :乐观锁 悲观锁
  20. 摘自《大长今励志启示》

热门文章

  1. 现在的杀毒软件真是无语的没话说
  2. 情感脑机接口研究综述
  3. 构建私有云,需要考虑哪些要点?
  4. spark sql 出现 java.lang.RuntimeException: serious problem
  5. syslog-ng详解——syslog-ng配置语法
  6. 霹雳巴拉卷积神经网络+图像分类篇
  7. linux安装mt7601网卡固件,上网本Debian下装无线网卡7601的驱动过程
  8. CODING 敏捷实战系列课第五讲:敏捷中国史
  9. 蓝桥杯之单片机设计与开发(34)——第十届省赛前最后总结与程序封装
  10. 图像质量评价学习笔记01:IQA的基本概念及分类