回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

Beetle 树莓派 RP2350:健康监测系统 简单

头像 豆爸 2025.05.18 54 0

一、项目背景

实时监测血氧浓度与心率对健康管理至关重要,血氧值低于 90% 提示缺氧风险,心率异常可反映心脏功能状态。本项目从便携健康监测的实际需求出发,结合 Beetle RP2350 开发板的微型化优势与高性能特性,利用其 I²C 接口连接 MAX30102 血氧传感器,打造轻量化、低功耗的生理指标实时监测方案,适用于可穿戴设备、移动医疗等空间受限场景,为个人健康管理提供便携解决方案。

a08b5aff226a44d5c1247084d5060680.jpg

二、学习目标

掌握 Beetle RP2350 开发板的Arduino C 编程方法。

理解 MAX30102 血氧传感器的工作原理,实现生理数据的采集与处理。

完成从硬件连接、程序编写到系统调试的全流程开发。

三、硬件准备

序号名称数量连接说明
1Beetle RP2350 开发板1主控核心,提供 I²C 通信接口(SDA - 4、SCL - 5)与电源管理
2MAX30102 血氧传感器模块1通过 I²C 接口与 Beetle 连接,采集心率与血氧数据
3锂电池(可选)1通过 BAT 接口连接,支持便携供电

3.1 Beetle RP2350 开发板

Beetle RP2350 是一款基于树莓派 RP2350 芯片的高性能迷你开发板,专为嵌入式开发和可穿戴设备设计。其核心特点包括:

双核双架构设计:支持 Arm Cortex-M33 或 Hazard3 RISC-V 内核,主频 150MHz,可灵活配置计算资源

低功耗特性:休眠电流仅 25μA,集成锂电池充电管理(支持 0.5A 充电电流)和电池电压监测功能

高度集成:在 25mm×20.5mm 尺寸上引出 11 个 GPIO、I²C、SPI 等接口,支持 3.3V/5V 供电

大容量存储:配备 520KB SRAM 和 2MB Flash,可满足复杂算法需求

开发便捷:支持 Arduino/C++、MicroPython 编程,兼容标准树莓派 Pico 生态

3a8983b1a6894c13755656d58903d643.png
引脚号数字口模拟口UARTI2CSPI其它
0D0 TX1
1D1 RX1
4D4 SDA
5D5 SCL
8D8 TX2
9D9 RX2
16D16 SPI0/MISO
18D18 SPI0/SCK
19D19 SPI0/MOSI
26D26A0
27D27A1
29 ADC,锂电池电压检测引脚,分压比为 1:2
BAT 锂电池输入接口
GND 接地引脚
VCC 该引脚接在USB电源引脚,作为输出时电压为USB电压,通常为5V
3V3 3.3V稳压电源输出

3.2 MAX30102 心率血氧传感器

MAX30102 心率血氧传感器模块搭载了美信(maxim)的MAX30102心率血氧芯片和一颗集成心率血氧算法的微控制器。模块内部集成了红外LED、红色光LED和光电检测器,通过红外LED和红色光LED照射皮肤,然后光电检测器采集反射光信号,进而进行血氧饱和度和心率的计算。

光学检测原理:

内置红光 LED(660nm)和红外 LED(880nm),通过皮肤组织发射光线

光电二极管捕捉反射光信号,检测血液容积变化产生的脉搏波

血氧饱和度(SpO2)计算:

氧合血红蛋白(HbO₂)和脱氧血红蛋白(HHb)对不同波长光的吸收特性差异

通过朗伯 - 比尔定律,分析红光 / 红外光吸收比例推算 SpO2 值

心率测量:

提取脉搏波信号的周期性变化,计算每分钟心跳次数

低功耗设计:

工作电流 < 5mA,待机电流仅 0.7μA,适合可穿戴设备应用

接口特性:

标准 I²C 通信接口,支持高速模式(400kHz)

