【花雕学编程】Arduino PID 之姿态控制与多点校准

在这里插入图片描述

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述
在 Arduino 系统中,PID 算法主要用于对各种物理量(如温度、速度、位置等)进行精确控制。例如,通过连接温度传感器到 Arduino,利用 PID 算法可以精准控制加热或制冷设备,使温度稳定在设定值;在电机控制中,PID 可以根据目标速度和实际速度的偏差来调整电机的驱动信号,实现稳定的转速控制。

主要特点
1、实时反馈控制:PID控制器能够实时处理系统误差,通过比例、积分和微分三部分的调节,快速响应外部扰动,保持系统的稳定性。
2、简单易用:PID控制算法相对简单,易于实现和调试,适合大多数嵌入式系统和实时控制应用。
3、适应性强:PID控制器可以根据系统的动态特性进行调整,适应不同的负载和工作条件,保持良好的控制效果。
4、高精度控制:PID控制能够快速且准确地调整电机速度,确保电机在各种工况下都能稳定地达到设定速度,减少稳态误差。
5、良好的动态响应:通过调整比例、积分和微分参数,控制系统能够快速响应速度变化,适应负载变化和外部扰动,保持系统的稳定性。

应用场景
1、机器人运动控制:在机器人技术中,基于速度闭环的PID控制可以用于电机的速度调节,实现精确的运动控制,提高机器人的灵活性和稳定性。
2、自动化生产线:在自动化设备中,如传送带和机械手臂,PID控制能够确保各个设备的速度稳定,提高生产效率和产品质量。
3、电动工具:在电动工具(如电钻、切割机等)中,PID控制可以实现对电机转速的精确调节,满足不同工作条件的需要。
4、风扇和泵控制:在风扇和水泵等设备中,PID控制能够根据需求自动调节转速,提供适合的流量和风速,提高系统的能效。
5、电动车辆:在电动交通工具中,速度闭环PID控制可以用于电机的速度调节,提升驾驶的平顺性和安全性。

需要注意的事项
1、参数调试:PID控制器的效果高度依赖于参数设置,开发者需要进行细致的调试,以防止系统震荡或响应不及时。
2、传感器校准:使用PID控制时,需要定期校准传感器,以确保数据准确性,特别是在不同的环境条件下使用时。
3、数据融合:在控制中,可以考虑使用数据融合算法(如互补滤波或卡尔曼滤波)来提高姿态估计的稳定性和准确性。
4、电源管理:确保电源供应稳定且符合电机的工作要求,以避免电压波动对电机驱动性能造成影响。
5、热管理:设计合适的散热方案,以防止电机和驱动器过热,影响系统性能和寿命。

在这里插入图片描述
姿态控制
主要特点
高精度控制:通过 PID 算法,能够根据传感器反馈的姿态信息,精确地计算出控制量,从而实现对物体姿态的高精度控制。例如,在四轴飞行器中,可以将飞行姿态控制在很小的误差范围内。
实时性强:可以快速响应姿态的变化,及时调整控制输出。由于 Arduino 具有一定的实时处理能力,结合 PID 算法的快速计算,能够在短时间内对姿态偏差做出反应,确保物体姿态的稳定性。
适应性好:PID 控制器的参数可以根据不同的应用场景和物体特性进行调整,以适应各种复杂的姿态控制需求。无论是在静止状态下保持姿态,还是在运动过程中改变姿态,都能通过合理调整参数实现较好的控制效果。
应用场景
航空航天领域:如无人机、卫星等。无人机需要通过姿态控制来保持稳定飞行,实现各种飞行任务,如定点悬停、航线飞行等。卫星则需要精确控制姿态,以保证其太阳能板对准太阳,以及天线对准地面接收站等。
机器人领域:机器人的行走、转弯、手臂操作等动作都涉及到姿态控制。例如,人形机器人在行走过程中需要不断调整身体姿态以保持平衡;机械臂在抓取和放置物体时,需要精确控制手臂的姿态,以确保准确操作。
虚拟现实与增强现实设备:头戴式显示设备需要精确的姿态控制来实时跟踪用户的头部运动,为用户提供逼真的沉浸式体验。通过姿态控制,设备能够快速准确地将虚拟场景与用户的实际头部姿态相匹配。
注意事项
传感器精度:姿态控制高度依赖传感器提供的准确信息,如陀螺仪、加速度计等。传感器的精度直接影响姿态控制的效果,因此要选择高精度的传感器,并进行定期校准,以减少测量误差。
参数调整:PID 参数的调整是一个复杂且关键的过程。不同的物体和应用场景需要不同的参数组合。一般需要通过多次实验和调试,根据实际的姿态控制效果来逐步优化参数,以达到最佳的控制性能。
系统稳定性:在姿态控制中,要确保整个系统的稳定性。特别是在存在外部干扰的情况下,如风力、振动等,系统可能会出现不稳定的情况。可以采用一些滤波算法对传感器数据进行处理,增强系统的抗干扰能力,保证姿态控制的稳定性。

