ROS 2 FishBot PID控制电机代码

发布于:2025-05-11 ⋅ 阅读:(23) ⋅ 点赞:(0)
#include <Arduino.h>
#include <Wire.h>
#include <MPU6050_light.h>
#include <Esp32McpwmMotor.h>
#include <Esp32PcntEncoder.h>

Esp32McpwmMotor motor;        // 创建一个名为motor的对象,用于控制电机
Esp32PcntEncoder encoders[2]; // 创建一个数组用于存储两个编码器

MPU6050 mpu(Wire);

int64_t last_ticks[2] = {0, 0}; // 用于存储上一次编码器的计数
int64_t delta_ticks[2] = {0, 0}; // 用于存储两次编码器计数之间的差值
int64_t last_update_time = 0;    // 用于存储上一次更新时间
float current_speed[2] = {0, 0}; // 用于存储当前速度

// put function declarations here:
int myFunction(int, int);

#define TRIG 27
#define ECHO 21
#define LED_BUILTIN 2

unsigned long previousMillis = 0; // 用于记录上一次电平切换的时间
const long interval = 500;        // 定时器间隔,单位为毫秒

void setup()
{
  // put your setup code here, to run once:
  int result = myFunction(2, 3);
  Serial.begin(115200);
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  Wire.begin(18, 19); // SDA, SCL
  byte status = mpu.begin();
  Serial.print(F("MPU6050 status: "));
  Serial.println(status);
  while (status != 0)
  {
    // stop everything if could not connect to MPU6050
  }
  mpu.calcOffsets(true, true); // gyro and accelero
  Serial.println("Done!");
  Serial.println("===========================\n");
  motor.attachMotor(0, 22, 23); // 将电机0连接到引脚22和引脚23
  motor.attachMotor(1, 12, 13); // 将电机1连接到引脚12和引脚13
  Serial.println("Motor Done!");
  // 编码器
  encoders[0].init(0, 32, 33); // 初始化第一个编码器,使用GPIO 32和33连接
  encoders[1].init(1, 26, 25); // 初始化第二个编码器,使用GPIO 26和25连接
  Serial.println("Encoder Done!");

  // 控制电机
  motor.updateMotorSpeed(0, 100); // 设置电机0的速度为负70
  motor.updateMotorSpeed(1, 0);  // 设置电机1的速度为正70
}

unsigned long timer = 0;
void loop()
{
  // put your main code here, to run repeatedly:
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  double duration = pulseIn(ECHO, HIGH);
  double distance = duration * 0.034 / 2;
  // Serial.printf("Distance: %lf cm\n", distance);
  /*
  mpu.update();
  if ((millis() - timer) > 1000)
  {
    // 温度
    Serial.printf("Temp: %lf\n", mpu.getTemp());
    // 加速度计数据
    Serial.printf("Accel: %lf %lf %lf\n", mpu.getAccX(), mpu.getAccY(), mpu.getAccZ());
    // 加速度计角度
    Serial.printf("Angle: %lf %lf %lf\n", mpu.getAngleX(), mpu.getAngleY(), mpu.getAngleZ());
    // 陀螺仪数据
    Serial.printf("Gyro: %lf %lf %lf\n", mpu.getGyroX(), mpu.getGyroY(), mpu.getGyroZ());
    // 综合角度
    Serial.printf("Angle: %lf %lf %lf\n", mpu.getAngleX(), mpu.getAngleY(), mpu.getAngleZ());
    Serial.println("===========================\n");
    timer = millis();
  }
  */
  // 获取当前时间
  unsigned long currentMillis = millis();

  // 检查是否达到定时器间隔
  if (currentMillis - previousMillis >= interval)
  {
    // 记录当前时间
    previousMillis = currentMillis;
    // 切换2号脚的电平
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }

  delay(10);
  // 读取编码器的计数器数值
  int64_t dt = millis() - last_update_time; // 计算时间差
  delta_ticks[0] = encoders[0].getTicks() - last_ticks[0]; // 计算第一个编码器的差值
  delta_ticks[1] = encoders[1].getTicks() - last_ticks[1]; // 计算第二个编码器的差值
  current_speed[0] = delta_ticks[0]*0.105805 / (float)dt; // 计算第一个编码器的速度
  current_speed[1] = delta_ticks[1]*0.105805 / (float)dt; // 计算第二个编码器的速度

  //下次正常计算
  last_ticks[0] = encoders[0].getTicks(); // 保存第一个编码器的计数
  last_ticks[1] = encoders[1].getTicks(); // 保存第二个编码器的计数
  last_update_time = millis(); // 保存当前时间
  // 读取并打印两个编码器的计数器数值 一圈1930个脉冲 直径65mm  一个脉冲前进=0.105805mm
  Serial.printf("speed1=%lf,speed2=%lf\n", current_speed[0], current_speed[1]);
  //Serial.printf("tick1=%d,tick2=%d\n", encoders[0].getTicks(), encoders[1].getTicks());
}

