当前位置: 首页 > news >正文

编写程序让智能瑜伽垫检测动作时长,达到标准时长,提示“动作完成”。

🧘‍♀️ 项目实战:基于压力传感与状态机的智能瑜伽垫动作计时器

一、实际应用场景描述 (Scenario)

在居家健身场景中,瑜伽和普拉提非常注重体式的保持时长(例如:平板支撑需保持30秒,下犬式保持5个呼吸)。然而,初学者往往缺乏节奏感,要么坚持时间不足导致训练无效,要么过度坚持导致肌肉代偿受伤。

目标:通过嵌入在瑜伽垫底部的压阻式薄膜压力传感器(FSR),实时监测用户是否处于特定动作姿态,并精确计时,达标后给予声光反馈。

二、引入痛点 (Pain Points)

1. 计时不精准:用户一边看手机计时器一边做动作,注意力分散,违背“身心合一”的练习初衷。

2. 动作识别难:传统传感器难以区分“站立”、“躺卧”和“特定体式”。

3. 误触与抖动:用户微小的身体晃动不应被判定为动作结束。

4. 缺乏即时反馈:不知道自己是否达到了该动作的生理刺激时长。

三、核心逻辑讲解 (Core Logic)

本系统采用“阈值触发 + 状态机 + 定时器”的逻辑架构:

1. 信号采集层:模拟压阻式薄膜传感器(FSR),其电阻随压力增大而减小。

2. 特征提取:将原始电压值映射为“压力等级”(None, Low, High)。

3. 状态机 (State Machine):

* IDLE (空闲态):未检测到压力。

* DETECTED (检测态):检测到压力,开始计时。

* HELD (保持态):持续时间超过阈值,提示“动作完成”。

4. 防抖机制 (Debounce):只有在连续 N 次采样均满足条件后,才切换状态,防止微小抖动导致计时中断。

四、代码模块化实现 (Code Implementation)

项目结构如下:

smart_yoga_mat/

├── main.py # 主程序入口

├── config.py # 配置文件

├── sensors/

│ └── pressure_sensor.py # 压力传感器模块

├── core/

│ └── pose_timer.py # 动作计时核心逻辑

├── utils/

│ └── feedback.py # 反馈模块 (声音/LED)

└── README.md

1. config.py (配置文件)

# config.py

# 智能瑜伽垫系统配置

# 压力阈值 (ADC值,假设10位ADC,范围0-1023)

PRESSURE_THRESHOLD_ENTER = 400 # 进入动作的最小压力

PRESSURE_THRESHOLD_EXIT = 300 # 退出动作的压力下限 (迟滞效应)

# 时间设置 (秒)

REQUIRED_HOLD_TIME = 5 # 动作需保持的标准时长 (例如: 5秒)

# 采样与防抖设置

SAMPLING_RATE = 0.2 # 采样间隔 (秒)

STABILITY_COUNT = 3 # 连续稳定采样次数 (防抖)

# GPIO 定义 (BCM模式,用于树莓派)

BUZZER_PIN = 17

LED_PIN = 27

2. sensors/pressure_sensor.py (传感器模拟层)

# sensors/pressure_sensor.py

import random

import time

class PressureSensor:

"""

压阻式薄膜压力传感器 (FSR) 模拟类

实际硬件: FSR402 + 分压电路 + ADC (如MCP3008)

"""

def __init__(self, noise_level=20):

self.noise_level = noise_level

self._base_value = 0

def simulate_pose(self, duration_sec: int):

"""

模拟一个持续一定时长的动作

:param duration_sec: 模拟施加压力的时长

"""

start_time = time.time()

while time.time() - start_time < duration_sec:

yield self.read_raw_value()

time.sleep(0.1)

# 动作结束后归零

self._base_value = 0

def read_raw_value(self) -> int:

"""

读取原始ADC值

模拟逻辑:

- 基础值为0

- 如果有_base_value,则模拟压力读数

"""

if self._base_value == 0:

# 空闲状态,只有噪声

raw_value = random.randint(0, 50)

else:

# 受压状态,包含信号和噪声

raw_value = self._base_value + random.randint(-self.noise_level, self.noise_level)

return max(0, min(1023, raw_value))

def set_pressure(self, value: int):

