360|3

34

帖子

4

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测应用 [复制链接]

  本帖最后由 鲜de芒果 于 2025-1-10 19:36 编辑

一、项目介绍

        随着现代办公和学习方式的改变,长时间保持不正确的坐姿可能导致多种健康问题,如腰背疼痛、颈椎疾病等。为了帮助用户实时监测和纠正坐姿,提高健康管理能力,我决定开发一款基于 Arduino Nano RP2040 Connect 的坐姿检测应用。

 

        本项目旨在开发一套智能坐姿检测系统,利用 Arduino Nano RP2040 Connect 进行数据采集与处理。系统通过传感器实时监测用户的坐姿,并在检测到不良坐姿时提供提醒,以帮助用户改善坐姿,减少因长时间不良坐姿导致的健康问题。

 

二、任务要求

  1. 坐姿检测,实时坐姿检测以帮助用户纠正不良坐姿。并将坐姿状态通过蓝牙传输至 Seeed Studio XIAO ESP32S3。
  2. 蓝牙通信,坐姿数据通过蓝牙同步,以帮助用户记录或分析坐姿数据。可以进一步优化算法和增加更多功能,如定制化的坐姿建议、长期数据分析等,为用户提供更全面的健康管理服务。
  3. Seeed Studio XIAO ESP32S3 根据接收到的坐姿状态是否良好,显示在OLED屏幕上。并且当坐姿不良时,通过蜂鸣器发出警示音。

 

三、 硬件准备

  • Arduino Nano RP2040 Connect 搭载功能丰富的 Raspberry Pi RP2040 微控制器,将其融入到 Nano 尺寸封装中。充分利用双核32位Arm® Cortex®-M0+处理器,通过U-blox® Nina W102模块实现蓝牙和WiFi连接,集速度计、陀螺仪、RGB LED和麦克风于一体,是物联网应用的不错选择。
  • Seeed Studio XIAO ESP32S3 Seeed Studio XIAO 系列是小型开发板,共享类似的硬件结构,尺寸实际上是拇指大小。这里的代号“XIAO”代表它的一半特征 “小”,另一半将是 “羊角面包”。 Seeed Studio XIAO ESP32S3 结合嵌入式ML计算能力和摄影能力,这款开发板可以成为您开始使用智能语音和视觉AI的绝佳工具。

 

四、代码实现

4.1 软件流程图

 

4.2 坐姿检测外设实现代码

