当前位置: 首页 > article >正文

ESP32使用mpu6050以及pid调参

pid

//pid参考教程  https://www.xpstem.com/article/10120
#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu6050(Wire);

// pid相关参数
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1秒
double outMin,outMax;

void setup() {
  Serial.begin(115200);
  delay(5000);
  Wire.begin();
  mpu6050.begin();
  mpu6050.calcGyroOffsets(true);
  // pid初始化
  Setpoint = 0; //设置目标值
  SetTunings(15,0.3,0);  //设置kp ki kd 参数
  SetSampleTime(50);//设置采样时间  毫秒
  SetOutputLimits(-255,255); //设置输出的最大最小值
}

void loop() {
  mpu6050.update();
  // Serial.print("angleX : ");
  // Serial.print(mpu6050.getAngleX());
  Serial.print("\tangleY : ");
  Serial.println(mpu6050.getAngleY());
  // Serial.print("\tangleZ : ");
  // Serial.println(mpu6050.getAngleZ());
  Input = mpu6050.getAngleY(); //设置 输入值
  Compute();//计算
  Serial.println(Output);//输出
}

//pid计算 Output输出值的范围在 -255--255
void Compute()
{
   /*How long since we last calculated*/
   unsigned long now = millis();
   int timeChange = (now-lastTime);
   if(timeChange >= SampleTime)
   {
     double error = Setpoint - Input;
     ITerm += (ki*error);
     if(ITerm > outMax) ITerm = outMax;
     else if(ITerm < outMin) ITerm = outMin;

     double dInput =(Input-lastInput);

    Output = kp * error + ITerm - kd * dInput;
    if(Output > outMax) Output = outMax;
    else if(Output < outMin) Output = outMin;

    lastInput = Input;
    lastTime = now;
   } 
}
// 设置kp ki kd参数值
void SetTunings(double Kp, double Ki, double Kd)
{
  double SampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki*SampleTimeInSec;
   kd = Kd/SampleTimeInSec;
}
// 设置采样时间
void SetSampleTime(int NewSampleTime)
{
  if(NewSampleTime >0)
  {
    double ratio = (double)NewSampleTime/(double)SampleTime;
    ki *= ratio;
    kd /= ratio;
    SampleTime = (unsigned long)NewSampleTime;
  }
}
// 设置输出值的范围
void SetOutputLimits(double Min,double Max)
{
  if(Min >Max) return;
  outMin = Min;
  outMax = Max;

  if(Output >outMax ) Output = outMax;
  else if (Output <outMin) Output = outMin;

  if(ITerm >outMax) ITerm = outMax;
  else if(ITerm < outMin) ITerm = outMin;
}


/*
#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu6050(Wire);

long timer = 0;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  mpu6050.begin();
  mpu6050.calcGyroOffsets(true);
  delay(5000);
}

void loop() {
  mpu6050.update();

  if(millis() - timer > 1000){
    
    Serial.println("=======================================================");
    Serial.print("temp : ");Serial.println(mpu6050.getTemp());
    Serial.print("accX : ");Serial.print(mpu6050.getAccX());
    Serial.print("\taccY : ");Serial.print(mpu6050.getAccY());
    Serial.print("\taccZ : ");Serial.println(mpu6050.getAccZ());
  
    Serial.print("gyroX : ");Serial.print(mpu6050.getGyroX());
    Serial.print("\tgyroY : ");Serial.print(mpu6050.getGyroY());
    Serial.print("\tgyroZ : ");Serial.println(mpu6050.getGyroZ());
  
    Serial.print("accAngleX : ");Serial.print(mpu6050.getAccAngleX());
    Serial.print("\taccAngleY : ");Serial.println(mpu6050.getAccAngleY());
  
    Serial.print("gyroAngleX : ");Serial.print(mpu6050.getGyroAngleX());
    Serial.print("\tgyroAngleY : ");Serial.print(mpu6050.getGyroAngleY());
    Serial.print("\tgyroAngleZ : ");Serial.println(mpu6050.getGyroAngleZ());
    
    Serial.print("angleX : ");Serial.print(mpu6050.getAngleX());
    Serial.print("\tangleY : ");Serial.print(mpu6050.getAngleY());
    Serial.print("\tangleZ : ");Serial.println(mpu6050.getAngleZ());
    Serial.println("=======================================================\n");
    timer = millis();
    
  }

}
*/

串口调参

#include <Arduino.h>
//串口输入字符串的模式  10,0.01,0   中间使用,间隔
double pid_array[] ={10,0.01,0};  //申明一个数组  分别存放 kp  ki  kd 的值

void setup() {
  Serial.begin(115200);
}

void loop() {
  String inString="";
  while(Serial.available()>0){
    inString += char(Serial.read());
    delay(10);      // 延时函数用于等待字符完全进入缓冲区
  }
  // 检查是否接收到数据,如果接收到数据,则输出该数据
  if(inString!=""){
    Serial.print("Input String:");
    Serial.println(inString);       //Input String:10,0.01,0
    char *ptr = strtok(const_cast<char*>(inString.c_str()),",");   // string转化为char* 使用   const_cast<char*>(inString.c_str())
    int i = 0;
    while(ptr != NULL){
      Serial.println(ptr);
      String tmp_str = ptr;    //char*转化为string
      pid_array[i] = tmp_str.toDouble();
      i++;
      ptr = strtok(NULL,",");
    }
    SetTunings(pid_array[0],pid_array[1],pid_array[2]);
  }
}

// 设置kp ki kd参数值
void SetTunings(double Kp, double Ki, double Kd)
{
  Serial.print("kp=");
  Serial.print(Kp);
  Serial.print("\t ki=");
  Serial.print(Ki);
  Serial.print("\t kd=");
  Serial.println(Kd);    //kp=10.00	 ki=0.01	 kd=0.00
  // double SampleTimeInSec = ((double)SampleTime)/1000;
  //  kp = Kp;
  //  ki = Ki*SampleTimeInSec;
  //  kd = Kd/SampleTimeInSec;
}


http://www.kler.cn/a/156002.html

相关文章:

  • 深度学习——权重初始化、评估指标、梯度消失和梯度爆炸
  • 《DiffusionDet: Diffusion Model for Object Detection》ICCV2023
  • Qt 获取当前系统中连接的所有USB设备的信息 libudev版
  • vscode下nuget包的本地引入方法
  • learn-F12 Performance(性能)前端性能分析(LCP,CLS,INP)
  • Mysql 8迁移到达梦DM8遇到的报错
  • Python - 字典3
  • 详解云WAF:免费GOODWAF归来
  • HarmonyOS—ArkTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化【鸿蒙专栏-11】
  • C语言实现Cohen_Sutherland算法
  • 构造函数的定义
  • Prometheus+Grafana搭建日志采集
  • Langchain-Chatchat的安装过程
  • C++基础 -35- string类
  • 操作系统·存储器管理
  • 亚信科技AntDB数据库完成中国信通院数据库迁移工具专项测试
  • unordered_map与unordered_set的实现(含迭代器)
  • go使用aes加密算法
  • 【ArcGIS Pro微课1000例】0043:深度学习--框架库安装
  • 【java+vue+微信小程序项目】从零开始搭建——健身房管理平台(3)路由导航卫士、主页实现
  • Jupyter NoteBook未授权访问漏洞
  • 2024年天津财经大学珠江学院专升本专业课报名缴费操作流程
  • KALI LINUX入门
  • LC-1423. 可获得的最大点数(子数组和、枚举)
  • 牛客在线编程(SQL大厂面试真题)
  • 抓取检测(Grasp Dection)