"""外部接口:设置模拟压力值"""

self._base_value = value

3. core/pose_timer.py (核心状态机逻辑)

# core/pose_timer.py

from enum import Enum, auto

from config import *

class PoseState(Enum):

IDLE = auto() # 空闲:未检测到动作

HOLDING = auto() # 保持:正在计时中

COMPLETED = auto() # 完成:已达标准时长

class PoseTimer:

"""

动作计时器核心类

实现有限状态机 (FSM)

"""

def __init__(self):

self.state = PoseState.IDLE

self.hold_start_time = None

self.stable_counter = 0

def update(self, pressure_value: int) -> PoseState:

"""

根据压力值更新状态机

:param pressure_value: 当前压力ADC值

:return: 当前状态

"""

# 1. 判断当前是否为有效压力状态

is_pressed = pressure_value > PRESSURE_THRESHOLD_ENTER

# 2. 防抖计数

if is_pressed:

self.stable_counter += 1

else:

self.stable_counter = max(0, self.stable_counter - 1)

# 3. 状态机逻辑

if self.state == PoseState.IDLE:

if self.stable_counter >= STABILITY_COUNT:

self.state = PoseState.HOLDING

self.hold_start_time = time.time()

print("[STATE] 检测到动作,开始计时...")

elif self.state == PoseState.HOLDING:

# 检查是否仍然稳定

if self.stable_counter < STABILITY_COUNT:

# 不稳定,判定为动作中断

print("[STATE] 动作不稳定,计时重置。")

self.reset()

else:

elapsed_time = time.time() - self.hold_start_time

if elapsed_time >= REQUIRED_HOLD_TIME:

self.state = PoseState.COMPLETED

print(f"[SUCCESS] 动作完成!保持时长: {elapsed_time:.2f}s")

return self.state

def reset(self):

"""重置状态机"""

self.state = PoseState.IDLE

self.hold_start_time = None

self.stable_counter = 0

4. main.py (主程序)

# main.py

import time

from sensors.pressure_sensor import PressureSensor

from core.pose_timer import PoseTimer

from utils.feedback import FeedbackDevice

def main():

sensor = PressureSensor()

timer = PoseTimer()

feedback = FeedbackDevice()

print("智能瑜伽垫启动。模拟 3 秒后开始动作...")

time.sleep(3)

# 模拟用户踩上瑜伽垫并保持6秒

sensor.set_pressure(600)

try:

while True:

pressure = sensor.read_raw_value()

print(f"[SENSOR] Raw Value: {pressure}", end="\r")

state = timer.update(pressure)

if state == timer.state.COMPLETED:

feedback.trigger_success()

# 完成后重置,准备下一次动作

timer.reset()

# 模拟动作结束

sensor.set_pressure(0)

time.sleep(SAMPLING_RATE)

except KeyboardInterrupt:

print("\n程序退出。")

if __name__ == "__main__":

main()

5. utils/feedback.py

# utils/feedback.py

import time

class FeedbackDevice:

"""反馈设备类 (模拟GPIO)"""

def trigger_success(self):

"""触发成功提示"""

print("\n🔊 哔哔!动作完成!Good Job!💡")

# 实际硬件代码:

# GPIO.output(LED_PIN, GPIO.HIGH)

# buzzer.beep()

time.sleep(1)

# GPIO.output(LED_PIN, GPIO.LOW)

五、README.md 文件

# Smart Yoga Mat - 智能瑜伽垫动作计时器

## 📋 项目简介

这是一个基于 Python 的智能仪器项目,通过模拟压力传感器数据,实现对瑜伽/健身动作保持时长的精确监测与反馈。

## 🚀 功能特性

* 有限状态机 (FSM) 管理动作生命周期

* 迟滞比较器防止边界抖动

* 模块化设计,易于替换为真实硬件

## 🛠️ 运行指南

bash

pip install -r requirements.txt

python main.py

## 📈 运行逻辑

1. 程序启动,等待压力输入。

2. 当压力持续超过阈值 3 次采样,开始计时。

3. 计时达到 `REQUIRED_HOLD_TIME` 后,终端打印成功信息。

六、核心知识点卡片 (Knowledge Cards)

领域 知识点 说明

智能仪器 迟滞比较 (Hysteresis) 设置不同的进入/退出阈值,防止在临界值附近震荡。