src=http%3A%2F%2Fimg.alicdn.com%2Fi1%2F1639117447%2FO1CN01kItqbV24smFo1Tu8A_!!1639117447.jpg&refer=http%3A%2F%2Fimg.alicdn.jpeg
src=http%3A%2F%2Fimg.alicdn.com%2Fi3%2F1639117447%2FO1CN01dlkaAT24smFo1Q58N_!!1639117447.jpg&refer=http%3A%2F%2Fimg.alicdn.jpeg

四、接线图

Beetle RP2350 MAX30102 OLED
3.3V VCC VCC
GND GND GND
4 (SDA) SDA SDA
5 (SCL) SCL SCL

五、流程图

image.png

六、程序编写

6.1 开发环境

1. Arduino IDE安装Beetle RP2350 开发板

步骤 1:添加开发板管理器网址

打开 Arduino IDE 后,点击菜单栏中的 文件 -> 首选项。

在弹出的 首选项 窗口中,找到 附加开发板管理器网址 输入框。

输入 Beetle RP2350 开发板的支持包链接。通常可以在开发板的官方文档或者社区中找到对应的链接。对于 RP2350 开发板,一般使用的链接是 https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json。

点击 确定 保存设置。

image-20250516074502812.png
步骤 2:安装 Beetle RP2350 开发板支持

点击菜单栏中的 工具 -> 开发板 -> 开发板管理器,在开发板管理器窗口中,等待索引更新完成。

在搜索框中输入 RP2350。

在搜索结果中找到 Raspberry Pi Pico/RP2040/RP2350 并点击 安装 按钮。

image-20250516073904537.png

等待安装过程完成,这可能需要一些时间,具体取决于你的网络速度。

步骤 3:选择 Generic RP2350 开发板

安装完成后,点击菜单栏中的 工具 -> 开发板,在开发板列表中选择 Generic RP2350。

4E885EEB-63FA-4447-A72E-A208DD093520.png
步骤 4:选择端口

将 Beetle RP2350 开发板通过 USB 线连接到计算机。点击菜单栏中的 工具 -> 端口,选择与开发板对应的端口。

完成以上步骤后,你就可以在 Arduino IDE 中使用 Beetle RP2350 开发板进行编程和开发了。你可以编写代码并上传到开发板上运行。

2. 安装库文件

在 Arduino IDE 的菜单栏中,选择 工具 -> 管理库,这将打开库管理器窗口。

1.搜索并安装MAX30102

在库管理器的搜索框中输入 MAX30102,然后在搜索结果中找到对应的库。点击 安装 按钮,等待安装完成。这个库是专门为 MAX30102 这类生物传感器设计的驱动库,支持对传感器进行数据读取与配置操作。通过该库,能够方便地从 MAX30102 传感器获取心率和血氧饱和度等生理数据。

image-20250518175047831.png
2. 搜索并安装 Adafruit GFX Library

在库管理器的搜索框中输入 Adafruit GFX Library,然后在搜索结果中找到对应的库。点击 安装 按钮,等待安装完成。这个库是 Adafruit 图形库,提供了基本的图形绘制功能,许多 Adafruit 的显示设备都会依赖这个库。

image-20250516072303169.png
3. 搜索并安装 Adafruit SSD1306

在库管理器的搜索框中输入 Adafruit SSD1306,在搜索结果中找到该库后,点击 安装 按钮进行安装。这个库专门用于驱动基于 SSD1306 芯片的 OLED 显示屏,项目中使用的 0.96 寸 OLED 显示屏正是基于此芯片。

image-20250516072543257.png

6.2 主要程序代码及说明

代码
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "heartRate.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128             // OLED分辨率
#define SCREEN_HEIGHT 64             // OLED分辨率
#define OLED_RESET     -1            // 复位引脚,不接
#define BATT_PIN       29            // 电池检测引脚(IO29)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

MAX30105 particleSensor;