多点校准
主要特点
提高准确性:通过在多个点进行校准,可以更全面地考虑系统在不同工作点的特性,从而提高姿态控制的准确性。与单点校准相比,多点校准能够更好地适应系统参数在不同状态下的变化,减少误差。
增强鲁棒性:多点校准可以使系统在不同的工作条件下都能保持较好的性能,增强了系统的鲁棒性。即使系统受到一定的干扰或工作环境发生变化,由于经过了多个点的校准,仍然能够较为准确地控制姿态。
灵活性:可以根据具体的应用需求选择不同的校准点,具有较高的灵活性。例如,可以根据物体的运动范围、不同的姿态角度等因素来确定校准点的位置和数量,以满足不同场景下的姿态控制要求。
应用场景
高精度工业设备:在一些需要高精度姿态控制的工业设备中,如光刻机、半导体制造设备等,多点校准可以确保设备在不同的工作位置和姿态下都能保持高精度的运行,提高产品质量和生产效率。
航空航天精密仪器:对于航空航天领域中的一些精密仪器,如惯性导航系统、天文观测设备等,多点校准能够提高其姿态控制的精度和可靠性,保证在复杂的空间环境中准确工作。
医疗设备:某些医疗设备,如手术机器人、医疗影像设备等,需要精确的姿态控制来实现准确的诊断和治疗。多点校准可以使这些设备在不同的操作场景下都能提供稳定、准确的姿态控制,提高医疗操作的安全性和准确性。
注意事项
校准点选择:校准点的选择要具有代表性和合理性,能够覆盖系统的主要工作范围和不同的工作状态。如果校准点选择不当,可能无法全面反映系统的特性,导致校准效果不佳。
校准精度:在进行多点校准时,要保证每个校准点的校准精度。这需要使用高精度的校准设备和方法,并且在校准过程中要严格按照操作规程进行,以确保校准结果的准确性。
数据处理与存储:多点校准会产生大量的数据,需要对这些数据进行有效的处理和存储。合理的数据处理方法可以帮助提取有用的信息,优化校准参数。同时,要确保数据的安全性和可访问性,以便在需要时能够及时调用和更新校准数据。

在这里插入图片描述
1、带有校准功能的姿态控制

#include <PID_v1.h>
#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;
double setPoint = 0; // 目标角度
double input, output;
double calibrationOffset = 0; // 校准偏移

double kp = 2, ki = 5, kd = 1;
PID myPID(&input, &output, &setPoint, kp, ki, kd, DIRECT);

void setup() {
    Serial.begin(9600);
    Wire.begin();
    mpu.initialize();
    calibrate(); // 开始校准
    myPID.SetMode(AUTOMATIC);
}

