一、项目概述
1.1 项目目标和用途
本项目旨在设计并实现一种基于STM32单片机的四旋翼无人机。该无人机系统主要应用于航拍、测绘、环境监测等领域。通过集成多种传感器和控制算法,用户能够实现高精度的飞行控制和数据监测。
1.2 项目解决的问题
传统的四旋翼无人机在飞行控制和数据传输方面存在一些问题,例如:
-
数据噪声: 传感器数据受环境噪声影响较大,导致飞行控制不稳定。
-
调参效率低: 传统无人机需要通过上位机与无人机进行有线连接,调整PID参数繁琐。
-
实时性不足: 飞行数据的实时反馈和监控能力不足,影响飞行安全。
本项目通过使用MPU9250传感器、卡尔曼滤波算法、串级PID控制和ESP8266无线通信模块,解决了上述问题,提高了无人机的飞行稳定性和操作便利性。
二、系统架构
2.1 系统架构设计
本系统的架构图显示了主要组件及其相互关系,如下所示:
2.2 组件选择
-
单片机: STM32F103系列,具备丰富的外设接口和较高的处理速度。
-
传感器: MPU9250,集成三轴加速度计和三轴陀螺仪,支持高精度姿态测量。
-
控制算法: 串级PID控制,适合非线性系统的精确控制。
-
无线通信模块: ESP8266,支持Wi-Fi通信,方便数据传输和参数调整。
三、环境搭建
3.1 开发环境安装
-
开发工具: 推荐使用STM32CubeIDE或Keil uVision进行开发。
-
库文件: 下载并安装STM32 HAL库,确保对外设的支持。
3.2 配置步骤
-
创建项目:
- 打开STM32CubeIDE,创建新的STM32项目,选择STM32F103系列单片机。
-
配置外设:
-
使用STM32CubeMX配置GPIO、I2C、UART等外设。对于MPU9250,使用I2C接口进行数据通信。
-
设置通信波特率,确保数据传输稳定。
-
-
代码示例:
// 初始化MPU9250 void MPU9250_Init() { // 配置I2C HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDR, PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, &value, sizeof(value), HAL_MAX_DELAY); // 其他寄存器的设置 }
3.3 注意事项
-
确保电源电压稳定,避免对传感器和控制器的影响。
-
在连接ESP8266时,注意供电电压和接口匹配,以防损坏模块。
四、代码实现
本节将详细介绍四旋翼无人机的各个功能模块的代码实现,包括传感器数据读取、卡尔曼滤波、PID控制及无线通信。
4.1 MPU9250数据读取模块
MPU9250是一个集成了三轴加速度计和三轴陀螺仪的传感器。我们通过I2C接口读取传感器的数据,获取无人机的加速度和角速度。
4.1.1 初始化MPU9250
#include "stm32f1xx_hal.h"
#define MPU9250_ADDR 0x68 // MPU9250 I2C地址
void MPU9250_Init(I2C_HandleTypeDef *hi2c) {
uint8_t check;
uint8_t Data;
// 检查MPU9250是否连接
HAL_I2C_Mem_Read(hi2c, MPU9250_ADDR << 1, 117, 1, &check, 1, 1000);
if (check == 0x71) { // 0x71是MPU9250的WHO_AM_I寄存器值
// 进入休眠模式
Data = 0;
HAL_I2C_Mem_Write(hi2c, MPU9250_ADDR << 1, 107, 1, &Data, 1, 1000);
// 配置传感器
Data = 0x01; // 设置加速度范围
HAL_I2C_Mem_Write(hi2c, MPU9250_ADDR << 1, 28, 1, &Data, 1, 1000);
Data = 0x00; // 设置陀螺仪范围
HAL_I2C_Mem_Write(hi2c, MPU9250_ADDR << 1, 27, 1, &Data, 1, 1000);
Data = 0x00; // 设置电源管理
HAL_I2C_Mem_Write(hi2c, MPU9250_ADDR << 1, 106, 1, &Data, 1, 1000);
}
}
4.1.2 读取传感器数据
void Read_MPU9250(I2C_HandleTypeDef *hi2c, float *accel, float *gyro) {
uint8_t data[14];
// 读取加速度和陀螺仪数据
HAL_I2C_Mem_Read(hi2c, MPU9250_ADDR << 1, 0x3B, 1, data, 14, 1000);
// 数据转换
int16_t ax = (data[0] << 8) | data[1];
int16_t ay = (data[2] << 8) | data[3];
int16_t az = (data[4] << 8) | data[5];
int16_t gx = (data[8] << 8) | data[9];
int16_t gy = (data[10] << 8) | data[11];
int16_t gz = (data[12] << 8) | data[13];
// 将原始数据转换为g和度/秒
*accel = (float)ax / 16384.0; // 加速度转换
*(accel + 1) = (float)ay / 16384.0;
*(accel + 2) = (float)az / 16384.0;
*gyro = (float)gx / 131.0; // 陀螺仪转换
*(gyro + 1) = (float)gy / 131.0;
*(gyro + 2) = (float)gz / 131.0;
}
4.2 卡尔曼滤波算法
4.2.1 卡尔曼滤波器初始化
在使用卡尔曼滤波器之前,需要初始化其参数。以下是初始化函数的实现:
void Kalman_Init(KalmanFilter *kf, float q, float r, float initial_value) {
kf->q = q; // 过程噪声
kf->r = r; // 观测噪声
kf->x = initial_value; // 初始估计值
kf->p = 1; // 初始估计误差
}
4.2.2 卡尔曼滤波算法实现
以下是卡尔曼滤波算法的实现,用于处理来自传感器的数据:
float Kalman_Update(KalmanFilter *kf, float measurement) {
// 预测更新
kf->p += kf->q;
// 计算卡尔曼增益
kf->k = kf->p / (kf->p + kf->r);
// 更新估计值
kf->x += kf->k * (measurement - kf->x);
// 更新估计误差
kf->p *= (1 - kf->k);
return kf->x; // 返回更新后的估计值
}
4.3 PID控制模块
PID控制算法用于对无人机的姿态进行控制,确保其稳定飞行。
4.3.1 PID控制器结构
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float integral; // 积分值
float last_error; // 上一次误差
} PIDController;
4.3.2 PID控制器初始化
void PID_Init(PIDController *pid, float kp, float ki, float kd) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0;
pid->last_error = 0;
}
4.3.3 PID控制算法实现
float PID_Compute(PIDController *pid, float setpoint, float measured_value, float dt) {
float error = setpoint - measured_value; // 计算误差
pid->integral += error * dt; // 积分
float derivative = (error - pid->last_error) / dt; // 微分
pid->last_error = error; // 更新上次误差
// PID输出
return pid->kp * error + pid->ki * pid->integral + pid->kd * derivative;
}
4.4 无线通信模块
ESP8266模块用于实现飞行数据的实时传输和参数的无线调节。
4.4.1 初始化ESP8266
void ESP8266_Init(UART_HandleTypeDef *huart) {
// 发送AT指令以初始化ESP8266
HAL_UART_Transmit(huart, (uint8_t *)"AT+RST\r\n", strlen("AT+RST\r\n"), HAL_MAX_DELAY);
HAL_Delay(1000); // 等待重启完成
HAL_UART_Transmit(huart, (uint8_t *)"AT+CWMODE=1\r\n", strlen("AT+CWMODE=1\r\n"), HAL_MAX_DELAY);
HAL_UART_Transmit(huart, (uint8_t *)"AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n", strlen("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"), HAL_MAX_DELAY);
}
4.4.2 发送数据
void ESP8266_Send_Data(UART_HandleTypeDef *huart, float roll, float pitch, float yaw) {
char buffer[100];
sprintf(buffer, "ROLL: %.2f, PITCH: %.2f, YAW: %.2f\r\n", roll, pitch, yaw);
HAL_UART_Transmit(huart, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
}
4.5 时序图
以下是系统中各模块之间的交互时序图,展示了数据流和控制信号的传递过程。
4.6 主程序结构
以下是主程序的基本结构,展示了如何将上述模块集成到一起:
#include "stm32f1xx_hal.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
KalmanFilter kf[3]; // 一个用于每个轴
PIDController pid_roll, pid_pitch, pid_yaw;
float roll, pitch, yaw; // 姿态角
void main() {
HAL_Init();
SystemClock_Config();
MPU9250_Init(&hi2c1);
ESP8266_Init(&huart1);
// 初始化卡尔曼滤波器
for (int i = 0; i < 3; i++) {
Kalman_Init(&kf[i], 0.001, 0.01, 0);
}
// 初始化PID控制器
PID_Init(&pid_roll, 1.0, 0.1, 0.01);
PID_Init(&pid_pitch, 1.0, 0.1, 0.01);
PID_Init(&pid_yaw, 1.0, 0.1, 0.01);
while (1) {
float accel[3], gyro[3];
Read_MPU9250(&hi2c1, accel, gyro);
// 更新卡尔曼滤波器
roll = Kalman_Update(&kf[0], gyro[0]);
pitch = Kalman_Update(&kf[1], gyro[1]);
yaw = Kalman_Update(&kf[2], gyro[2]);
// 计算PID控制信号
float roll_control = PID_Compute(&pid_roll, desired_roll, roll, 0.01);
float pitch_control = PID_Compute(&pid_pitch, desired_pitch, pitch, 0.01);
float yaw_control = PID_Compute(&pid_yaw, desired_yaw, yaw, 0.01);
// 发送控制信号到电机
Drive_Motors(roll_control, pitch_control, yaw_control);
// 发送数据到ESP8266
ESP8266_Send_Data(&huart1, roll, pitch, yaw);
HAL_Delay(10); // 延时10ms
}
}
4.7 驱动电机函数
下面是一个简单的电机驱动函数,它将PID控制输出转换为电机驱动信号。
void Drive_Motors(float roll_signal, float pitch_signal, float yaw_signal) {
// 将PID输出转换为PWM信号,控制电机速度
uint16_t motor1_speed = (uint16_t)(1500 + roll_signal + pitch_signal + yaw_signal);
uint16_t motor2_speed = (uint16_t)(1500 - roll_signal + pitch_signal - yaw_signal);
uint16_t motor3_speed = (uint16_t)(1500 + roll_signal - pitch_signal - yaw_signal);
uint16_t motor4_speed = (uint16_t)(1500 - roll_signal - pitch_signal + yaw_signal);
// 设置PWM信号,控制电机
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, motor1_speed);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, motor2_speed);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, motor3_speed);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, motor4_speed);
}
五、项目总结
5.1 项目功能
本项目成功设计并实现了一种基于STM32单片机的四旋翼无人机,具备以下主要功能:
-
实时数据采集:通过MPU9250传感器,实时获取无人机的三轴加速度和三轴角速度数据,为姿态控制提供基础。
-
数据噪声处理:使用卡尔曼滤波算法对传感器数据进行处理,有效去除了环境噪声,提高了数据的准确性和可靠性。
-
高效姿态控制:采用串级PID控制算法,能够在飞行过程中精确调节无人机的姿态,确保飞行的稳定性和安全性。
-
无线通信:利用ESP8266无线模块,实现飞行数据的实时回传,并支持用户通过无线方式调整PID参数,提升了操作的便捷性。
5.2 实现过程
项目的实现过程主要分为以下几个步骤:
-
硬件设计:选择合适的单片机(STM32F103)、传感器(MPU9250)和无线模块(ESP8266),并进行电路设计和连接。
-
软件环境搭建:使用STM32CubeIDE进行开发,配置外设(I2C、UART等),确保与硬件的兼容性。
-
模块开发:逐步实现各个功能模块,首先完成MPU9250的数据读取,然后实现卡尔曼滤波和PID控制算法,最后集成ESP8266进行无线通信。
-
系统集成与调试:将各个模块整合到主程序中,进行系统调试,确保数据流和控制信号的准确性。
-
性能测试:通过多次测试,评估无人机的飞行稳定性和控制精度,根据测试结果调整PID参数和滤波器设置。