// 数据缓冲区和计算结果
#define SAMPLE_SIZE 100
uint32_t irBuffer[SAMPLE_SIZE];      // 红外光数据缓冲区
uint32_t redBuffer[SAMPLE_SIZE];     // 红光数据缓冲区
int32_t heartRateValue = 0;          // 心率值
int8_t validHeartRate = 0;           // 心率计算有效性标志
int32_t spo2Value = 0;               // 血氧饱和度值
int8_t validSPO2 = 0;                // 血氧计算有效性标志
float temperatureValue = 0.0;        // 温度值
const float TEMP_CALIBRATION = 0.5;  // 温度校准偏移量
int32_t signalStrength = 0;          // 信号强度指标

// 心率计算相关变量
const byte RATE_SIZE = 4;            // 心率平均值计算窗口大小
byte rates[RATE_SIZE];               // 心率值数组
byte rateSpot = 0;
long lastBeat = 0;                   // 上次心跳时间戳
uint32_t beatCount = 0;              // 心跳计数

// 显示区域定义
#define STATUS_AREA_Y      0
#define BATTERY_AREA_X    100
#define SPO2_AREA_Y       15
#define HR_AREA_Y         35
#define SIGNAL_AREA_Y     55

// 手指检测稳定性参数
const byte FINGER_STABILIZE_COUNT = 3;
byte fingerStableCount = 0;

// 状态评估常量
enum Status {
  STATUS_NORMAL,           // 正常
  STATUS_MILD_HYPOXIA,     // 轻度缺氧
  STATUS_SEVERE_HYPOXIA,   // 重度缺氧
  STATUS_TACHYCARDIA,      // 心动过速
  STATUS_BRADYCARDIA,      // 心动过缓
  STATUS_INVALID,          // 测量中
  STATUS_FINGER_MISSING    // 手指未放置
};

// 初始化传感器
bool initializeSensor() {
  Serial.println("MAX30102健康监测系统初始化中...");
  
  // 初始化传感器
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("错误:未找到MAX30102传感器,请检查接线和电源!");
    return false;
  }

  // 配置传感器参数(优化信号质量)
  byte ledBrightness = 40;   // 降低LED亮度,避免信号饱和
  byte sampleAverage = 8;    // 增加采样平均,提高稳定性
  byte ledMode = 2;          // 双模模式(红光+红外)
  byte sampleRate = 100;     // 采样率(100Hz)
  int pulseWidth = 411;      // 脉冲宽度
  int adcRange = 4096;       // ADC范围
  
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
  particleSensor.enableDIETEMPRDY();  // 启用温度测量
  
  Serial.println("传感器就绪");
  return true;
}

// 初始化显示屏
void initializeDisplay() {
  // 初始化OLED显示屏
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306显示屏初始化失败"));
    for(;;);
  }

  // 显示初始化画面(英文)
  clearDisplayArea(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("MAX30105 Health Monitor");
  display.setTextSize(2);
  display.setCursor(30, 20);
  display.println("Initializing...");
  display.setTextSize(1);
  display.setCursor(0, 50);
  display.println("Place finger on sensor");
  display.display();
  delay(2000);
}

// 清除指定区域
void clearDisplayArea(int16_t x, int16_t y, int16_t w, int16_t h) {
  display.fillRect(x, y, w, h, SSD1306_BLACK);
}

// 检测手指是否正确放置(增强稳定性)
bool isFingerPresent() {
  while (!particleSensor.available()) 
    particleSensor.check();
  
  uint32_t irValue = particleSensor.getIR();
  signalStrength = irValue / 1000; // 计算信号强度指标
  
  // 连续稳定检测到手指才返回true
  if (irValue > 50000) {
    fingerStableCount = min(fingerStableCount + 1, FINGER_STABILIZE_COUNT);
  } else {
    fingerStableCount = 0;
  }
  
  return fingerStableCount >= FINGER_STABILIZE_COUNT;
}

// 获取电池电量百分比(适配分压电路)
int getBatteryLevel() {
  int adcValue = analogRead(BATT_PIN);
  float voltage = adcValue * (3.3 / 1023.0) * 2.0;
  int batteryPercent = constrain(map(voltage * 100, 300, 370, 0, 100), 0, 100);
  
  return batteryPercent;
}

// 获取血氧饱和度
int getSPO2() {
  return validSPO2 ? spo2Value : 0;
}