嵌入式软件 有限状态机 (FSM) 将复杂行为分解为 IDLE/HOLDING/COMPLETED 离散状态。

信号处理 数字滤波/防抖 通过连续采样计数,滤除高频噪声。

IoT 硬件 FSR 传感器特性 电阻随压力变化,需配合分压电路和 ADC 使用。

七、总结 (Summary)

在这个项目中,我们不仅仅是写了几行 Python 代码,而是完整复现了一个智能硬件产品的开发流程。

作为全栈工程师,我特别强调了“软硬件解耦”的设计思想:

"pressure_sensor.py" 负责与硬件对话,而

"pose_timer.py" 只关心逻辑状态。这种设计使得当你真的拿到树莓派和 FSR 传感器时,只需要修改

"read_raw_value" 方法的实现,而不必重构核心算法。

此外,迟滞效应 (Hysteresis) 的引入是这个程序的灵魂——它体现了智能仪器课程中“工程思维”的重要性:现实世界的信号永远是带噪声。

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

http://www.jsqmd.com/news/538414/

相关文章:

  • SkyWalking Agent性能调优实战:如何调整数据队列与上报策略来应对高并发场景
  • 基于Dify快速搭建高可用智能客服系统:从架构设计到生产环境部署
  • 告别龟速下载!手把手教你用Aspera ascp命令高效获取SRA数据(附常见错误排查)
  • 5分钟掌握Umi-OCR:免费离线OCR工具如何解决你的文字识别痛点
  • OpenClaw成本控制:Qwen3.5-9B自部署模型节省Token消耗实测
  • 3步攻克B站缓存难题:m4s-converter让视频资产重获自由
  • Windows 11 vs Windows 10:五年老用户亲测到底该不该升级?
  • LM386集成功放电路实战:从零搭建到波形调试全记录(附实测数据)
  • 从地理查询到学术报告:一个‘降智’ChatGPT账号的邮件申诉与恢复全记录
  • Win11Debloat终极优化指南:释放Windows 11隐藏性能的完整教程
  • 2026年财务软件公司TOP3深度解析:中小企业数字化转型的智慧之选! - 深度智识库
  • 5个场景深度解析:League Akari如何让英雄联盟游戏体验提升300%
  • OpenClaw配置优化:提升Qwen3.5-4B-Claude响应速度的3个技巧
  • ISO27145协议核心服务解析:12/14/19/22/31服务在汽车排放检测中的实际应用
  • 如何在ComfyUI中使用IPAdapter快速实现AI图像风格迁移:完整新手教程
  • 高效实战:ComfyUI-WanVideoWrapper视频生成工具完全配置指南
  • 从《王者荣耀》到你的项目:拆解一个高并发、可堆叠的Unity技能Buff系统实战框架
  • 【2026】最简单的白嫖百度文库方法
  • Cuvil × PyTorch推理部署全链路实操:3小时将ResNet50延迟压至8.2ms(含完整CI/CD脚本)
  • ESP32 LVGL8.1 ——Style outline 进阶应用:打造动态交互式UI (Style 5)
  • TradingAgents-CN:三步构建你的终极AI智能交易系统,实现专业级金融决策
  • 2026年 电力滤波与补偿装置厂家推荐榜:有源/无源滤波、高低压电容柜、消弧接地及启动装置专业品牌深度解析 - 品牌企业推荐师(官方)
  • 智能体架构的创新突破:Agent-S框架的技术解析与实战应用
  • Spring Boot 4 + AI 推理后端集成 — 让 Java 在大模型时代重装上阵
  • 智能客服产品的架构设计与性能优化实战
  • JIT启用后反而变慢?Python 3.15 JIT适配避坑指南,90%开发者忽略的3个启动阈值配置!
  • League-Toolkit:全方位英雄联盟辅助工具,提升游戏体验与竞技效率
  • 2026年高性价比个人网盘盘点:告别“空间焦虑”,谁才是真正的效率神器?
  • 2026年哈尔滨、牡丹江等地哈尔滨万通职业学校家长反馈,课程体系靠谱吗 - 工业品牌热点
  • YOLOv8 Detect Head 源码拆解:从张量变形到边界框解码,一步步带你理解Anchor-Free预测