void loop() {
    input = mpu.getAccelerationY() - calibrationOffset; // 应用校准偏移

    // PID 控制
    myPID.Compute();

    // 控制电机输出
    analogWrite(9, output);

    // 打印信息
    Serial.print("Input Angle: ");
    Serial.print(input);
    Serial.print(" SetPoint: ");
    Serial.println(setPoint);
    delay(100);
}

void calibrate() {
    double sum = 0;
    const int samples = 100;

    for (int i = 0; i < samples; i++) {
        sum += mpu.getAccelerationY();
        delay(10);
    }
    calibrationOffset = sum / samples; // 计算平均值作为校准偏移
}

要点解读:
姿态控制基础:使用 MPU6050 传感器读取设备的加速度,以获取姿态信息。
校准功能:通过在启动时读取多个样本并计算平均值,得出一个校准偏移量,确保传感器的准确性。
PID 控制算法:使用 PID 控制器来计算电机的控制输出。通过 myPID.Compute() 方法根据当前输入与目标姿态之间的误差来调整输出。
数据输出与监测:通过串口输出当前姿态、目标姿态和其他信息,便于实时监测和调试。
实时反馈:利用串口输出当前状态和 PID 参数,便于监控和调试。

2、用户输入控制目标姿态

#include <PID_v1.h>
#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;
double setPoint = 0; // 目标角度
double input, output;
double calibrationOffset = 0; // 校准偏移

double kp = 2, ki = 5, kd = 1;
PID myPID(&input, &output, &setPoint, kp, ki, kd, DIRECT);

void setup() {
    Serial.begin(9600);
    Wire.begin();
    mpu.initialize();
    calibrate(); // 开始校准
    myPID.SetMode(AUTOMATIC);
}

void loop() {
    input = mpu.getAccelerationY() - calibrationOffset; // 应用校准偏移

    // 用户输入调整目标姿态
    if (Serial.available()) {
        char command = Serial.read();
        if (command == 'u') { // 增加目标姿态
            setPoint += 1;
        } else if (command == 'd') { // 减少目标姿态
            setPoint -= 1;
        }
    }

    // PID 控制
    myPID.Compute();

    // 控制电机输出
    analogWrite(9, output);

    // 打印信息
    Serial.print("Input Angle: ");
    Serial.print(input);
    Serial.print(" SetPoint: ");
    Serial.println(setPoint);
    delay(100);
}

void calibrate() {
    double sum = 0;
    const int samples = 100;

    for (int i = 0; i < samples; i++) {
        sum += mpu.getAccelerationY();
        delay(10);
    }
    calibrationOffset = sum / samples; // 计算平均值作为校准偏移
}

要点解读:
用户交互:允许用户通过串口输入调整目标姿态。用户可以通过输入 ‘u’(增加)和 ‘d’(减少)来手动控制目标姿态,增加了系统的灵活性。
姿态控制基础:使用 MPU6050 传感器读取设备的加速度,以获取姿态信息。
校准功能:通过在启动时读取多个样本并计算平均值,得出一个校准偏移量,确保传感器的准确性。
PID 控制算法:使用 PID 控制器来计算电机的控制输出。通过 myPID.Compute() 方法根据当前输入与目标姿态之间的误差来调整输出。
数据输出与监测:通过串口输出当前姿态、目标姿态和其他信息,便于实时监测和调试。

3、姿态控制与多点校准

#include <PID_v1.h>

const int motorPin = 9;      // 电机引脚
const int angleSensorPin = A0; // 角度传感器引脚

double setpoint, input, output;
double Kp = 2.0, Ki = 5.0, Kd = 1.0;

PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

void setup() {
    Serial.begin(115200);
    pinMode(motorPin, OUTPUT);

    setpoint = 0; // 设定目标姿态为0度
    myPID.SetMode(AUTOMATIC);

    // 执行多点校准
    multiPointCalibration();
}