// 获取心率(添加数据过滤)
int getHeartbeat() {
  int hr = validHeartRate ? heartRateValue : 0;
  // 过滤异常心率值(正常范围:20-200 BPM)
  return (hr >= 20 && hr <= 200) ? hr : 0;
}

// 获取温度(摄氏度)
float getTemperature_C() {
  return temperatureValue;
}

// 计算平均心率
int calculateAverageRate() {
  byte sum = 0;
  byte count = 0;
  for (byte i = 0; i < RATE_SIZE; i++) {
    if (rates[i] > 20 && rates[i] <= 200) { // 只统计有效心率
      sum += rates[i];
      count++;
    }
  }
  return count > 0 ? sum / count : 0;
}

// 评估综合状态
Status evaluateStatus() {
  if (!isFingerPresent()) return STATUS_FINGER_MISSING;
  if (!validHeartRate || !validSPO2) return STATUS_INVALID;
  
  int hr = getHeartbeat();
  int spo2 = getSPO2();
  
  if (spo2 >= 95 && hr >= 60 && hr <= 100) {
    return STATUS_NORMAL;
  } else if (spo2 >= 90 && spo2 < 95) {
    return STATUS_MILD_HYPOXIA;
  } else if (spo2 < 90) {
    return STATUS_SEVERE_HYPOXIA;
  } else if (hr > 100 && hr <= 200) {
    return STATUS_TACHYCARDIA;
  } else if (hr < 60 && hr >= 20) {
    return STATUS_BRADYCARDIA;
  } else {
    return STATUS_INVALID;
  }
}

// 获取状态文本描述(中文,用于串口输出)
const char* getStatusTextCN(Status status) {
  switch(status) {
    case STATUS_NORMAL: return "正常";
    case STATUS_MILD_HYPOXIA: return "轻度缺氧";
    case STATUS_SEVERE_HYPOXIA: return "重度缺氧";
    case STATUS_TACHYCARDIA: return "心动过速";
    case STATUS_BRADYCARDIA: return "心动过缓";
    case STATUS_INVALID: return "测量中...";
    case STATUS_FINGER_MISSING: return "请放手指";
    default: return "未知";
  }
}

// 获取状态文本描述(英文,用于OLED显示)
const char* getStatusTextEN(Status status) {
  switch(status) {
    case STATUS_NORMAL: return "Normal";
    case STATUS_MILD_HYPOXIA: return "Mild Hypoxia";
    case STATUS_SEVERE_HYPOXIA: return "Severe Hypoxia";
    case STATUS_TACHYCARDIA: return "Tachycardia";
    case STATUS_BRADYCARDIA: return "Bradycardia";
    case STATUS_INVALID: return "Measuring";
    case STATUS_FINGER_MISSING: return "Place Finger";
    default: return "Unknown";
  }
}