坐姿检测外设基于本次活动开发板 Arduino Nano RP2040 Connect 来实现,搭戴一块锂电池安装到模拟设备身上进行坐姿检测。

  • /**
  • * FollowMe 2-4 任务4:
  • * 1. 坐姿检测
  • * 2. 蓝牙通信
  • * 3. 坐姿数据通过蓝牙传输
  • */
  • #include <Arduino.h>
  • #include <ArduinoBLE.h>
  • #include <Arduino_LSM6DSOX.h>
  • #include <GyverFilters.h>
  • #include <WiFiNINA.h>
  • #include "Madgwick.h"
  • #define CALIB_OFFSET_NB_MES 1000 // 计算IMU零漂次数
  • #define DATA_MULTIPLIER 100 // 欧拉角数据放大100倍
  • #define SITTING_STRAIGHT_THRESHOLD 1.0 // 坐姿加速度阈值
  • #define TOLERANCE 0.05 // 坐姿加速度阈值允许的误差范围
  • GKalman xAccKalmanFilter(2, 2, 0.01); // x轴加速度计卡尔曼滤波
  • GKalman yAccKalmanFilter(2, 2, 0.01); // y轴加速度计卡尔曼滤波
  • GKalman zAccKalmanFilter(2, 2, 0.01); // z轴加速度计卡尔曼滤波
  • GKalman xGyroKalmanFilter(2, 2, 0.01); // x轴陀螺仪卡尔曼滤波
  • GKalman yGyroKalmanFilter(2, 2, 0.01); // y轴陀螺仪卡尔曼滤波
  • GKalman zGyroKalmanFilter(2, 2, 0.01); // z轴陀螺仪卡尔曼滤波
  • // 初始化 MadgwickAHRS 算法过滤器,用于姿态估
  • Madgwick filter;
  • bool isSittingPostureOk = false; // 坐姿状态是否正常
  • float Ax, Ay, Az; // 三轴加速度计数据
  • float Gx, Gy, Gz; // 三轴陀螺仪数据
  • float roll, pitch, yaw; // 欧拉角数据
  • float xAccOffset = 0; // x轴加速度计零漂
  • float yAccOffset = 0; // y轴加速度计零漂
  • float zAccOffset = 0; // z轴加速度计零漂
  • float xGyroOffset = 0; // x轴陀螺仪零漂
  • float yGyroOffset = 0; // y轴陀螺仪零漂
  • float zGyroOffset = 0; // z轴陀螺仪零漂
  • float xAcc = 0; // x轴加速度计
  • float yAcc = 0; // y轴加速度计
  • float zAcc = 0; // z轴加速度计
  • float xGyro = 0; // x轴陀螺仪
  • float yGyro = 0; // y轴陀螺仪
  • float zGyro = 0; // z轴陀螺仪
  • uint32_t previousMillis = 0; // tick
  • // roll = pitch = yaw = Ax = Ay = Az = Gx = Gy = Gz = 0.0f;
  • BLEService IMUService("19B10000-E8F2-537E-4F6C-D104768A1214"); // IMU 服务
  • // IMU 特征符
  • BLEBoolCharacteristic sittingPostureCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // 坐姿,1:正常,0:不良
  • BLEFloatCharacteristic xAccCharacteristic("19B10002-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // x轴加速度计
  • BLEFloatCharacteristic yAccCharacteristic("19B10003-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // y轴加速度计
  • BLEFloatCharacteristic zAccCharacteristic("19B10004-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // z轴加速度计
  • BLEFloatCharacteristic xGyroCharacteristic("19B10005-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // x轴陀螺仪
  • BLEFloatCharacteristic yGyroCharacteristic("19B10006-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // y轴陀螺仪
  • BLEFloatCharacteristic zGyroCharacteristic("19B10007-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // z轴陀螺仪
  • /**
  • * 计算陀螺仪零漂
  • */
  • void calcOffsets(bool is_calc_gyro, bool is_calc_acc);
  • void setup() {
  • // 串口初始化
  • Serial.begin(115200);
  • delay(1500);
  • // 初始化三色 LED 为输出
  • pinMode(LEDR, OUTPUT);
  • pinMode(LEDG, OUTPUT);
  • pinMode(LEDB, OUTPUT);
  • // IMU 初始化并启动通信
  • while (!IMU.begin()) {
  • Serial.println("IMU(LSM6DSOXTR) 初始化失败, 延时1秒后重试!");
  • IMU.end();
  • delay(1000);
  • }
  • // 打印采样速率
  • Serial.print("加速度计采样速率 ");
  • Serial.print(IMU.accelerationSampleRate());
  • Serial.println(" Hz");
  • Serial.print("陀螺仪采样速率 ");
  • Serial.print(IMU.gyroscopeSampleRate());
  • Serial.println(" Hz");
  • // 蓝牙初始化
  • if (!BLE.begin()) {
  • Serial.println("starting Bluetooth® Low Energy failed!");
  • }
  • // 设置发布的蓝牙服务本地名称和服务UUID
  • BLE.setLocalName("IMU Device");
  • BLE.setAdvertisedService(IMUService);
  • // 添加特征码至IMU服务
  • IMUService.addCharacteristic(sittingPostureCharacteristic);
  • IMUService.addCharacteristic(xAccCharacteristic);
  • IMUService.addCharacteristic(yAccCharacteristic);
  • IMUService.addCharacteristic(zAccCharacteristic);
  • IMUService.addCharacteristic(xGyroCharacteristic);
  • IMUService.addCharacteristic(yGyroCharacteristic);
  • IMUService.addCharacteristic(zGyroCharacteristic);
  • // 绑定蓝牙服务
  • BLE.addService(IMUService);
  • // 发布服务
  • BLE.advertise();
  • }
  • void loop() {
  • // 监听蓝牙外设连接
  • BLEDevice central = BLE.central();
  • // 中心连接到外设
  • if (central) {
  • Serial.print("Connected to central: ");
  • Serial.println(central.address());
  • // 连接状态
  • while (central.connected()) { // 连接成功,发布数据
  • uint32_t currentMillis = millis();
  • // 读取加速度计数据与陀螺仪数据
  • if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
  • IMU.readAcceleration(Ax, Ay, Az);
  • IMU.readGyroscope(Gx, Gy, Gz);
  • xAcc = (Ax - xAccOffset); // x轴加速度计
  • yAcc = (Ay - yAccOffset); // y轴加速度计
  • zAcc = (Az - zAccOffset); // z轴加速度计
  • xGyro = (Gx - xGyroOffset); // x轴陀螺仪
  • yGyro = (Gy - yGyroOffset); // y轴陀螺仪
  • zGyro = (Gz - zGyroOffset); // z轴陀螺仪
  • isSittingPostureOk = (SITTING_STRAIGHT_THRESHOLD - TOLERANCE) <= abs(xAcc) && abs(xAcc) <= (SITTING_STRAIGHT_THRESHOLD + TOLERANCE);
  • if(200 <= (currentMillis - previousMillis)) {
  • previousMillis = currentMillis;
  • sittingPostureCharacteristic.writeValue(isSittingPostureOk);
  • xAccCharacteristic.writeValue(xAcc); // x轴加速度计
  • yAccCharacteristic.writeValue(yAcc); // y轴加速度计
  • zAccCharacteristic.writeValue(zAcc); // z轴加速度计
  • xGyroCharacteristic.writeValue(xGyro); // x轴陀螺仪
  • yGyroCharacteristic.writeValue(yGyro); // y轴陀螺仪
  • zGyroCharacteristic.writeValue(zGyro); // z轴陀螺仪
  • Serial.print(xGyro);
  • Serial.print(",");
  • Serial.print(yGyro);
  • Serial.print(",");
  • Serial.print(zGyro);
  • Serial.print(",");
  • Serial.print(xAcc);
  • Serial.print(",");
  • Serial.print(yAcc);
  • Serial.print(",");
  • Serial.print(zAcc);
  • Serial.print(",");
  • Serial.println(isSittingPostureOk);
  • }
  • }
  • delay(50);
  • }
  • // 连接断开
  • Serial.print("Disconnected from central: ");
  • Serial.println(central.address());
  • }
  • }
  • /**
  • * 计算陀螺仪零漂
  • */
  • void calcOffsets(bool is_calc_gyro, bool is_calc_acc) {
  • if(is_calc_gyro) {
  • xGyroOffset = 0;
  • yGyroOffset = 0;
  • zGyroOffset = 0;
  • }
  • if(is_calc_acc) {
  • xAccOffset = 0;
  • yAccOffset = 0;
  • zAccOffset = 0;
  • }
  • float ag[6] = {0,0,0,0,0,0}; // 3*acc, 3*gyro
  • for(int i = 0; i < CALIB_OFFSET_NB_MES; i++){
  • if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
  • IMU.readAcceleration(Ax, Ay, Az);
  • IMU.readGyroscope(Gx, Gy, Gz);
  • }
  • ag[0] += Ax;
  • ag[1] += Ay;
  • ag[2] += (Az-1.0); // 假设设备静止且Z轴向下
  • ag[3] += Gx;
  • ag[4] += Gy;
  • ag[5] += Gz;
  • delay(10);
  • }
  • if(is_calc_acc){
  • xAccOffset = ag[0] / CALIB_OFFSET_NB_MES;
  • yAccOffset = ag[1] / CALIB_OFFSET_NB_MES;
  • zAccOffset = ag[2] / CALIB_OFFSET_NB_MES;
  • }
  • if(is_calc_gyro){
  • xGyroOffset = ag[3] / CALIB_OFFSET_NB_MES;
  • yGyroOffset = ag[4] / CALIB_OFFSET_NB_MES;
  • zGyroOffset = ag[5] / CALIB_OFFSET_NB_MES;
  • }
  • }

4.3 作品源码

项目源码下载地址:https://download.eeworld.com.cn/detail/%E9%B2%9Cde%E8%8A%92%E6%9E%9C/635463

 

源码说明

  • followme2_4_task1 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 入门任务源码,Arduino 工程。
  • followme2_4_task2 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 基础任务源码,Arduino 工程。
  • followme2_4_task3 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 进阶任务源码,Arduino 工程。
  • followme2_4_task4 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测任务外设部分源码,Arduino 工程。
  • followme2_4_task4_central 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测任务接收部分源码,PlatformIO Arduino 工程。

 

五、效果展示

5.1 坐姿检测模拟实验

 

5.2 坐姿正常

 

5.3 不良坐姿

 

5.4 作品演示视频

 

六、结语

        本项目利用先进的Arduino Nano RP2040 Connect开发板,结合多种传感器和反馈机制,利用简单的硬件和软件工具帮助用户纠正不良坐姿,促进健康生活方式。实现了实时、准确的坐姿检测和纠正功能。未来,我们可以进一步优化算法和增加更多功能,如定制化的坐姿建议、长期数据分析等,为用户提供更全面的健康管理服务。

        通过这个项目,我们不仅提高了对物联网技术的理解和运用能力,也学会了如何将理论转化为解决实际问题的应用。希望这些经验和心得能为未来的项目提供参考和启发。

 

七、参考资料

 

八、传送门

【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 入门任务

【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 基础任务

【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 进阶任务

最新回复

坐姿检测,这个应用前景非常多呀,比如对人员的疲劳预警,老人的久坐提醒。  详情 回复 发表于 2024-12-30 22:22
点赞 关注
 
 

回复
举报

6876

帖子

10

TA的资源

版主

沙发
 

这小接收板看着不错,估计明年的活动会出现它 

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复

7502

帖子

2

TA的资源

版主

板凳
 

如果只是单轴的话,站姿估计和坐姿数据是一样的。

 
 
 

回复

7190

帖子

11

TA的资源

版主

4
 
坐姿检测,这个应用前景非常多呀,比如对人员的疲劳预警,老人的久坐提醒。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
中星联华&ADI明日直播
直播主题:大咖面对面,轻松玩转高速ADC性能测试
直播时间:3月25日(周二)14:00
活动奖励:京东卡、双肩包

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 6

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表