【esp8266实践记录】三、esp8266开发版PID控制SG90舵机

文章目录

  • 前言
  • 一、基本思路
  • 二、主要代码
  • 三、结果展示
  • 总结


前言

不能只满足于简单地控制舵机,引入略显高端的做法,使用PID方法控制舵机

一、基本思路

舵机使用基础(SG90模拟舵机和MG90S数字舵机为例)

PID算法的特点及原理讲解

老规矩,首先要安装舵机相关的******库,不教安装。
先初始化PID结构体,然后传入目标值即可。

要说最难的还是调PID的参数,我是调了差不多一下午。

二、主要代码

PID函数定义,套用忘了从哪来的模板


typedef struct 
{
  float Target_value;  //目标值
  float Current_value;  //当前值
  float PWM;  //PWM
  float Err;  //目前误差
  float Last_Err;  //上一次误差
  float Kp,Ki,Kd;  //比例常数,积分常数,微分常数
  float output;  //PID输出,通常作为控制执行器的变量
  float integral;  //积分值
}PID_TypeDef;

PID_TypeDef PID;  //定义结构体变量

void PID_Init();
float PID_operation(float value);

//初始化PID各项参数
void PID_Init()
{
  PID.Target_value = 0.0;
  PID.Current_value = 0.0;
  PID.PWM = 0.0;
  PID.Err = 0.0;
  PID.Last_Err = 0.0;
  PID.output = 0.0;
  PID.integral = 0.0;
  PID.Kp = 0.4;  
  PID.Ki = 0.03;  
  PID.Kd = 0.2;     //比例常数,积分常数,微分常数的调整非常重要,这里的参数是经过几次试验得出的经验参数
}
//PID操作
float PID_operation(float value)
{
  float index;
  PID.Target_value = value;  //确定目标值
  Serial.println("Target_value:");Serial.print(PID.Target_value);Serial.println();
  PID.Err = PID.Target_value - PID.Current_value;  //计算偏差量
  if (abs(PID.Err)<value*0.01)
    return value;
  Serial.println("Err:");Serial.print(PID.Err);Serial.println();
  
      if (abs(PID.Err) > 100)
    {
        index = 0;
    }
    else
    {
        index = 1;
        PID.integral += PID.Err;  //计算和
    }
  PID.output = PID.Kp*PID.Err + index*PID.Ki*PID.integral + PID.Kd* (PID.Err-PID.Last_Err);  //PID运算


  Serial.println("output:");Serial.print(PID.output);Serial.println();

  PID.Last_Err = PID.Err;  //将当前误差值存入上一误差值
  
  PID.PWM = int(PID.Current_value+PID.output);  //将当前值更新为PID的输出值
  Serial.println("PWM:");Serial.print(PID.PWM);Serial.println();
  //PID.Current_value=int(PID.PWM);
  //Serial.println("Current_value:");Serial.print(PID.Current_value);Serial.println();
  if(PID.PWM>0&&PID.PWM<=180){


    return PID.PWM;  //返回当前值
  }
  else{
    return 0;
  }
}

分割

#include 

Servo myServo;  // 定义Servo对象来控制
int pos = 0,t=0;    // 角度存储变量

//这里放PID函数定义,就上面那些代码


void setup() {
  myServo.attach(D5); //D5   
  Serial.begin(9600);
}

void loop() { 
  PID_Init();
  for (pos = 0; pos <= 90; pos ++) {
  PID.Current_value = myServo.read();

  if(t=PID_operation(1)){
    
      Serial.println("Current_value45:");Serial.print(PID.Current_value);Serial.println();
      Serial.println("t45:");Serial.print(t);Serial.println();

    myServo.write(t);
    delay(15);
  }
  }

  delay(2000);//延时2s 
  PID_Init();
  for (pos = 0; pos <= 90; pos ++) {
    PID.Current_value = myServo.read();

    if(t=PID_operation(135)){
      
            Serial.println("t135:");Serial.print(PID.Current_value);Serial.println();

    myServo.write(t);
    delay(15);
  }
  }
  delay(2000);//延时2s 
  
}

三、结果展示

【esp8266实践记录】三、esp8266开发版PID控制SG90舵机_第1张图片
【esp8266实践记录】三、esp8266开发版PID控制SG90舵机_第2张图片

总结

舵机不舵机倒无所谓,主要是想学一下PID控制。这东西后面用处可多了。

【esp8266实践记录】三、esp8266开发版PID控制SG90舵机_第3张图片

“每一次相聚都将是一场离别的盛宴。”

你可能感兴趣的:(esp8266实践记录,单片机,嵌入式硬件,物联网)