STM32智能平衡车项目实战:PID控制算法与蓝牙通信技术的应用

一、项目概述

项目目标和用途

本项目旨在设计和实现一款基于STM32单片机的平衡车。平衡车是一种新型的个人交通工具,广泛应用于短途出行、休闲娱乐等场景。通过本项目,我们希望能够实现一款具备良好稳定性和操控性的平衡车,能够在不同的地形上自如行驶。

解决的问题和带来的价值

平衡车的核心问题在于如何保持其平衡。传统的平衡车往往依赖于复杂的控制算法和高精度的传感器。通过本项目,我们将利用STM32的强大计算能力和多种传感器的结合,解决平衡控制的问题,提高平衡车的稳定性和安全性。此外,平衡车的设计将为用户提供更为便捷的出行方式,提升生活质量。

二、系统架构

系统架构设计

本项目的系统架构主要由以下几个部分组成:

  1. 控制单元:STM32单片机作为核心控制器,负责数据处理和控制算法的实现。

  2. 传感器模块:包括陀螺仪和加速度计,用于实时获取平衡车的姿态信息。

  3. 驱动模块:电机驱动模块,负责控制平衡车的前进、后退和转向。

  4. 通信模块:无线通信模块(如蓝牙或Wi-Fi),用于与手机或其他设备进行数据交互。