void loop() {
    // 读取角度传感器输入
    int sensorValue = analogRead(angleSensorPin);
    input = map(sensorValue, 0, 1023, -30, 30); // 假设角度范围为-30到30度

    myPID.Compute(); // 计算PID输出

    // 限制输出范围
    if (output > 255) output = 255;
    if (output < 0) output = 0;

    analogWrite(motorPin, output); // 控制电机

    // 串口输出
    Serial.print("Current Angle: ");
    Serial.print(input);
    Serial.print("°, Motor Output: ");
    Serial.println(output);

    delay(100);
}

void multiPointCalibration() {
    Serial.println("Performing Multi-Point Calibration...");
    for (int i = -2; i <= 2; i++) {
        setpoint = i * 10; // 设置不同的目标姿态进行校准
        delay(2000); // 等待稳定
        Serial.print("Calibrating at setpoint: ");
        Serial.println(setpoint);
        // 这里可以添加读取传感器和存储校准数据的逻辑
    }
    Serial.println("Multi-Point Calibration complete.");
}

要点解读:
多点校准:在 setup() 中执行多点校准,模拟多种目标姿态的校准过程。
循环校准:通过循环设置不同的目标姿态,观察稳定性并进行校准。
PID 控制实现:根据当前角度动态调整电机输出,以保持目标姿态。
输出限制:确保电机输出在合法范围内(0到255)。
实时监测:通过串口输出当前角度和电机输出,便于调试和观察控制效果。

在这里插入图片描述

4、平衡小车姿态控制

#include <PID_v1.h>
#include <MPU6050.h>

// 定义引脚
const int motorPinA = 9;
const int motorPinB = 10;

// 定义变量
double setpoint = 0;  // 目标角度(平衡点)
double input, output;

// 定义PID参数
double Kp = 2, Ki = 5, Kd = 1;
PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

MPU6050 mpu;

void setup() {
  Wire.begin();
  mpu.initialize();
  pinMode(motorPinA, OUTPUT);
  pinMode(motorPinB, OUTPUT);
  
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-255, 255);
}

void loop() {
  int16_t ax, ay, az;
  int16_t gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // 计算角度
  input = atan2(ay, az) * 180 / PI;  // 转换为角度
  myPID.Compute();  // 计算PID输出
  
  if (output > 0) {
    analogWrite(motorPinA, output);  // 正向转动
    analogWrite(motorPinB, 0);
  } else {
    analogWrite(motorPinA, 0);
    analogWrite(motorPinB, -output);  // 反向转动
  }
  delay(10);  // 控制循环时间
}

要点解读:

MPU6050读取:通过MPU6050传感器读取加速度和陀螺仪数据。

角度计算:使用加速度计数据计算当前角度。

PID控制:使用PID控制器调整电机输出,使小车保持平衡。

双向控制:PID输出可以是正负值,以实现双向控制。

5、无人机姿态控制

#include <PID_v1.h>
#include <MPU6050.h>

// 定义引脚
const int motorPin1 = 9;
const int motorPin2 = 10;
const int motorPin3 = 11;
const int motorPin4 = 12;

// 定义变量
double setpointRoll = 0, setpointPitch = 0;  // 目标滚转和俯仰角度
double inputRoll, inputPitch, outputRoll, outputPitch;

// 定义PID参数
double Kp = 2, Ki = 5, Kd = 1;
PID pidRoll(&inputRoll, &outputRoll, &setpointRoll, Kp, Ki, Kd, DIRECT);
PID pidPitch(&inputPitch, &outputPitch, &setpointPitch, Kp, Ki, Kd, DIRECT);

MPU6050 mpu;

void setup() {
  Wire.begin();
  mpu.initialize();
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  
  pidRoll.SetMode(AUTOMATIC);
  pidPitch.SetMode(AUTOMATIC);
  pidRoll.SetOutputLimits(-255, 255);
  pidPitch.SetOutputLimits(-255, 255);
}

