一、背景
随着人口老龄化的不断加剧,老年人的健康和安全问题备受关注。本设计旨在利用STM32单片机与MPU6050传感器相结合,实现基于角度变化的跌倒检测系统。这一系统不仅能够快速、准确地检测老年人是否发生跌倒,还通过整合通信模块实现了实时的跌倒提醒功能。设计目标包括通过C编写MPU6050传感器的驱动代码和数据滤波算法,确保系统对身体姿态的敏感性和准确性。同时,通过整合通信模块,老年人在发生跌倒时能够及时地向特定用户发送提醒信息,包括短信和坐标,以便他们能够及时作出相应的帮助。为确保系统的可用性和便携性,本设计采用小型电池供电,使老年人可以随时随地使用。
注:本设计由于前期调研不够充分,没有GPS模块,也没有无线传输功能。
二、项目材料清单
面包板已经各种公母线
stm32f103c8t6
蜂鸣器
0.96寸OLED显示模块
CH340串口
ESP8266-01s
三、主控器与传感器的连接
电路连接图
这里因为我已经将原来的电路给拆了,所以只能照着这张图去给大家说下,GND和VCC就省去了。
蜂鸣器:I/O 与PB12相接
OLED:SCL与PB8,SDAPB9
MPU6050:SCL与PB10,SDA与PB11
串口:TXD与PA10,RXD与PA9
ESP8266-01s我没有驱动成功,所以放在这里只是一个摆设。需要注意的是MPU6050最好像我这样连接,因为我们需要通过它获取俯仰角和翻滚角,要保证模块的平稳。
通过串口发送数据
四、跌倒检测算法的设计
使用MPU6050传感器获取加速度计和陀螺仪的原始数据,通过STM32的I2C接口与MPU6050进行通信,读取加速度和角速度数据。该算法可以根据以下步骤来实现
步骤:
1. 计算加速度计推导的俯仰角和横滚角:
a. 使用 atan2(AY, sqrt(AX * AX + AZ * AZ)) 计算 accPitch,将结果转换为角度。
b. 使用 atan2(-AX, AZ) 计算 accRoll,将结果转换为角度。
2. 对陀螺仪数据进行角速度积分:
a. 通过积分陀螺仪数据 GY,按照灵敏度系数(131.0)进行缩放,计算 gyroPitch。
b. 通过积分陀螺仪数据 GX,使用相同的灵敏度系数,计算 gyroRoll。
3. 应用互补滤波:
a. 将互补滤波系数 alpha 定义为 0.98。
b. 利用互补滤波,结合加速度计推导的角度(accPitch、accRoll)和陀螺仪积分得到的角度(gyroPitch、gyroRoll):
4. 输出:
更新后的俯仰角和横滚角代表设备平稳和稳定的方向。
下面是我写的伪代码,帮助大家理解这里:
Algorithm UpdateAttitude(int16_t AX, int16_t AY, int16_t AZ, int16_t GX, int16_t GY, int16_t GZ): |
Input: Acceleration and gyroscope data (AX, AY, AZ, GX, GY, GZ) Output: None (updates global variables pitch and roll) 1:accPitch = atan2(AY, sqrt(AX * AX + AZ * AZ)) * (180.0 / M_PI) 2:accRoll = atan2(-AX, AZ) * (180.0 / M_PI) 3:gyroPitch = pitch + (float)GY / 131.0 4:gyroRoll = roll + (float)GX / 131.0 5:alpha = 0.98 6:pitch = alpha * gyroPitch + (1.0 - alpha) * accPitch 7:roll = alpha * gyroRoll + (1.0 - alpha) * accRoll |
五、主逻辑代码
软件使用的Keil5,这些库函数都可以从江科大的视频获得,所以这里仅仅展示主逻辑代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"
#include "Buzzer.h"
#include "Serial.h"
#include <math.h>
#include <stdbool.h>
bool pose1 = true;
bool pose2 = true;
#define M_PI (3.14159265358979323846264338327950288)
uint8_t ID; //定义用于存放ID号的变量
int16_t AX, AY, AZ, GX, GY, GZ; //定义用于存放各个数据的变量
// 定义全局变量用于存储姿态角度
float pitch = 0.0; // 俯仰角
float roll = 0.0; // 横滚角
// 定义函数进行姿态检测
void UpdateAttitude(int16_t AX, int16_t AY, int16_t AZ, int16_t GX, int16_t GY, int16_t GZ) {
// 加速度计的角度计算
float accPitch = atan2(AY, sqrt(AX * AX + AZ * AZ)) * (180.0 / M_PI);
float accRoll = atan2(-AX, AZ) * (180.0 / M_PI);
// 陀螺仪积分得到角速度
float gyroPitch = pitch + (float)GY / 131.0; // 131 根据陀螺仪灵敏度调整
float gyroRoll = roll + (float)GX / 131.0;
// 综合加速度计和陀螺仪数据,使用互补滤波
float alpha = 0.98; // 互补滤波系数,根据需要调整
pitch = alpha * gyroPitch + (1.0 - alpha) * accPitch;
roll = alpha * gyroRoll + (1.0 - alpha) * accRoll;
}
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
MPU6050_Init(); //MPU6050初始化
Serial_Init();
Buzzer_Init();
/*显示ID号*/
OLED_ShowString(1, 1, "ID:"); //显示静态字符串
ID = MPU6050_GetID(); //获取MPU6050的ID号
OLED_ShowHexNum(1, 4, ID, 2); //OLED显示ID号
//Serial_SendByte(0x41);
while (1)
{
MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ); //获取MPU6050的数据
// 更新姿态角度
UpdateAttitude(AX, AY, AZ, GX, GY, GZ);
// 在OLED上显示姿态角度
OLED_ShowString(2, 1, "Pitch: ");
OLED_ShowSignedNum(2, 8, (int16_t)pitch, 5);
OLED_ShowString(3, 1, "Roll: ");
OLED_ShowSignedNum(3, 7, (int16_t)roll, 5);
// 打印姿态
if (pitch > 30) {
OLED_ShowString(4, 1, "Back ");
pose1 = false;
} else if (pitch < -30) {
OLED_ShowString(4, 1, "Front ");
pose1 = false;
} else {
OLED_ShowString(4, 1, "Normal ");
pose1 = true;
}
if (roll < -70) {
OLED_ShowString(4, 10, "Right ");
pose2 = false;
} else if (roll > 0) {
OLED_ShowString(4, 10, "Left ");
pose2 = false;
} else {
OLED_ShowString(4, 10, "Normal");
pose2 = true;
}
if (!pose1 || !pose2) {
// 触发蜂鸣器响
Buzzer_ON();
} else {
// 关闭蜂鸣器
Buzzer_OFF();
}
// 通过串口发送姿态角度
Serial_SendString("Pitch: ");
Serial_SendNumber((int16_t)pitch, 5);
Serial_SendString(", Roll: ");
Serial_SendNumber((int16_t)roll, 5);
Serial_SendString("\r\n");
}
}
简单来说下这个代码大致完成了什么功能,将面板板平放之后,我发现Pitch大约在-00006左右,roll大约在-00039左右,经过多次测试当俯仰角>30时判定为后倾,当俯仰角<-30时判定为前倾,当翻滚角>0时判定为左斜,当翻滚角<-70时判定为右斜。当满足上面任意请求时,蜂鸣器发出警报向周围人求助。
这里的阈值是可以修改的,在测试的时候也用OLED来显示了的,到一定的范围就打印出它的姿态,正常的就是normal,其他的就是使用的方向的英文来表示,大家想提供可以使用中文,因为我这个就是个课设作业,我也是才接触的stm32,花了一周的时间学习的江科大(有很多其实都没有用到),想拿高分最好就是把无线通信还有GPS的功能加上。
六、总结
本设计致力于解决老年人跌倒检测问题,采用了STM32F103C8T6主控制器,搭配蜂鸣器模块、MPU6050三轴加速度传感器、0.96寸OLED显示模块以及ESP8266-01s模块等组件,以实现全面的跌倒监测与通信功能。技术指标方面,STM32F103C8T6主控制器具备高性能、低功耗、丰富的I/O端口和通信端口等特点。MPU6050传感器具备消除敏感度、陀螺仪积分等先进特性,而0.96寸OLED屏为系统提供实时数据显示和系统调试支持。
尚待完善的地方:
(1)优化互补滤波算法的参数,以提高姿态角度计算的准确性和稳定性。
(2)进一步完善系统的无线通信功能,特别是考虑引入GPS功能,以确保在实际应用中能够可靠地向监护人发送准确的警报信息。同时还存在ESP8266-01s模块与STM32F103C8T6进行驱动时的连接及通信问题,目前尚需解决。