北方. 发表于 2025-12-4 15:23:44

《2025 DigiKey AI应用创意挑战赛》智能篮球监测

一、项目名称:智能篮球监测
二、项目概述:基于 FRDM-MCXW71 的智能篮球监测(拍球计数 + 力量计算),这个项目是采用FRDM-MCXW71,适配低功耗、高性能的运动传感器应用。实现智能篮球的拍球计数和力量监测功能。辅助篮球训练和练习。

三、作品实物图这个是采用的FRDM-MCXW71开发板,并利用板载加速度传感器读取数据,进行处理。开发板采用VS Code for MCUexpresso,导入sdk运行的过程中,输出的是拍球的次数和排球的力量值。这个数据可以比较完整的实现预计的数据采集和智能处理功能。采用uart口输出计算结果。这个开发板可以采用内置在篮球中,并供电 ,这个就可以实现篮球的的数据采集和功能。目前,这个开发板还是比较大,采用这样的方案还需要更进一步的改进和提升。
四、演示视频后补。

五、项目文档5.1 核心代码,实现了对于x-y-z三轴的角向量转换和数据度量,这个是实现计算的数学基础。以下代码基于 FXLS** 加速度传感器数据,实现篮球拍球计数和拍球力量计算。核心思路是:通过 Z 轴加速度变化检测拍球冲击(地面反弹),结合阈值过滤噪声,统计有效拍球次数;通过加速度峰值计算拍球力量(力量与加速度变化幅度正相关)。#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <time.h>

// 传感器配置参数(根据硬件实际情况调整)
#define ACCEL_THRESHOLD   800    // 拍球冲击阈值(Z轴原始值突变)
#define IMPULSE_DURATION    0.2f   // 单次冲击有效时长(秒),避免重复计数
#define SAMPLING_FREQ       50   // 传感器采样频率(Hz)
#define GRAVITY             9.81f// 重力加速度 (m/s²)
#define SCALE_FACTOR      0.061f // FXLS**刻度因子 (mg/LSB),±2g量程对应0.061
#define BASKETBALL_MASS   0.6f   // 篮球质量(kg),标准约0.6kg
#define HISTORY_LEN         10   // 加速度历史数据长度

// 拍球计数与力量统计结构体
typedef struct {
    uint16_t dribble_count;      // 累计拍球次数
    double last_impact_time;       // 上一次有效冲击时间(秒)
    int16_t accel_history; // Z轴加速度原始值历史
    uint8_t history_idx;         // 历史数据索引
    float max_force;               // 最大拍球力量(N)
    float avg_force;               // 平均拍球力量(N)
    float force_history;      // 力量历史(最多存储100次)
    uint8_t force_count;         // 力量数据计数
} DribbleCounter;

/**
* @brief 初始化拍球计数器
* @param counter 计数器结构体指针
*/
void dribble_counter_init(DribbleCounter *counter) {
    counter->dribble_count = 0;
    counter->last_impact_time = 0.0;
    counter->history_idx = 0;
    counter->max_force = 0.0f;
    counter->avg_force = 0.0f;
    counter->force_count = 0;
    // 初始化历史数据
    for (int i = 0; i < HISTORY_LEN; i++) {
      counter->accel_history = 0;
    }
    for (int i = 0; i < 100; i++) {
      counter->force_history = 0.0f;
    }
}

/**
* @brief 传感器原始值转换为实际加速度 (m/s²)
* @param raw_value 传感器原始值
* @return 实际加速度值
*/
float convert_accel(int16_t raw_value) {
    float accel_g = raw_value * SCALE_FACTOR / 1000.0f;
    return accel_g * GRAVITY;
}

/**
* @brief 计算拍球力量(牛顿)
* @param peak_accel 冲击时的峰值加速度 (m/s²)
* @return 拍球力量值
*/
float calculate_force(float peak_accel) {
    // 简化模型:F = Δa * m(Δa为加速度变化量,m为篮球质量)
    float delta_accel = fabs(peak_accel - GRAVITY);
    return delta_accel * BASKETBALL_MASS;
}

/**
* @brief 获取历史数据中的加速度峰值
* @param counter 计数器结构体指针
* @return 峰值加速度 (m/s²)
*/
float get_peak_accel(DribbleCounter *counter) {
    float peak = 0.0f;
    for (int i = 0; i < HISTORY_LEN; i++) {
      float accel = convert_accel(counter->accel_history);
      if (fabs(accel) > peak) {
            peak = fabs(accel);
      }
    }
    return peak;
}

