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

手表关于MPU6050中的功能实现

MPU6050 OV-Watch 中的睡眠和唤醒功能实现

OV-Watch 项目为 MPU6050 传感器实施了复杂的电源管理,以优化电池寿命,同时保持手腕检测和计步功能。以下是对睡眠和唤醒机制的详细分析:

内核休眠/唤醒功能实现

MPU6050 有两个主要功能来控制其电源状态:

void MPU_Sleep()  
{  MPU_Write_Byte(MPU_PWR_MGMT1_REG,0x48);//sleep=1,cycle=0,temp_dis=1,internal 8MHz  
}  void MPU_Wakeup()  
{  //low power modes  MPU_Write_Byte(MPU_PWR_MGMT1_REG,0x28);//sleep=0,cycle=1,temp_dis=1,internal 8MHz  
}

这些函数写入 MPU6050 的电源管理寄存器(MPU_PWR_MGMT1_REG,地址 0x6B)以配置:

  • Sleep bit:控制设备是否处于睡眠模式 (1) 或不处于 (0)
  • Cycle bit:启用 (1) 或禁用 (0) 循环模式,其中设备在睡眠和测量之间循环
  • 温度传感器:禁用 (1) 以节省电量
  • 时钟源:使用内部 8MHz 振荡器(位 0-2 = 0)

初始化过程

MPU6050配置为在初始化期间实现节能运行:

MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X28);  //SET the internal 8MHz,sleep=0,cycle=1,TEMP_DIS=1//low power modes  
MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X87);  //enable accelerometer,disanable gyroscope,set the wake up frequence=20Hz  
MPU_Set_Rate(50);                        //采样率50Hz

此初始配置:

  1. 将 MPU6050 设置为低功耗循环模式 (0x28)
  2. 在保持启用加速度计的同时禁用陀螺仪 (0x87)
  3. 将唤醒频率设置为 20Hz
  4. 配置 50Hz 采样率

DMP 运动处理配置

OV-Watch 通过数字运动处理器 (DMP) 功能进一步优化了功耗:

u8 mpu_dmp_init(void)  
{  u8 res=0;  MPU_Bus_Init();  if(mpu_init()==0) //初始化MPU6050  {	  res = mpu_lp_accel_mode(20);  if(res)return -1;   res=mpu_configure_fifo(INV_XYZ_ACCEL);//配置FIFO  if(res)return 2;   res=mpu_set_sample_rate(DEFAULT_MPU_HZ);	//设置采样率  if(res)return 3;   res=dmp_load_motion_driver_firmware();		//加载dmp固件  if(res)return 4;   res=dmp_enable_feature(DMP_FEATURE_TAP| DMP_FEATURE_SEND_RAW_ACCEL| DMP_FEATURE_PEDOMETER);//使能dmp功能  if(res)return 6;   res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);	//设置DMP输出速率(最大不超过200Hz)  if(res)return 7;     res=mpu_set_dmp_state(1);	//使能DMP  if(res)return 9;   }else return 10;  return 0;  
}

此初始化:

  1. 将低功耗加速度计模式配置为 20Hz 唤醒频率
  2. 为加速度计数据设置 FIFO
  3. 加载 DMP 固件以进行高级运动处理
  4. 启用特定功能:点击检测、原始加速度数据和计步器
  5. 设置适当的数据速率

低功耗加速度计模式

mpu_lp_accel_mode 功能对于电源效率至关重要:

int mpu_lp_accel_mode(unsigned char rate)  
{  unsigned char tmp[2];  if (rate > 40)  return -1;  if (!rate) {  mpu_set_int_latched(0);  tmp[0] = 0;  tmp[1] = BIT_STBY_XYZG;  if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 2, tmp))  return -1;  st.chip_cfg.lp_accel_mode = 0;  return 0;  }  /* For LP accel, we automatically configure the hardware to produce latched  * interrupts. In LP accel mode, the hardware cycles into sleep mode before  * it gets a chance to deassert the interrupt pin; therefore, we shift this  * responsibility over to the MCU.  */  mpu_set_int_latched(1);  
#if defined MPU6050  //tmp[0] = BIT_LPA_CYCLE;  tmp[0] = 0x28;

此功能:

  1. 设置低功耗作所需的锁存中断
  2. 使用 0x28 配置电源管理寄存器 (cycle=1, sleep=0, temp_dis=1)sleep=1:将设备置于睡眠模式cycle=0:禁用循环模式(周期性唤醒)temp_dis=1:禁用温度传感器以节省电量使用内部 8MHz 振荡器进行定时
  3. 根据请求的速率选择合适的唤醒频率
  4. 禁用陀螺仪以节省电量

手腕检测实现