void loop() {
  int16_t ax, ay, az;
  int16_t gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // 计算滚转和俯仰角度
  inputRoll = atan2(ay, az) * 180 / PI;  // 滚转角度
  inputPitch = atan2(ax, az) * 180 / PI;  // 俯仰角度
  
  pidRoll.Compute();  // 计算滚转PID输出
  pidPitch.Compute();  // 计算俯仰PID输出
  
  // 调整电机输出
  analogWrite(motorPin1, 128 + outputRoll + outputPitch);
  analogWrite(motorPin2, 128 - outputRoll + outputPitch);
  analogWrite(motorPin3, 128 + outputRoll - outputPitch);
  analogWrite(motorPin4, 128 - outputRoll - outputPitch);
  
  delay(10);  // 控制循环时间
}

要点解读:

MPU6050读取:通过MPU6050传感器读取加速度和陀螺仪数据。

角度计算:使用加速度计数据计算滚转和俯仰角度。

PID控制:使用两个PID控制器分别调整滚转和俯仰角度。

电机调整:根据PID输出调整四个电机的输出,以保持无人机平衡。

6、机械臂姿态控制与多点校准

#include <PID_v1.h>
#include <Servo.h>

// 定义引脚
const int servoPin1 = 9;
const int servoPin2 = 10;

// 定义变量
double setpoint1 = 90, setpoint2 = 90;  // 目标角度
double input1, input2, output1, output2;

// 定义PID参数
double Kp = 2, Ki = 5, Kd = 1;
PID pid1(&input1, &output1, &setpoint1, Kp, Ki, Kd, DIRECT);
PID pid2(&input2, &output2, &setpoint2, Kp, Ki, Kd, DIRECT);

Servo servo1;
Servo servo2;

void setup() {
  servo1.attach(servoPin1);
  servo2.attach(servoPin2);
  
  pid1.SetMode(AUTOMATIC);
  pid2.SetMode(AUTOMATIC);
  pid1.SetOutputLimits(0, 180);
  pid2.SetOutputLimits(0, 180);
}

void loop() {
  // 读取当前角度(假设通过传感器读取)
  input1 = readAngle1();  // 读取第一个关节角度
  input2 = readAngle2();  // 读取第二个关节角度
  
  pid1.Compute();  // 计算第一个关节PID输出
  pid2.Compute();  // 计算第二个关节PID输出
  
  servo1.write(output1);  // 设置第一个关节角度
  servo2.write(output2);  // 设置第二个关节角度
  
  delay(10);  // 控制循环时间
}

double readAngle1() {
  // 模拟读取角度
  return analogRead(A0) * 180.0 / 1023.0;
}

double readAngle2() {
  // 模拟读取角度
  return analogRead(A1) * 180.0 / 1023.0;
}

要点解读:

角度读取:通过传感器读取机械臂关节的当前角度。

PID控制:使用PID控制器调整关节角度,使其接近目标角度。

伺服控制:通过伺服电机控制机械臂关节的角度。

多点校准:通过设置不同的目标角度,实现机械臂的多点校准。

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

「雕爷编程Arduino动手做寻迹的实验可以使用TCRT5000红外反射光电开关寻迹传感器模块。这个传感器模块可以通过检测周围的光反射来进行寻迹操作。你可以将这个模块连接到mBot的主控板mCore V1.5的RJ25接口上,因为mBot的主控板兼容Arduino系统,所以你可以使用Arduino编程语言来控制mBot进行寻迹操作。请参考【Arduino】168种传感器模块系列实验中的实验六十六,该实验详细介绍了如何使用TCRT5000红外反射光电开关寻迹传感器模块进行寻迹。祝你成功完成实验!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【雕爷编程Arduino动手做(194)---makeblock mbot 主控板2](https://blog.csdn.net/weixin_41659040/article/details/132141677)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [【雕爷编程Arduino动手做(65)---红外寻迹传感器](https://blog.csdn.net/weixin_41659040/article/details/106604080)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值