// 更新OLED显示内容(英文)
void updateOLEDDisplay() {
  Status currentStatus = evaluateStatus();
  
  // 清屏准备显示新数据
  display.clearDisplay();
  
  // 显示状态文本(英文)
  clearDisplayArea(0, STATUS_AREA_Y, SCREEN_WIDTH, 10);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, STATUS_AREA_Y);
  display.print("Stat:");
  display.println(getStatusTextEN(currentStatus));
  
  // 显示电池电量
  clearDisplayArea(BATTERY_AREA_X, STATUS_AREA_Y, SCREEN_WIDTH - BATTERY_AREA_X, 10);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(BATTERY_AREA_X + 3, STATUS_AREA_Y);
  display.print(getBatteryLevel());
  display.println("%");
  
  // 显示血氧数据
  clearDisplayArea(0, SPO2_AREA_Y, SCREEN_WIDTH, 15);
  display.setTextSize(2);
  display.setCursor(0, SPO2_AREA_Y);
  display.print("SPO2: ");
  if (validSPO2 && spo2Value >= 70 && spo2Value <= 100) {
    display.setTextColor(SSD1306_WHITE);
    display.print(spo2Value);
    display.println("%");
  } else {
    display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
    display.println("-- %");
  }
  
  // 显示心率数据
  clearDisplayArea(0, HR_AREA_Y, SCREEN_WIDTH, 15);
  display.setTextSize(2);
  display.setCursor(0, HR_AREA_Y);
  display.print("HR: ");
  if (validHeartRate && heartRateValue >= 20 && heartRateValue <= 200) {
    display.setTextColor(SSD1306_WHITE);
    display.print(heartRateValue);
    display.print(" BPM");
  } else {
    display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
    display.println("-- BPM");
  }
  
  // 显示信号强度
  clearDisplayArea(0, SIGNAL_AREA_Y, SCREEN_WIDTH, 10);
  display.setTextSize(1);
  display.setCursor(0, SIGNAL_AREA_Y);
  display.print("Signal: ");
  display.print(min(signalStrength, 100)); // 限制最大值为100
  display.print("/100");
  
  // 显示心跳动画
  if (validHeartRate && beatCount % 2 == 0) {
    clearDisplayArea(115, SIGNAL_AREA_Y, 10, 10);
    display.setTextSize(1);
    display.setCursor(115, SIGNAL_AREA_Y);
    display.print("♥");
  } else {
    clearDisplayArea(115, SIGNAL_AREA_Y, 10, 10);
  }
  
  // 将缓冲区内容刷新到屏幕
  display.display();
}

// 串口输出监测数据(中文)
void printSensorDataToSerial() {
  Status currentStatus = evaluateStatus();
  
  // 输出时间戳
  Serial.print("时间: ");
  Serial.print(millis() / 1000);
  Serial.println("秒");
  
  // 输出状态
  Serial.print("状态: ");
  Serial.println(getStatusTextCN(currentStatus));
  
  // 输出血氧
  Serial.print("血氧饱和度: ");
  if (validSPO2 && spo2Value >= 70 && spo2Value <= 100) {
    Serial.print(spo2Value);
    Serial.println(" %");
  } else {
    Serial.println("未检测到");
  }
  
  // 输出心率
  Serial.print("心率: ");
  if (validHeartRate && heartRateValue >= 20 && heartRateValue <= 200) {
    Serial.print(heartRateValue);
    Serial.print(" BPM (平均: ");
    Serial.print(calculateAverageRate());
    Serial.println(" BPM)");
  } else {
    Serial.println("未检测到");
  }
  
  // 输出信号强度
  Serial.print("信号强度: ");
  Serial.print(min(signalStrength, 100)); // 限制最大值为100
  Serial.println("/100");
  
  // 输出电池电量
  Serial.print("电池电量: ");
  Serial.print(getBatteryLevel());
  Serial.println("%");
  
  // 输出温度
  Serial.print("传感器温度: ");
  Serial.print(getTemperature_C(), 1);
  Serial.println(" °C");
  
  // 分隔线
  Serial.println("===================================");
  Serial.println();
}

// 采集一次完整数据
void collectSensorData() {
  // 检测手指是否放置
  if (!isFingerPresent()) {
    validHeartRate = 0;
    validSPO2 = 0;
    return;
  }
  
  // 数据缓冲区滑动
  for (byte i = 25; i < SAMPLE_SIZE; i++) {
    redBuffer[i - 25] = redBuffer[i];
    irBuffer[i - 25] = irBuffer[i];
  }

  // 采集新数据
  for (byte i = SAMPLE_SIZE - 25; i < SAMPLE_SIZE; i++) {
    while (!particleSensor.available()) 
      particleSensor.check();
    
    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample();
  }

  // 计算心率和血氧
  maxim_heart_rate_and_oxygen_saturation(irBuffer, SAMPLE_SIZE, redBuffer, &spo2Value, &validSPO2, &heartRateValue, &validHeartRate);
  
  // 过滤异常心率值
  if (validHeartRate && (heartRateValue < 20 || heartRateValue > 200)) {
    validHeartRate = 0;
  }
  
  // 过滤异常血氧值
  if (validSPO2 && (spo2Value < 70 || spo2Value > 100)) {
    validSPO2 = 0;
  }
  
  // 更新心率平均值计算
  if (validHeartRate) {
    long irValue = particleSensor.getIR();
    if (checkForBeat(irValue) == true) {
      beatCount++;
      long delta = millis() - lastBeat;
      lastBeat = millis();

      float bpm = 60 / (delta / 1000.0);
      if (bpm > 20 && bpm <= 200) {
        rates[rateSpot++] = (byte)bpm;
        rateSpot %= RATE_SIZE;
      }
    }
  }
  
  // 读取温度数据
  temperatureValue = particleSensor.readTemperature() + TEMP_CALIBRATION;
}