OV-Watch 使用MPU6050进行手腕检测,以确定何时唤醒设备:

//MPU Check  
if(HWInterface.IMU.wrist_is_enabled)  
{  uint8_t hor;  hor = MPU_isHorizontal();  if(hor && HWInterface.IMU.wrist_state == WRIST_DOWN)  {  HWInterface.IMU.wrist_state = WRIST_UP;  Wrist_Flag = 1;  //resume, go on  }  else if(!hor && HWInterface.IMU.wrist_state == WRIST_UP)  {  HWInterface.IMU.wrist_state = WRIST_DOWN;  IdleTimerCount  = 0;  goto sleep;  }  
}

此机制:

  1. 检查是否启用了手腕检测
  2. 确定手表是否处于水平位置
  3. 更新手腕状态(UP 或 DOWN)
  4. 控制设备是应唤醒还是返回睡眠状态

水平位置检测使用加速度计数据来计算滚动和俯仰:

uint8_t MPU_isHorizontal(void)  
{  float roll,pitch;  MPU_Get_Angles(&roll,&pitch);  if(roll<=0.50 && roll>=-0.50 && pitch<=0.50 && pitch>=-0.50)  {return 1;}  return 0;  
}

硬件接口层

OV-Watch 实现了一个硬件抽象层来管理手腕检测:

void HW_MPU_Wrist_Enable(void)  
{  #if HW_USE_IMU  HWInterface.IMU.wrist_is_enabled = 1;  #endif  
}  void HW_MPU_Wrist_Disable(void)  
{  #if HW_USE_IMU  HWInterface.IMU.wrist_is_enabled = 0;  #endif  
}

这些函数控制手腕检测功能是否处于活动状态,这直接影响何时调用 MPU6050 睡眠/唤醒函数。

笔记

  1. OV-Watch 中的 MPU6050 实现通过以下方式最大限度地降低功耗:

    • 在不需要时禁用陀螺仪
    • 禁用温度传感器
    • 使用循环模式而不是恒定作
    • 仔细选择合适的唤醒频率
  2. 手腕检测功能允许手表保持睡眠模式,直到用户抬起手腕,在保持可用性的同时显着延长电池寿命。

  3. 数字运动处理器 (DMP) 可高效处理复杂的运动检测任务,使主处理器保持低功耗状态。

OV-Watch 智能手表使用 MPU6050 IMU 传感器来保持计步功能,即使设备处于睡眠模式也是如此。这种方法是手表能效战略的核心。

Power Mode 架构

OV-Watch 有三种不同的电源模式:

  1. 正常运行模式 - 功能齐全(消耗 70-80mA)
  2. 睡眠模式 - 当 MCU 处于停止模式(约 800μA)时,MPU6050继续计数步数
  3. 关断模式 - 完全断电,仅 RTC 处于活动状态 README_Eng.md:142-146

MPU6050 低功耗配置

在初始化期间,MPU6050 专门配置为在低功耗模式下运行,同时保持步数功能:

u8 mpu_dmp_init(void)  
{  u8 res=0;  MPU_Bus_Init();  if(mpu_init()==0)//初始化MPU6050  {      res = mpu_lp_accel_mode(20);  if(res)return -1;   //...  res=dmp_enable_feature(DMP_FEATURE_TAP| DMP_FEATURE_SEND_RAW_ACCEL| DMP_FEATURE_PEDOMETER);//enable dmp features  if(res)return 6;   //...  }  return 0;  
}

关键部分是调用,它将 MPU6050 配置为在低功耗模式下以 20Hz 采样率运行。此功能专门将加速度计设置为继续运行,同时最大限度地降低功耗。mpu_lp_accel_mode(20)

睡眠模式实现

当设备进入睡眠模式时,MCU 进入 STOP 模式,同时保持 MPU6050 处于活动状态:

void StopEnterTask(void *argument)  
{  //...  if(osMessageQueueGet(Stop_MessageQueue,&Stopstr,NULL,0)==osOK)  {  //...  //enter stop mode  HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON,PWR_STOPENTRY_WFI);  //here is the sleep period  //...  }  //...  
}

值得注意的是,虽然 LCD 和 UART 等其他外设在进入睡眠模式之前被取消初始化,但 MPU6050 有意保持运行状态,允许它在 MCU 处于 STOP 模式时继续计算步数。

跨电源周期的步数持久性

步数通过 EEPROM 存储在整个休眠周期中保留:

void DataSaveTask(void *argument)  
{  while(1)  {  //...  RTC_DateTypeDef nowdate;  HAL_RTC_GetDate(&hrtc,&nowdate,RTC_FORMAT_BIN);  SettingGet(dat,0x20,3);  if(dat[0] != nowdate.Date)  {  //...  }  else  {  uint16_t temp = HWInterface.IMU.GetSteps();  dat[0] = nowdate.Date;  dat[2] = temp & 0xff;  dat[1] = temp>>8 & 0xff;  SettingSave(dat,0x20,3);  }  //...  }  
}

当系统初始化时,它会从 EEPROM 恢复上一步计数:

// EEPROM  
EEPROM_Init();  
if(!EEPROM_Check())  
{  //...  SettingGet(recbuf,0x20,3);  if(recbuf[0] == nowdate.Date)  {  uint16_t steps=0;  steps = recbuf[1]&0x00ff;  steps = steps<<8 | recbuf[2];  if(!HWInterface.IMU.ConnectionError)  dmp_set_pedometer_step_count((unsigned long)steps);  }  
}

步数计算实现

MPU6050 使用其 DMP(数字运动处理器)在内部计算步数。OV-Watch 仅在需要时检索此计数:

uint16_t HW_MPU_Get_Steps(void)  
{  #if HW_USE_IMU  unsigned long STEPS = 0;  if(!HWInterface.IMU.ConnectionError)  dmp_get_pedometer_step_count(&STEPS);  return (uint16_t)STEPS;  #endif  return 0;  
}

笔记

该项目需要对 MPU6050 DMP 库进行自定义修改,以实现低功耗。如 README 中所述:“MPU6050 不能直接使用 DMP 库。初始化后,功耗很高,需要进行一些修改以降低功耗。

这种实现方式允许 OV-Watch 在睡眠模式下保持连续计步,与正常工作时的 70-80mA 相比,实现了约 800μA 的极低功耗。

我将解释为什么以这种方式编写代码,以便从两个 8 位字节重新构造 16 位值。

了解步数检索中的字节作

查看 OV-Watch 项目中的相关代码:

steps = recbuf[1]&0x00ff; steps = steps<<8 | recbuf[2];

此代码从数组中存储的两个 8 位字节重建一个 16 位整数 (steps)。让我解释一下为什么它是这样写的:

准则的目的

此代码出现在硬件初始化任务中,系统正在从 EEPROM 内存中检索之前保存的步数。步数存储为 16 位值(可表示 0-65535 步),但作为两个独立的 8 位字节保存在 EEPROM 中。

重建如何运作

  1. 第一行:steps = recbuf[1]&0x00ff;
    • 这将获取高字节 (recbuf[1]) 并用 0x00FF 掩码它
    • 掩码作 () 在技术上是多余的,因为 recbuf[1] 已经是一个 8 位值,但它确保只使用低 8 位&0x00ff
  2. 第二行:steps = steps<<8 | recbuf[2];
    • 将高字节左移 8 位(为低字节腾出空间)
    • 然后使用按位 OR 运算将其与低字节 (recbuf[2]) 组合

为什么以这种方式存储数据?

该器件中的 EEPROM 存储使用简单的字节可寻址格式。保存 16 位步数时,它被分成两个字节:

dat[0] = nowdate.Date;  
dat[2] = temp & 0xff;         // Low byte of step count  
dat[1] = temp>>8 & 0xff;      // High byte of step count  
SettingSave(dat,0x20,3);

检索数据时,该过程将相反,以重建原始的 16 位值。

字节序注意事项

此实现使用 big-endian 格式进行存储(最高有效字节在前):

  • 高字节存储在 recbuf[1] 中
  • 低字节存储在 recbuf[2] 中

这是嵌入式系统中的常见约定,尤其是在 EEPROM 或其他字节可寻址存储中存储多字节值时。

完整上下文

此代码是设备初始化期间步数恢复过程的一部分。如果当前日期与存储的日期匹配,则系统会检索之前保存的步数并在MPU6050的计步器中进行设置:

if(recbuf[0] == nowdate.Date)  
{  uint16_t steps=0;  steps = recbuf[1]&0x00ff;  steps = steps<<8 | recbuf[2];  if(!HWInterface.IMU.ConnectionError)  dmp_set_pedometer_step_count((unsigned long)steps);  
}

这可确保步数在设备重启或睡眠周期中保持不变,从而保持准确的每日步数。

笔记

代码可以更简洁地编写为:

steps = (recbuf[1] << 8) | recbuf[2];

但是,对于某些开发人员,尤其是那些不太熟悉按位运算的开发人员,两步方法可能更具可读性。

MPU6050 OV-Watch 中的点击检测功能

您询问的是为什么MPU6050(一个运动传感器)会有点击检测功能,而这看起来应该是触摸屏的功能。这是一个很好的问题,让我来解释一下。

MPU6050的点击检测功能

在OV-Watch项目中,MPU6050确实被配置为启用了点击检测(tap detection)功能。这可以在初始化代码中看到: inv_mpu.c:2974

这里启用了三个DMP功能:

  1. DMP_FEATURE_TAP- 点击检测
  2. DMP_FEATURE_SEND_RAW_ACCEL- 原始加速度数据
  3. DMP_FEATURE_PEDOMETER- 计步器功能

点击检测与触摸屏的区别

虽然OV-Watch确实有触摸屏(在功能列表中可以看到),但MPU6050的点击检测功能与触摸屏的触摸检测是完全不同的:

  1. 触摸屏检测:检测用户在屏幕表面的触摸动作,是基于电容或电阻变化的。

  2. MPU6050点击检测:检测的是整个设备受到的物理冲击或敲击,是基于加速度传感器检测到的突然加速度变化。

MPU6050点击检测的工作原理

MPU6050的点击检测是通过其内置的DMP(数字运动处理器)实现的,它能够识别出特定的加速度模式,这些模式对应于设备被敲击或轻拍的动作。在代码中,这个功能被设置为检测X、Y、Z三个轴向的敲击: inv_mpu_dmp_motion_driver.c:1069

为什么需要这个功能?

在智能手表中,点击检测功能可以用于:

  1. 唤醒设备:当手表处于睡眠模式时,轻敲手表可以唤醒它,而不需要按按钮。

  2. 手势控制:可以通过不同方向的敲击来实现简单的手势控制,例如双击表面来确认操作。

  3. 节省电量:与持续监听触摸屏输入相比,使用加速度传感器检测敲击可能更省电。

在OV-Watch中的应用

在OV-Watch的低功耗设计中,MPU6050在手表睡眠模式下仍然保持活跃,以便继续计步和检测手腕动作: README_Eng.md:144-146

虽然最终OV-Watch项目选择使用RTC定时中断而不是MPU6050的运动检测来唤醒设备(因为需要较大的动作才能触发中断),但点击检测功能仍然被保留在代码中,可能用于其他交互功能。

笔记

  1. OV-Watch同时拥有触摸屏和MPU6050的点击检测功能,它们服务于不同的用途。

  2. 虽然在提供的代码片段中没有明确看到MPU6050的点击检测功能被如何使用,但该功能在初始化时被启用,表明它可能在某些交互场景中被使用。

  3. 值得注意的是,MPU6050的DMP功能被特别优化以降低功耗,这对于电池供电的智能手表来说是非常重要的。

相关文章:

  • 架构思维:构建高并发读服务_基于流量回放实现读服务的自动化测试回归方案
  • Kubernetes控制平面组件:Controller Manager 之 NamespaceController 全方位讲解
  • 基于windows安装MySQL8.0.40
  • Dubbo(97)如何在物联网系统中应用Dubbo?
  • 【PDF拆分+提取内容改名】批量拆分PDF提取拆分后的每个PDF物流面单数据改名或导出表格,基于WPF的PDF物流面单批量处理方案
  • 【计算机视觉】3d人脸重建:3DDFA_V2:实时高精度3D人脸重建与密集对齐技术指南
  • Linux 怎么使用局域网内电脑的网络访问外部
  • Python cv2图像几何变换全攻略:从理论到实战
  • 开源模型应用落地-qwen模型小试-Qwen3-8B-快速体验-批量推理(三)
  • 【Elasticsearch入门到落地】12、索引库删除判断以及文档增删改查
  • (一)Modular Monolith Architecture(项目结构/.net项目初始化/垂直切片架构)
  • 【NLP】30. 深入理解 In-Context Learning 的核心机制与策略
  • 浅析AI大模型为何需要向量数据库?【入门基础】
  • 【全队项目】智能学术海报生成系统PosterGenius--前后端系统介绍
  • NGINX 的 ngx_http_auth_jwt_module模块
  • 《繁花》投资、交易启示及思考
  • 深入探索 Apache Spark:从初识到集群运行原理
  • 【Hive入门】Hive安全管理与权限控制:基于SQL标准的授权GRANT REVOKE深度解析
  • Python中有序序列容器的概念及其与可变性的关系
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.4 异构数据源整合(CSV/JSON/Excel数据导入)
  • 86岁书画家、美术教育家、吴昌硕嫡裔曾孙吴民先离世
  • 怎样正确看待体脂率数据?或许并不需要太“执着”
  • 中国医药科技出版社回应发布“男性患子宫肌瘤”论文:正在核查
  • 虚构医药服务项目、协助冒名就医等,北京4家医疗机构被处罚
  • 为什么有的人闻到烟味,会咳嗽、胸闷?别再伤害身边的人
  • 多省份晒出“五一”旅游“成绩单”:北京游客接待量、旅游消费创历史新高