/**
* @brief 检测拍球冲击(核心逻辑)
* @param counter 计数器结构体指针
* @param z_raw Z轴加速度原始值
* @return 1-检测到冲击,0-未检测到
*/
uint8_t detect_impact(DribbleCounter *counter, int16_t z_raw) {
    double current_time = (double)clock() / CLOCKS_PER_SEC; // 获取当前时间(秒)
    float z_accel = convert_accel(z_raw);

    // 1. 过滤短时间内的重复冲击
    if (current_time - counter->last_impact_time < IMPULSE_DURATION) {
      return 0;
    }

    // 2. 检测Z轴加速度突变(超过阈值)
    if (fabs(z_accel) > (ACCEL_THRESHOLD * SCALE_FACTOR / 1000.0f * GRAVITY)) {
      // 更新冲击时间
      counter->last_impact_time = current_time;

      // 计算本次拍球力量
      float peak_accel = get_peak_accel(counter);
      float current_force = calculate_force(peak_accel);

      // 更新计数
      counter->dribble_count++;

      // 更新力量统计
      if (counter->force_count < 100) {
            counter->force_history = current_force;
            counter->force_count++;
      } else {
            // 超出存储上限时,覆盖最早数据
            for (int i = 1; i < 100; i++) {
                counter->force_history = counter->force_history;
            }
            counter->force_history = current_force;
      }

      // 更新最大力量
      if (current_force > counter->max_force) {
            counter->max_force = current_force;
      }

      // 更新平均力量
      float sum_force = 0.0f;
      for (int i = 0; i < counter->force_count; i++) {
            sum_force += counter->force_history;
      }
      counter->avg_force = sum_force / counter->force_count;

      return 1;
    }

    return 0;
}

/**
* @brief 处理单帧传感器数据
* @param counter 计数器结构体指针
* @param x_raw X轴原始值
* @param y_raw Y轴原始值
* @param z_raw Z轴原始值
* @param current_force 输出参数:本次拍球力量(N)
* @return 当前累计拍球次数
*/
uint16_t process_sensor_data(DribbleCounter *counter, int16_t x_raw, int16_t y_raw, int16_t z_raw, float *current_force) {
    // 1. 保存Z轴原始值到历史数据
    counter->accel_history = z_raw;
    counter->history_idx = (counter->history_idx + 1) % HISTORY_LEN;

    // 2. 检测冲击
    uint8_t impact_detected = detect_impact(counter, z_raw);

    // 3. 获取当前力量
    *current_force = 0.0f;
    if (impact_detected && counter->force_count > 0) {
      *current_force = counter->force_history;
    }

    // 4. 返回累计拍球次数
    return counter->dribble_count;
}

// 模拟硬件读取传感器数据(实际使用时替换为I2C读取逻辑)
void read_fxls**_data(int16_t *x, int16_t *y, int16_t *z) {
    // 示例:固定返回初始数据,实际需从0x19地址读取
    *x = -31;
    *y = -100;
    *z = 1063;
}
核心功能:拍球计数:通过检测 Z 轴加速度突变(地面反弹冲击),结合时间阈值避免重复计数;力量计算:基于加速度峰值和篮球质量(0.6kg)计算拍球力量(单位:牛顿);数据统计:实时输出当前拍球次数、单次力量、最大力量、平均力量。关键参数调整:ACCEL_THRESHOLD:拍球冲击阈值,需根据实际使用场景校准(建议在无动作时采集基线数据,阈值设为基线 + 200 左右);SCALE_FACTOR:FXLS** 的刻度因子,需匹配传感器实际量程(如 ±2g 量程对应 0.061mg/LSB,±4g 对应 0.122mg/LSB);IMPULSE_DURATION:单次冲击有效时长,避免快速抖动导致重复计数(建议 0.1~0.3 秒)5.2 核心函数
函数名功能
dribble_counter_init初始化计数器,清空历史数据和统计值
convert_accel将传感器原始值转换为实际加速度(m/s²)
calculate_force基于加速度峰值和篮球质量计算拍球力量(牛顿)
detect_impact核心冲击检测逻辑(阈值判断 + 时间过滤,避免重复计数)
process_sensor_data处理单帧传感器数据,整合历史存储、冲击检测、力量计算逻辑



标准输出为
5.3 硬件连接:FXLS** 传感器 I2C 地址:0x19(与开发板默认 I2C1 连接);I2C 引脚:PTE24 (SDA)、PTE25 (SCL);供电:3.3V(与开发板 VDD 连接)。
5.4 编译与烧录
[*]SDK 配置:
[*]导入 FRDM-MCXW71 的 SDK 包(包含 I2C、SysTick、UART 驱动);
[*]启用 FPU(浮点运算),支持float类型计算;

[*]烧录:通过开发板的调试器烧录固件;
[*]串口工具:使用 Putty / 串口助手(115200 8N1)查看输出。

以下是编译成功的页面

以下是运行成功的页面



5.5 调试与校准

[*]阈值校准:
[*]先静止放置篮球,读取 Z 轴基线值(约 1024 左右,对应 1g);
[*]将ACCEL_THRESHOLD调整为基线 + 200~300(避免误触发)。

[*]采样频率调整:
[*]修改SAMPLING_FREQ和FXLS**_CTRL_REG1的 ODR 配置(100Hz/200Hz 可选)。

[*]力量校准:

[*]实际拍打篮球,对比测力仪数据,调整BASKETBALL_MASS系数。

5.6 代码附件
参加附件





页: [1]
查看完整版本: 《2025 DigiKey AI应用创意挑战赛》智能篮球监测

Baidu
map