// 显示错误信息(英文)
void displayError(const char* message) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("ERROR");
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.println(message);
  display.setTextSize(1);
  display.setCursor(0, 50);
  display.println("Please restart device");
  display.display();
}

void setup() {
  Serial.begin(115200);
  pinMode(BATT_PIN, INPUT);
  
  initializeDisplay();
  
  if (!initializeSensor()) {
    displayError("Sensor Connection Failed");
    while (1) delay(1000);  // 保持错误状态
  }
  
  lastBeat = millis();
  memset(rates, 0, sizeof(rates)); // 初始化心率数组
  
  // 串口输出初始化完成信息
  Serial.println("初始化完成,请将手指放在传感器上");
  Serial.println("开始测量...");
  Serial.println("===================================");
}

void loop() {
  static unsigned long lastUpdateTime = 0;
  static unsigned long lastSensorCheckTime = 0;
  static unsigned long lastSerialOutputTime = 0;
  
  // 每100ms检查传感器状态
  if (millis() - lastSensorCheckTime >= 100) {
    collectSensorData();
    lastSensorCheckTime = millis();
  }
  
  // 每秒更新一次OLED显示
  if (millis() - lastUpdateTime >= 1000) {
    updateOLEDDisplay();
    lastUpdateTime = millis();
  }
  
  // 每2秒串口输出一次数据
  if (millis() - lastSerialOutputTime >= 2000) {
    printSensorDataToSerial();
    lastSerialOutputTime = millis();
  }
  
  // 低功耗延时
  delay(10);
}    

七、系统运行结果

这个系统整合了 MAX30102 生物传感器和 0.96 寸 OLED 显示屏,能够实时监测并显示人体脉率、血氧饱和度等生理参数。以下是硬件运行时的详细效果描述:

1. 初始化阶段

OLED 显示

启动时显示初始化画面:

image.png

若传感器连接成功,OLED 会继续显示相关提示信息,等待用户操作。

若连接失败(如 I2C 通信异常),OLED 显示错误信息:

image.png

串口输出

image.png

2. 测量阶段

2.1 手指未放置或信号弱

OLED 显示

image.png

串口输出

image.png

2.2 正常测量状态

OLED 显示(动态更新)

image.png

串口输出

image.png

3. 不同健康状态下的显示效果

3.1 正常状态

脉率:60 - 100 BPM

血氧:≥95%

OLED 显示

image.png

文字颜色为白色(默认)。

3.2 轻度缺氧

脉率:可能升高(身体代偿反应)

血氧:90 - 94%

OLED 显示

image.png

3.3 重度缺氧

脉率:可能显著升高或不规则

血氧:< 90%

OLED 显示

image.png

4. 硬件交互效果

硬件交互主要体现在手指放置和移除时系统的响应。当手指放置在传感器上且信号稳定时,系统开始正常测量并显示数据;当手指移除时,系统会提示手指未放置,增强了用户与系统之间的互动性。

八、项目扩展与优化

接入Wifi网络:利用ESP8266模块通过串口通信让 Beetle RP2350 与 ESP8266 进行数据交互,实现接入Wifi网络。

数据可视化:通过 MQTT 协议将数据上传至物联网平台(如 SIoT),实现远程监控与历史数据查询。

低功耗设计:利用 Beetle 的睡眠模式与传感器待机模式,延长电池续航。

九、附件

评论

user-avatar