// put function definitions here:
int myFunction(int x, int y)
{
  return x + y;
}

Lib

PidController.cpp

#include "PidController.h"
#include <Arduino.h>

PidController::PidController() = default;
// 默认构造函数
PidController::PidController(float kp, float ki, float kd) {
    _kp = kp;
    _ki = ki;
    _kd = kd;

}
/*
        float update(float current);// 更新PID控制器,提供当前值,返回控制量
        void update_target(float target); // 更新目标值
        void update_pid(float kp, float ki, float kd); // 更新PID参数
        void reset(); // 重置PID控制器
        void out_limit(float); // 输出限制
*/
float PidController::update(float current){
    error_ = target_ - current; // 计算误差
    error_sum_ += error_; // 累加误差
    if(error_sum_ > intergral_up_) error_sum_ = intergral_up_; // 积分限幅
    if(error_sum_ < -1*intergral_up_) error_sum_ = -1*intergral_up_; // 积分限幅

    derror_ = error_ - prev_error_; // 计算误差变化率
    prev_error_ = error_; // 保存上一次误差
    float output = _kp * error_ + _ki * error_sum_ + _kd * derror_; // 计算输出
    if(output > out_max_) output = out_max_; // 输出限幅
    if(output < out_min_) output = out_min_; // 输出限幅
    return output;
}
void PidController::update_target(float target){
    target_ = target;
}
void PidController::update_pid(float kp, float ki, float kd){
    _kp = kp;
    _ki = ki;
    _kd = kd; 
}
void PidController::reset(){
    error_ = 0;
    error_sum_ = 0;
    derror_ = 0; 
    prev_error_ = 0;
    _kp = 0;
    _ki = 0;
    _kd = 0;
    intergral_up_ = 2500; 
    out_max_ = 0;
    out_min_ = 0;
}
void PidController::out_limit(float out_min, float out_max){
    out_max_ = out_max;
    out_min_ = out_min; 
}

PidController.h

#ifndef _PID_CONTROLLER_H_
#define _PID_CONTROLLER_H_

class PidController{
    public:
        PidController() = default;
        PidController(float kp, float ki, float kd);

    private:
        // pid 控制器参数
        float target_;// 目标值
        float out_min_;// 输出最小值
        float out_max_;// 输出最大值
        float _kp; // 比例系数
        float _ki; // 积分系数
        float _kd; // 微分系数
        float intergral_up_ = 2500; // 积分上限
        //pid 中间
        float error_; // 误差
        float error_sum_; // 误差和
        float derror_; // 误差差分
        float prev_error_; // 上次误差
        

    public:
        float update(float current);// 更新PID控制器,提供当前值,返回控制量
        void update_target(float target); // 更新目标值
        void update_pid(float kp, float ki, float kd); // 更新PID参数
        void reset(); // 重置PID控制器
        void out_limit(float out_min, float out_max); // 输出限制
        
};


#endif
// _PID_CONTROLLER_H_;


网站公告

今日签到

点亮在社区的每一天
去签到