选择的硬件和技术栈

  • 单片机:STM32F103C8T6,具备较高的处理能力和丰富的外设接口。

  • 传感器:MPU6050(陀螺仪和加速度计组合),用于获取车体的姿态信息。

  • 电机驱动:L298N电机驱动模块,能够控制直流电机的正反转。

  • 无线通信:HC-05蓝牙模块,用于与手机进行数据通信。

  • 系统架构图

    控制

    数据采集

    无线通信

    姿态信息

    STM32单片机

    电机驱动模块

    MPU6050传感器

    HC-05蓝牙模块

    三、环境示例和注意事项

    环境示例

  • 开发环境:使用Keil uVision或STM32CubeIDE进行代码编写和调试。

  • 硬件环境:搭建平衡车原型,确保电源稳定,连接各个模块时注意引脚对应。

  • 注意事项

    1. 电源管理:确保电源电压和电流满足各个模块的需求,避免因电源不足导致系统不稳定。

    2. 传感器校准:在使用MPU6050之前,需进行校准,以确保获取的数据准确。

    3. 代码调试:在调试过程中,建议逐步测试每个模块,确保其功能正常后再进行整体集成。

    四、代码实现

    在本节中,我们将详细介绍平衡车各个模块的代码实现,包括控制模块、传感器模块和电机驱动模块。每个模块的代码都将附有详细的说明,最后将展示模块之间的时序图。

    4.1 控制模块

    控制模块的主要功能是接收传感器数据,计算所需的电机速度,并根据控制算法调整电机的运行状态。我们将使用PID控制算法来实现平衡控制。

    代码示例
    #include "stm32f10x.h"
    #include "MPU6050.h"
    #include "Motor.h"
    
    // PID控制参数
    #define KP 1.0f  // 比例系数
    #define KI 0.1f  // 积分系数
    #define KD 0.01f // 微分系数
    
    float previous_error = 0; // 上一次误差
    float integral = 0;       // 积分值
    
    // 计算PID控制输出
    float CalculatePID(float setpoint, float measured_value) {
        float error = setpoint - measured_value; // 计算误差
        integral += error;                        // 积分
        float derivative = error - previous_error; // 微分
        previous_error = error;                   // 更新上一次误差
    
        // PID输出
        return (KP * error) + (KI * integral) + (KD * derivative);
    }
    
    // 控制循环
    void ControlLoop(void) {
        float angle = GetAngle(); // 获取当前角度
        float speed = CalculatePID(0.0f, angle); // 计算电机速度
        SetMotorSpeed(speed); // 设置电机速度
    }
    
    int main(void) {
        SystemInit(); // 系统初始化
        MPU6050_Init(); // 初始化MPU6050传感器
        Motor_Init(); // 初始化电机驱动模块
    
        while (1) {
            ControlLoop(); // 持续执行控制循环
        }
    }
    
    代码说明
  • PID控制参数:定义了比例、积分和微分系数,用于PID控制算法。

  • CalculatePID:计算PID控制输出,接受设定值和测量值作为参数,返回控制输出。

  • ControlLoop:在该函数中获取当前角度并计算电机速度,然后调用SetMotorSpeed函数设置电机速度。

  • main函数:初始化系统、传感器和电机驱动模块,并进入无限循环执行控制逻辑。

  • 4.2 传感器模块

    传感器模块负责获取平衡车的姿态信息。我们使用MPU6050传感器来获取加速度和角速度数据,并计算出当前的倾斜角度。

    代码示例
    #include "MPU6050.h"
    #include "I2C.h"
    
    // MPU6050寄存器地址
    #define MPU6050_ADDR 0x68
    #define PWR_MGMT_1 0x6B
    #define ACCEL_XOUT_H 0x3B
    #define GYRO_XOUT_H 0x43
    
    // 初始化MPU6050
    void MPU6050_Init(void) {
        I2C_Init(); // 初始化I2C
        I2C_WriteByte(MPU6050_ADDR, PWR_MGMT_1, 0x00); // 唤醒MPU6050
    }
    
    // 读取MPU6050数据
    void ReadMPU6050(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz) {
        uint8_t buffer[14];
        I2C_ReadBytes(MPU6050_ADDR, ACCEL_XOUT_H, buffer, 14); // 读取14个字节的数据
    
        // 解析加速度和陀螺仪数据
        *ax = (int16_t)((buffer[0] << 8) | buffer[1]);
        *ay = (int16_t)((buffer[2] << 8) | buffer[3]);
        *az = (int16_t)((buffer[4] << 8) | buffer[5]);
        *gx = (int16_t)((buffer[8] << 8) | buffer[9]);
        *gy = (int16_t)((buffer[10] << 8) | buffer[11]);
        *gz = (int16_t)((buffer[12] << 8) | buffer[13]);
    }
    
    // 计算倾斜角度
    float GetAngle(void) {
        int16_t ax, ay, az, gx, gy, gz;
        ReadMPU6050(&ax, &ay, &az, &gx, &gy, &gz); // 读取传感器数据
    
        // 计算倾斜角度(使用简单的低通滤波器)
        float angle = atan2(ay, az) * 180.0 / M_PI; // 计算倾斜角度(单位:度)
    
        return angle; // 返回计算得到的角度
    }
    
    代码说明
  • MPU6050_Init:初始化MPU6050传感器,唤醒传感器以开始工作。

  • ReadMPU6050:从MPU6050读取加速度和陀螺仪数据。该函数使用I2C协议读取14个字节的数据,并解析出加速度(ax, ay, az)和角速度(gx, gy, gz)。

  • GetAngle:计算倾斜角度。使用atan2函数根据加速度数据计算出当前的倾斜角度,并将其转换为度数。

  • 4.3 电机驱动模块

    电机驱动模块负责控制平衡车的前进、后退和转向。我们将使用L298N电机驱动模块来控制直流电机的正反转。

    代码示例
    #include "Motor.h"
    #include "stm32f10x_gpio.h"
    
    // 定义电机控制引脚
    #define MOTOR_A_PWM_PIN GPIO_Pin_6 // PWM引脚
    #define MOTOR_A_DIR_PIN GPIO_Pin_7 // 方向引脚
    #define MOTOR_B_PWM_PIN GPIO_Pin_8 // PWM引脚
    #define MOTOR_B_DIR_PIN GPIO_Pin_9 // 方向引脚
    
    // 初始化电机驱动模块
    void Motor_Init(void) {
        // 配置GPIO引脚
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
    
        GPIO_InitStructure.GPIO_Pin = MOTOR_A_PWM_PIN | MOTOR_A_DIR_PIN | MOTOR_B_PWM_PIN | MOTOR_B_DIR_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速度50MHz
        GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIO
    }
    
    // 设置电机速度
    void SetMotorSpeed(float speed) {
        if (speed > 0) {
            // 正转
            GPIO_SetBits(GPIOA, MOTOR_A_DIR_PIN); // 设置方向
            GPIO_ResetBits(GPIOA, MOTOR_B_DIR_PIN); // 设置方向
        } else {
            // 反转
            GPIO_ResetBits(GPIOA, MOTOR_A_DIR_PIN); // 设置方向
            GPIO_SetBits(GPIOA, MOTOR_B_DIR_PIN); // 设置方向
        }
    
        // 设置PWM信号
        speed = fabs(speed); // 取绝对值
        if (speed > 100) speed = 100; // 限制最大速度
        TIM_SetCompare1(TIM2, speed); // 设置PWM占空比
    }
    
    代码说明
  • Motor_Init:初始化电机驱动模块,配置GPIO引脚为推挽输出模式。

  • SetMotorSpeed:根据输入的速度值设置电机的转动方向和PWM信号。正值表示前进,负值表示后退。使用TIM_SetCompare1设置PWM的占空比来控制电机速度。

  • 4.4 模块之间的时序图

    以下是各个模块之间的时序图,展示了数据流和控制逻辑的顺序。

    STM32单片机

    MPU6050传感器

    电机驱动模块

    初始化传感器

    传感器初始化完成

    读取传感器数据

    返回加速度和角速度数据

    计算当前角度

    计算电机速度 (PID控制)

    设置电机速度

    loop

    [控制循环]

    STM32单片机

    MPU6050传感器

    电机驱动模块

    时序图说明
    1. 初始化阶段:

    2. STM32单片机向MPU6050传感器发送初始化命令,传感器完成初始化后返回确认信息。
    3. 控制循环:

    4. 在控制循环中,STM32单片机定期向MPU6050传感器请求数据,获取加速度和角速度信息。

    5. 传感器返回读取到的加速度和角速度数据。

    6. STM32单片机根据传感器数据计算当前的倾斜角度。

    7. 使用PID控制算法计算出电机的速度。

    8. 最后,STM32单片机将计算出的电机速度发送给电机驱动模块,控制电机的转动方向和速度。

    五、项目总结

    本项目成功设计并实现了一款基于STM32单片机的平衡车,主要功能和实现过程如下:

    1. 项目目标:

    2. 设计一款具备良好稳定性和操控性的平衡车,能够在不同地形上自如行驶。
    3. 系统架构:

    4. 系统由控制单元(STM32单片机)、传感器模块(MPU6050)、电机驱动模块(L298N)和无线通信模块(HC-05)组成。

    5. 采用了PID控制算法来实现平衡控制,确保平衡车在行驶过程中保持稳定。

    6. 模块实现:

    7. 控制模块:负责接收传感器数据,计算电机速度,并通过PID控制算法调整电机的运行状态。

    8. 传感器模块:使用MPU6050传感器获取加速度和角速度数据,并计算出当前的倾斜角度。

    9. 电机驱动模块:通过L298N电机驱动模块控制电机的正反转和速度。

    10. 代码实现:

    11. 代码结构清晰,模块化设计使得各个功能模块之间的耦合度低,便于后续的维护和扩展。

    12. 采用了适当的注释和说明,确保代码逻辑易于理解。

    13. 未来改进方向:

    14. 可以考虑增加更多的传感器(如GPS、超声波传感器等)以增强平衡车的功能。

    15. 进一步优化PID控制算法,提高平衡车的响应速度和稳定性。

    16. 增加手机APP控制功能,提升用户体验。

    作者:极客小张

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32智能平衡车项目实战:PID控制算法与蓝牙通信技术的应用

    发表回复