1. 项目概述与设计初衷在健身房撸铁的时候你有没有过这样的经历一组动作做到力竭大脑一片空白完全记不清这是第几组了还得停下来掰着手指头数或者跟教练反复确认。这种打断不仅影响训练节奏也容易让好不容易积攒的泵感消散。作为一个电子工程师兼健身爱好者我决定自己动手解决这个小痛点——做一个能戴在手腕上、随时显示训练组数的智能手环。这个项目的核心目标很明确打造一个极度紧凑、可穿戴、操作直观的健身组数计数器。它不需要复杂的传感器来自动识别动作那样成本高且容易误判。我的思路是“半自动”由我手动设定一个动作的目标组数比如卧推做4组然后每完成一组就按一下按钮手环上的LED灯会实时显示已完成组数。当完成的灯数等于目标灯数时手环会用炫彩灯光给我一个明确的“任务完成”反馈然后我就可以清空计数器进行下一个动作。整个设备围绕Atmega328PB这颗微控制器和WS2812B可编程LED构建。选择它们的原因很简单Atmega328PB在保持与经典Arduino UNO核心ATmega328P高度兼容的同时体积更小、外设更丰富而WS2812B只需要一根数据线就能驱动成百上千颗LED极大地简化了电路布线和程序控制是实现紧凑型点阵显示的绝佳选择。从画电路板PCB到3D打印一个柔性的表带外壳我将带你走完一个完整硬件产品从概念到实物的全流程。无论你是想做一个实用的健身伴侣还是想学习如何将Arduino项目“产品化”这个案例都有很多值得挖掘的细节。2. 核心硬件选型与电路设计解析2.1 微控制器为什么是Atmega328PB在开源硬件领域ATmega328P几乎是Arduino Uno的代名词稳定、资源丰富、生态完善。但当我们追求“可穿戴”和“紧凑”时它的体积常见的DIP-28或TQFP-32封装就成了障碍。这时Atmega328PB进入了我的视野。Atmega328PB可以看作是328P的“升级紧凑版”。它最大的优势在于提供了更小的封装选项例如我这次采用的32-pin MLFMicro Lead Frame封装。这种封装没有向外延伸的引脚芯片底部是焊盘通过回流焊直接贴在PCB上能极大地节省空间。性能上它完全兼容328P的指令集和大部分外设意味着我们熟悉的Arduino核心库和编程方式可以无缝迁移。此外PB版本还额外增加了一个硬件串口共有两个UART和更多的定时器/PWM资源为未来功能扩展留有余地。注意MLF这类封装属于QFNQuad Flat No-leads的一种手工焊接有一定难度需要热风枪或返修台。对于新手如果追求可手工焊接可以选择TQFP封装薄型四方扁平封装的328PB它虽然比MLF大一点但仍有引脚露出用尖头烙铁可以操作。2.2 显示单元WS2812B LED的优势与驱动逻辑显示方案我放弃了传统的七段数码管或LCD屏因为它们通常需要更多的IO口和驱动电路。WS2812B也被Adafruit称为NeoPixel是一款集成了控制电路和RGB三色LED的智能外设。其革命性在于采用了单线归零码通信协议。单线控制意味着什么传统LED点阵要控制N个灯可能需要N1根线共阳或共阴。而WS2812B只需要三根线电源VCC、地GND和一根数据线DIN。第一个LED的数据线接MCU第二个LED的数据线接第一个LED的DOUT引脚如此串联下去。MCU只需要通过一根IO口按照特定的时序发送一串数据这串数据就会像流水一样经过第一个、第二个……直到最后一个LED每个LED会自动截取属于自己的24位RGB数据8位红8位绿8位蓝然后将剩余数据转发给下一个。这种“串联”结构让布线变得极其简单特别适合在狭长空间如手环排列。在这个项目中我使用了12颗WS2812B排列成两列每列6颗。左边一列LED 0-5代表“目标组数”右边一列LED 6-11代表“已完成组数”。通过程序我可以轻松地控制任意一颗LED显示任意颜色和亮度。例如目标设为4组就让左边的前4颗灯亮起蓝色每完成一组就让右边对应点亮一颗绿色灯全部完成后让所有灯跑一个彩虹流光效果作为庆祝。2.3 核心电路原理图设计要点电路设计是在Altium Designer中完成的。整个系统的供电心脏是一颗3.7V的锂聚合物电池。为了能方便地充电我加入了基于TP4056芯片的充电管理模块并通过一个USB-C接口接入5V电源。TP4056是一款非常经典的线性充电IC外围电路简单只需几个电阻电容能提供稳定的1A充电电流并带有充电状态指示红/蓝LED。主控电路围绕Atmega328PB展开。除了必要的电源滤波电容0.1uF的贴片电容要尽量靠近MCU的VCC引脚放置这是保证数字电路稳定工作的黄金法则我还为其设计了两种时钟源选项一是外部16MHz晶振二是内部8MHz RC振荡器。为了追求极致紧凑和节省两个晶振焊盘的空间我最终选择了内部振荡器。对于这个计数应用时间精度要求不高内部振荡器完全足够且更省电、更可靠无外部元件失效风险。输入部分是两个轻触开关分别用于“增加目标组数”和“增加已完成组数”。它们通过10kΩ的上拉电阻接到VCC常态下MCU检测到高电平按下时接地变为低电平。这里在开关两端并联了一个0.1uF的电容用于硬件消抖虽然软件消抖也必不可少但硬件上的预防能进一步提升可靠性。输出部分就是WS2812B灯链。需要注意的是WS2812B的工作电压典型值是5V而我们的系统电压是3.7V电池~4.2V满电。实测表明在3.5V以上电压时WS2812B依然可以正常工作只是亮度略有降低这对于手环显示是可接受的。为了确保信号电平匹配我将MCU的IO口输出5V TTL电平直接连接到了LED的数据输入脚。在3.3V系统下可能需要一个电平转换电路但本例中我们避免了这个问题。电源路径管理是一个小细节但很重要。我使用了一个MOS管如SI2301来实现USB供电和电池供电的自动切换。当插入USB时MOS管导通系统由USB的5V经降压后供电同时TP4056给电池充电当拔掉USB时MOS管关闭系统由电池供电。这防止了电池通过USB路径反向漏电。3. PCB布局设计与制造实战3.1 在Altium Designer中进行布局规划原理图完成后更考验功力的是PCB布局。对于可穿戴设备尺寸是硬约束。我将板子尺寸定为30mm x 30mm一个非常小巧的方形。布局的核心原则是“功能分区”和“信号流导向”电源区我将USB-C接口和TP4056充电电路放在板子的一端边缘这样USB口可以露在外面。TP4056的充电电流设置电阻Rprog和电池连接端子BAT BAT-都安排在这个区域附近走线短而粗以减少压降和发热。主控区Atmega328PB放在板子中央这是所有信号的枢纽。其周围的去耦电容必须紧贴对应的电源引脚尤其是VCC和AVCC。输入/输出区两个按钮开关放在板子另一侧边缘便于手指按压。WS2812B LED的排布是难点。我需要12颗LED排成两列。由于WS2812B是串联通信PCB走线必须严格按照“数据流”顺序MCU的D9引脚 - LED0的DIN - LED0的DOUT - LED1的DIN … - LED5的DOUT - LED6的DIN … - LED11的DOUT悬空。在狭小空间内要保证这12个LED的物理位置顺序与数据流顺序完全一致需要精心规划。我采用了两列背靠背的布局中间通过过孔连接数据线。电池连接器放在板子背面空闲区域选用小型的2-pin JST PH接头。布线要点电源线VCC GND优先加粗。我使用了20mil约0.5mm的线宽。地平面GND尽可能保持完整采用铺铜方式为数字信号提供稳定的回流路径。WS2812B的数据线DATA是关键的高速数字信号线虽然速率只有800kbps但时序要求严苛。我尽量让这条线走线短、直避免锐角并远离电源等可能产生噪声的线路。在数据线靠近MCU输出端串联一个100欧姆的电阻有助于抑制信号过冲和振铃。为调试留出接口虽然追求紧凑但我还是挤出了空间放置了一个6-pin的ICSP在线串行编程焊盘。这样我可以用烧录器直接给板子上的MCU刷写Bootloader和程序而不必依赖预烧录好的芯片。3.2 生成Gerber文件与下单打样PCB设计完成后需要将设计文件转换为制造商能理解的通用格式——Gerber文件。在Altium Designer中通过“文件”-“制造输出”-“Gerber Files”可以很方便地生成。通常需要生成以下层顶层铜Top Layer底层铜Bottom Layer顶层丝印Top Overlay顶层阻焊Top Solder Mask底层阻焊Bottom Solder Mask板子轮廓Keep-Out Layer或Mechanical Layer钻孔文件NC Drill Files将这些文件打包成ZIP就可以去PCB打样厂商下单了。我选择了JLCPCB因为其对小批量、低成本打样非常友好。在它们的网站上上传Gerber文件后会自动解析出板子预览。你需要确认几个关键参数板子尺寸30*30mm。板子层数2层。板子厚度常规1.6mm即可。铜厚1盎司约35μm。阻焊颜色我选了黑色看起来更酷。表面工艺有铅喷锡HASL成本最低但若追求更平整、更适合小间距贴片焊接可以选择沉金ENIG当然价格会高一些。同时我订购了钢网Stencil。钢网是一张带有镂空图案的不锈钢薄片图案对应PCB上的焊盘。在焊接贴片元件时将钢网对齐盖在PCB上刮上锡膏锡膏就会通过镂空处漏印到焊盘上之后放上元件用热风枪或回流焊炉加热即可完成焊接。对于有大量贴片元件的板子钢网是必备工具。实操心得第一次在JLCPCB下单时务必仔细检查它们系统生成的3D预览图我曾因为疏忽没发现丝印层一个元件的方向标反了导致焊接时搞错极性。虽然电气连接可能没错但影响美观和后期调试。现在养成了习惯下单前必看3D预览并核对关键元件的封装和方向。4. 焊接组装与生产技巧4.1 回流焊接使用热板进行小批量生产收到PCB和钢网后就进入激动人心的组装环节。对于MLF封装的MCU和0402规格的阻容元件手工烙铁焊接非常困难且容易损坏焊盘。我采用的方法是热板回流焊这是一种低成本、适合极客和小批量制作的方法。所需材料和工具焊锡膏我选用的是Chip Quik SMDLTLFP10T5这是一种低熔点138°C的锡膏对热板非常友好。刮刀用于将锡膏刮过钢网。热板一个普通的恒温加热板即可。镊子高精度防静电镊子用于拾放元件。放大镜或台灯便于观察微小元件。洗板水或异丙醇焊接后清洗板子。步骤固定与对位将PCB放在平稳台面上用胶带稍微固定。将钢网小心地盖在PCB上确保每个焊盘孔都精确对准。印刷锡膏取一小团锡膏放在钢网一端用刮刀以大约45度角均匀用力将锡膏刮过整个钢网。抬起钢网你会看到PCB每个焊盘上都留下了一个大小均匀的锡膏点。贴装元件借助放大镜和镊子按照从中间MCU到外围、从小元件到大元件的顺序将所有贴片元件放到对应的锡膏上。MLF封装的MCU对准是关键引脚大致对准焊盘即可锡膏熔化时的表面张力会将其自动“拉正”。回流焊接将贴好元件的PCB小心移到预热好的热板上。观察锡膏的变化先会变亮然后慢慢熔化变成光滑的液态最后冷却凝固。整个过程大约2-3分钟。看到所有焊点的锡都变得圆润光亮后用镊子轻轻将板子夹起放在耐热垫上冷却。清洗与检查冷却后用棉签蘸取洗板水或异丙醇轻轻擦拭焊点周围去除残留的助焊剂。然后在放大镜下仔细检查每个焊点看是否有虚焊、连锡、元件立碑等问题。避坑指南热板温度不均匀是常见问题。可能导致一边的锡熔化了另一边还没化。解决方法是将PCB放在热板中心区域并在加热过程中用镊子轻轻拨动板子边缘使其受热更均匀。另外锡膏量很重要太多容易连锡太少则焊接不牢。初次尝试可以先在废板上练习。4.2 通孔元件与后期装配回流焊完成后板上剩下的就是USB-C接口、按钮、电池插座等通孔元件了。这些可以用普通烙铁进行焊接。焊接USB-C接口这是一个难点因为引脚密集。使用尖头烙铁和细焊锡丝并配合助焊剂可以让你事半功倍。先固定两个对角的位置引脚再焊接其他引脚。焊接按钮和插座这些就相对简单了。注意按钮不要长时间加热以免塑料部分熔化。连接电池最后将锂聚合物电池的插头连接到PCB的电池插座上。务必注意正负极通常红色线是正极BAT黑色线是负极BAT-。接反可能会损坏充电芯片甚至电池。焊接全部完成后先不要急着装外壳进行下一步的软件烧录和功能测试。5. 固件开发Arduino程序逻辑详解5.1 开发环境搭建与库依赖编程使用我们熟悉的Arduino IDE。首先需要确保你的IDE支持Atmega328PB。由于328PB不是官方Arduino核心默认包含的型号你需要安装一个第三方核心。我使用的是MiniCore这是一个非常优秀的第三方硬件支持包。安装步骤打开Arduino IDE进入“文件”-“首选项”在“附加开发板管理器网址”中添加https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json打开“工具”-“开发板”-“开发板管理器”搜索“MiniCore”找到并安装。安装完成后在“工具”-“开发板”菜单下选择“MiniCore”然后选择“ATmega328PB”。进一步在“工具”菜单下选择正确的时钟频率内部8MHz、编程器USBasp或你使用的ISP编程器和端口。接下来安装WS2812B的驱动库。在库管理器中搜索“Adafruit NeoPixel”并安装。这个库封装了复杂的时序控制让我们可以用简单的API来控制LED。5.2 程序结构与核心逻辑剖析完整的程序代码我会在文末提供下载链接这里拆解几个关键部分。初始化与定义#include Adafruit_NeoPixel.h #define LED_PIN 9 // WS2812B数据线连接的引脚 #define NUM_LEDS 12 // LED总数 #define TARGET_BUTTON_PIN 3 // “目标组数”按钮 #define DONE_BUTTON_PIN 4 // “完成组数”按钮 Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB NEO_KHZ800); int targetSets 0; // 目标组数范围0-6 int doneSets 0; // 已完成组数范围0-6 bool exerciseComplete false; // 训练是否完成的标志这里定义了硬件连接和全局变量。strip对象是我们控制所有LED的接口。按钮检测与消抖 机械按钮在按下和弹起时会产生一段时间的抖动导致MCU误判为多次按下。我们需要在软件中消抖。bool readButton(int pin) { static int lastState HIGH; // 按钮上一次稳定状态 static unsigned long lastDebounceTime 0; int reading digitalRead(pin); if (reading ! lastState) { lastDebounceTime millis(); // 重置消抖计时器 } if ((millis() - lastDebounceTime) 50) { // 消抖时间50ms // 如果当前读取的状态与保存的稳定状态不同 if (reading ! buttonState) { buttonState reading; if (buttonState LOW) { // 按钮被按下低电平有效 return true; } } } lastState reading; return false; }这个函数在每次循环中被调用检查指定引脚的电平。只有当低电平状态稳定超过50毫秒才认为是一次有效的按键。主循环逻辑void loop() { // 1. 检查目标组数按钮 if (readButton(TARGET_BUTTON_PIN)) { targetSets (targetSets 1) % 7; // 循环增加0-6 updateDisplay(); exerciseComplete false; // 修改目标后重置完成状态 } // 2. 检查完成组数按钮 if (readButton(DONE_BUTTON_PIN) !exerciseComplete) { doneSets; if (doneSets 6) doneSets 6; // 限制最大值 updateDisplay(); // 3. 检查是否完成 if (doneSets targetSets targetSets 0) { exerciseComplete true; celebrateAnimation(); // 播放庆祝动画 } } // 4. 长按完成按钮重置可选功能 if (checkLongPress(DONE_BUTTON_PIN)) { targetSets 0; doneSets 0; exerciseComplete false; updateDisplay(); } }主循环清晰明了检测两个按钮更新计数刷新显示判断是否完成。updateDisplay()函数根据targetSets和doneSets的值控制左边6颗和右边6颗LED的亮灭与颜色。显示更新函数void updateDisplay() { strip.clear(); // 先关闭所有LED // 显示目标组数左边蓝色 for (int i 0; i targetSets; i) { strip.setPixelColor(i, strip.Color(0, 0, 150)); // 蓝色 } // 显示已完成组数右边绿色 for (int i 0; i doneSets; i) { strip.setPixelColor(i 6, strip.Color(0, 150, 0)); // 绿色 } // 如果已完成等于目标且不为零将已完成的灯变为黄色提示 if (doneSets targetSets targetSets 0) { for (int i 0; i doneSets; i) { strip.setPixelColor(i 6, strip.Color(150, 150, 0)); // 黄色 } } strip.show(); // 发送数据到LED }strip.show()是实际将颜色数据发送到LED链的命令在此之前的所有setPixelColor操作都只是在内存中准备数据。庆祝动画 当训练完成时调用一个简单的彩虹循环动画增加趣味性。void celebrateAnimation() { for (int j 0; j 256 * 5; j) { // 循环5次彩虹 for (int i 0; i strip.numPixels(); i) { strip.setPixelColor(i, Wheel((i j) 255)); } strip.show(); delay(20); // 在动画期间如果按下任意按钮则退出动画 if (readButton(TARGET_BUTTON_PIN) || readButton(DONE_BUTTON_PIN)) { break; } } }5.3 程序烧录与Bootloader如何把写好的程序刷进板子上的Atmega328PB有两个常见方法使用ISP编程器这是最直接的方法。将USBasp等ISP编程器的6根线VCC GND RESET MOSI MISO SCK连接到PCB上预留的ICSP焊盘。在Arduino IDE中选择编程器为“USBasp”然后点击“烧录引导程序”。这会同时完成两个动作一是给MCU设置正确的熔丝位如选择内部8MHz时钟二是写入Arduino Bootloader。之后就可以像普通Arduino一样通过串口需要接一个USB转TTL模块到MCU的TX/RX引脚上传程序了。预烧录Bootloader的芯片如果你有另一块Arduino板如Uno可以将其作为ISP编程器先给新的ATmega328PB芯片烧录好Bootloader和程序再焊接到PCB上。这样PCB板上甚至可以省去ICSP接口。我选择了第一种方法因为更灵活便于后续调试和更新程序。6. 3D打印柔性外壳与总装6.1 使用Solidworks设计表带式外壳硬件和软件都准备好了需要一个“家”来容纳它们并让我能戴在手上。设计原则是紧凑、轻便、佩戴舒适、易于装配。我使用Solidworks进行建模导入参考将PCB的STEP文件或精确尺寸图导入Solidworks作为设计参考。创建主体设计一个底部敞开的盒状主体内部空腔尺寸比PCB四周大0.2-0.3mm作为装配公差。厚度要能容纳PCB、电池以及按钮的行程。开孔在对应USB-C接口、两个按钮以及12颗LED的位置开出精确的孔。按钮孔需要比按钮柱直径稍大确保按压顺畅。LED孔要做成“聚光筒”状让光线更集中地透出避免侧面漏光。设计表带从主体两侧延伸出表带。采用常见的针扣式结构一端有多个调节孔另一端是扣针。表带的宽度、曲率要符合手腕的生理结构。添加固定结构在主体内部设计几个小的立柱柱子上有螺丝孔。对应的在PCB的四个角设计通孔。这样可以用短小的自攻螺丝将PCB固定在壳体内部防止晃动。分件考虑为了便于放入PCB和电池我将外壳设计为底盖主体两部分通过四周的卡扣或螺丝连接。底盖上预留电池仓的位置。设计心得3D打印件尤其是FDM打印存在一定的收缩和尺寸误差。在设计卡扣、螺丝柱等配合结构时必须留出足够的间隙通常0.2mm-0.4mm的配合间隙。对于按钮孔直径最好比按钮实际尺寸大0.5mm以上否则很容易卡住。6.2 选择打印材料与切片设置对于可穿戴设备柔性材料TPU/TPE是首选。它有一定的弹性佩戴舒适抗冲击也能更好地适应不同粗细的手腕。我选用的是95A硬度的TPU材料在柔韧性和支撑性之间取得了很好的平衡。在Cura等切片软件中打印柔性材料需要特殊设置打印速度要慢通常20-40mm/s。速度太快容易导致挤出不稳定或层间粘合差。回抽Retraction需要开启但回抽距离不宜过大1-2mm速度也要慢否则容易拉断柔软的耗材。构建板附着一定要使用** brim裙边** 而不是 skirt 或 raft。Brim能增加底部接触面积防止翘边且比raft更容易剥离对柔性材料友好。层高和壁厚层高0.2mm壁厚建议至少3条线宽约1.2mm以保证强度。填充20%-30%的网格填充即可既能减轻重量也能保证抗压性。打印完成后小心地移除支撑如果用了的话和裙边。由于是柔性材料可以用锋利的刀片或剪刀进行修剪。6.3 最终总装与测试最后一步将所有部件组装起来安装PCB将PCB对准外壳内部的定位柱用M2*6mm的自攻螺丝固定。确保USB口和按钮从对应的孔中露出。安装电池将锂电池放入底盖的电池仓内。可以用一小块双面胶固定电池防止其移动。连接与闭合将电池插头连接到PCB上。然后合上底盖用螺丝或卡扣固定。佩戴将尼龙表带或橡胶表带穿过外壳两侧的耳孔调整到合适的长度。上电测试 按下电源开关或插入USB设备应该启动WS2812B会执行一个初始化的彩虹灯效。然后你可以测试按“目标”按钮左边的蓝色LED应逐个点亮到第6个后循环回0。按“完成”按钮右边的绿色LED应逐个点亮。当右边绿灯数等于左边蓝灯数时触发彩虹庆祝动画。测试长按“完成”按钮是否能够清零计数器。7. 常见问题排查与优化建议在实际制作和测试中你可能会遇到以下问题这里提供我的排查思路和解决方案问题现象可能原因排查步骤与解决方案上电无任何反应1. 电池没电或接反。2. 电源路径有问题如MOS管损坏。3. MCU未正确供电或短路。1. 用万用表测量电池电压检查电池插头极性。2. 测量TP4056的输出电压BAT引脚应有~4.2V。测量MCU的VCC引脚电压应有~3.7V-4.2V。3. 检查PCB是否有短路特别是电源和地触摸MCU是否异常发热。按钮按下无反应1. 按钮焊接不良或损坏。2. 上拉电阻未正确连接。3. 程序引脚定义错误或消抖逻辑问题。1. 用万用表通断档测量按钮按下时两端是否导通。2. 测量按钮引脚在未按下时是否为高电平~VCC。3. 检查程序#define的引脚号是否与原理图一致。简化程序只做一个按钮测试灯。WS2812B不亮或乱闪1. 数据线DIN连接错误或虚焊。2. 电源电压不足低于3.5V。3. 时序问题特别是高速MCU下。1. 用示波器或逻辑分析仪查看D9引脚是否有数据信号输出。检查LED链顺序是否与程序设定一致。2. 测量LED的VCC引脚电压确保在3.5V以上。尝试外接5V电源测试。3. 在strip.begin()后添加一小段延时delay(10);。确保程序中未在strip.show()前使用delay()打断时序。USB无法充电1. USB-C接口焊接不良。2. TP4056外围电路错误如PROG引脚电阻。3. 电池保护板触发。1. 检查USB-C接口的CC引脚是否通过5.1k电阻下拉。2. 测量TP4056的VCC接USB 5V和BAT引脚电压。检查PROG引脚到地的电阻是否为1.2kΩ设定1A充电。3. 断开电池测量电池两端电压是否过低如低于3.0V过放可能导致保护板锁死。设备功耗过大待机时间短1. WS2812B在未显示时未彻底关闭。2. MCU未进入睡眠模式。3. 其他外围电路漏电。1. 在不需要显示时调用strip.clear(); strip.show();并将数据引脚设置为输入防止电流倒灌。2. 在循环中添加LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);等睡眠函数需LowPower库。3. 用万用表电流档串联测量整机静态电流应低于1mA。逐段排查。功能优化建议增加振动马达在完成一组或全部完成时不仅亮灯还通过一个小型振动马达如1020扁平马达提供触觉反馈在嘈杂的健身房尤其有用。增加蓝牙模块加入一个HC-05或更低功耗的BLE模块如HM-10可以将训练数据同步到手机App进行长期记录和分析。改用低功耗MCU如果对续航有极致要求可以考虑将Atmega328PB换成更擅长低功耗的MCU如ATtiny系列或STM32L0系列并配合深度睡眠模式。改进外观使用半透明或磨砂的柔性材料打印外壳让LED光线更柔和、有质感。或者设计一个更时尚、更像商业手环的外观。这个项目从电路设计到最终戴在手上涵盖了硬件产品开发的主要环节。它不仅仅是一个计数器更是一个如何将想法一步步实现为实物的完整案例。最大的成就感莫过于在健身房举起哑铃时瞥一眼手腕上自己创造的小设备清晰地知道自己的进度。希望这个详细的分享能给你带来启发和帮助祝你制作顺利
基于Atmega328PB与WS2812B的智能健身手环DIY全流程解析
1. 项目概述与设计初衷在健身房撸铁的时候你有没有过这样的经历一组动作做到力竭大脑一片空白完全记不清这是第几组了还得停下来掰着手指头数或者跟教练反复确认。这种打断不仅影响训练节奏也容易让好不容易积攒的泵感消散。作为一个电子工程师兼健身爱好者我决定自己动手解决这个小痛点——做一个能戴在手腕上、随时显示训练组数的智能手环。这个项目的核心目标很明确打造一个极度紧凑、可穿戴、操作直观的健身组数计数器。它不需要复杂的传感器来自动识别动作那样成本高且容易误判。我的思路是“半自动”由我手动设定一个动作的目标组数比如卧推做4组然后每完成一组就按一下按钮手环上的LED灯会实时显示已完成组数。当完成的灯数等于目标灯数时手环会用炫彩灯光给我一个明确的“任务完成”反馈然后我就可以清空计数器进行下一个动作。整个设备围绕Atmega328PB这颗微控制器和WS2812B可编程LED构建。选择它们的原因很简单Atmega328PB在保持与经典Arduino UNO核心ATmega328P高度兼容的同时体积更小、外设更丰富而WS2812B只需要一根数据线就能驱动成百上千颗LED极大地简化了电路布线和程序控制是实现紧凑型点阵显示的绝佳选择。从画电路板PCB到3D打印一个柔性的表带外壳我将带你走完一个完整硬件产品从概念到实物的全流程。无论你是想做一个实用的健身伴侣还是想学习如何将Arduino项目“产品化”这个案例都有很多值得挖掘的细节。2. 核心硬件选型与电路设计解析2.1 微控制器为什么是Atmega328PB在开源硬件领域ATmega328P几乎是Arduino Uno的代名词稳定、资源丰富、生态完善。但当我们追求“可穿戴”和“紧凑”时它的体积常见的DIP-28或TQFP-32封装就成了障碍。这时Atmega328PB进入了我的视野。Atmega328PB可以看作是328P的“升级紧凑版”。它最大的优势在于提供了更小的封装选项例如我这次采用的32-pin MLFMicro Lead Frame封装。这种封装没有向外延伸的引脚芯片底部是焊盘通过回流焊直接贴在PCB上能极大地节省空间。性能上它完全兼容328P的指令集和大部分外设意味着我们熟悉的Arduino核心库和编程方式可以无缝迁移。此外PB版本还额外增加了一个硬件串口共有两个UART和更多的定时器/PWM资源为未来功能扩展留有余地。注意MLF这类封装属于QFNQuad Flat No-leads的一种手工焊接有一定难度需要热风枪或返修台。对于新手如果追求可手工焊接可以选择TQFP封装薄型四方扁平封装的328PB它虽然比MLF大一点但仍有引脚露出用尖头烙铁可以操作。2.2 显示单元WS2812B LED的优势与驱动逻辑显示方案我放弃了传统的七段数码管或LCD屏因为它们通常需要更多的IO口和驱动电路。WS2812B也被Adafruit称为NeoPixel是一款集成了控制电路和RGB三色LED的智能外设。其革命性在于采用了单线归零码通信协议。单线控制意味着什么传统LED点阵要控制N个灯可能需要N1根线共阳或共阴。而WS2812B只需要三根线电源VCC、地GND和一根数据线DIN。第一个LED的数据线接MCU第二个LED的数据线接第一个LED的DOUT引脚如此串联下去。MCU只需要通过一根IO口按照特定的时序发送一串数据这串数据就会像流水一样经过第一个、第二个……直到最后一个LED每个LED会自动截取属于自己的24位RGB数据8位红8位绿8位蓝然后将剩余数据转发给下一个。这种“串联”结构让布线变得极其简单特别适合在狭长空间如手环排列。在这个项目中我使用了12颗WS2812B排列成两列每列6颗。左边一列LED 0-5代表“目标组数”右边一列LED 6-11代表“已完成组数”。通过程序我可以轻松地控制任意一颗LED显示任意颜色和亮度。例如目标设为4组就让左边的前4颗灯亮起蓝色每完成一组就让右边对应点亮一颗绿色灯全部完成后让所有灯跑一个彩虹流光效果作为庆祝。2.3 核心电路原理图设计要点电路设计是在Altium Designer中完成的。整个系统的供电心脏是一颗3.7V的锂聚合物电池。为了能方便地充电我加入了基于TP4056芯片的充电管理模块并通过一个USB-C接口接入5V电源。TP4056是一款非常经典的线性充电IC外围电路简单只需几个电阻电容能提供稳定的1A充电电流并带有充电状态指示红/蓝LED。主控电路围绕Atmega328PB展开。除了必要的电源滤波电容0.1uF的贴片电容要尽量靠近MCU的VCC引脚放置这是保证数字电路稳定工作的黄金法则我还为其设计了两种时钟源选项一是外部16MHz晶振二是内部8MHz RC振荡器。为了追求极致紧凑和节省两个晶振焊盘的空间我最终选择了内部振荡器。对于这个计数应用时间精度要求不高内部振荡器完全足够且更省电、更可靠无外部元件失效风险。输入部分是两个轻触开关分别用于“增加目标组数”和“增加已完成组数”。它们通过10kΩ的上拉电阻接到VCC常态下MCU检测到高电平按下时接地变为低电平。这里在开关两端并联了一个0.1uF的电容用于硬件消抖虽然软件消抖也必不可少但硬件上的预防能进一步提升可靠性。输出部分就是WS2812B灯链。需要注意的是WS2812B的工作电压典型值是5V而我们的系统电压是3.7V电池~4.2V满电。实测表明在3.5V以上电压时WS2812B依然可以正常工作只是亮度略有降低这对于手环显示是可接受的。为了确保信号电平匹配我将MCU的IO口输出5V TTL电平直接连接到了LED的数据输入脚。在3.3V系统下可能需要一个电平转换电路但本例中我们避免了这个问题。电源路径管理是一个小细节但很重要。我使用了一个MOS管如SI2301来实现USB供电和电池供电的自动切换。当插入USB时MOS管导通系统由USB的5V经降压后供电同时TP4056给电池充电当拔掉USB时MOS管关闭系统由电池供电。这防止了电池通过USB路径反向漏电。3. PCB布局设计与制造实战3.1 在Altium Designer中进行布局规划原理图完成后更考验功力的是PCB布局。对于可穿戴设备尺寸是硬约束。我将板子尺寸定为30mm x 30mm一个非常小巧的方形。布局的核心原则是“功能分区”和“信号流导向”电源区我将USB-C接口和TP4056充电电路放在板子的一端边缘这样USB口可以露在外面。TP4056的充电电流设置电阻Rprog和电池连接端子BAT BAT-都安排在这个区域附近走线短而粗以减少压降和发热。主控区Atmega328PB放在板子中央这是所有信号的枢纽。其周围的去耦电容必须紧贴对应的电源引脚尤其是VCC和AVCC。输入/输出区两个按钮开关放在板子另一侧边缘便于手指按压。WS2812B LED的排布是难点。我需要12颗LED排成两列。由于WS2812B是串联通信PCB走线必须严格按照“数据流”顺序MCU的D9引脚 - LED0的DIN - LED0的DOUT - LED1的DIN … - LED5的DOUT - LED6的DIN … - LED11的DOUT悬空。在狭小空间内要保证这12个LED的物理位置顺序与数据流顺序完全一致需要精心规划。我采用了两列背靠背的布局中间通过过孔连接数据线。电池连接器放在板子背面空闲区域选用小型的2-pin JST PH接头。布线要点电源线VCC GND优先加粗。我使用了20mil约0.5mm的线宽。地平面GND尽可能保持完整采用铺铜方式为数字信号提供稳定的回流路径。WS2812B的数据线DATA是关键的高速数字信号线虽然速率只有800kbps但时序要求严苛。我尽量让这条线走线短、直避免锐角并远离电源等可能产生噪声的线路。在数据线靠近MCU输出端串联一个100欧姆的电阻有助于抑制信号过冲和振铃。为调试留出接口虽然追求紧凑但我还是挤出了空间放置了一个6-pin的ICSP在线串行编程焊盘。这样我可以用烧录器直接给板子上的MCU刷写Bootloader和程序而不必依赖预烧录好的芯片。3.2 生成Gerber文件与下单打样PCB设计完成后需要将设计文件转换为制造商能理解的通用格式——Gerber文件。在Altium Designer中通过“文件”-“制造输出”-“Gerber Files”可以很方便地生成。通常需要生成以下层顶层铜Top Layer底层铜Bottom Layer顶层丝印Top Overlay顶层阻焊Top Solder Mask底层阻焊Bottom Solder Mask板子轮廓Keep-Out Layer或Mechanical Layer钻孔文件NC Drill Files将这些文件打包成ZIP就可以去PCB打样厂商下单了。我选择了JLCPCB因为其对小批量、低成本打样非常友好。在它们的网站上上传Gerber文件后会自动解析出板子预览。你需要确认几个关键参数板子尺寸30*30mm。板子层数2层。板子厚度常规1.6mm即可。铜厚1盎司约35μm。阻焊颜色我选了黑色看起来更酷。表面工艺有铅喷锡HASL成本最低但若追求更平整、更适合小间距贴片焊接可以选择沉金ENIG当然价格会高一些。同时我订购了钢网Stencil。钢网是一张带有镂空图案的不锈钢薄片图案对应PCB上的焊盘。在焊接贴片元件时将钢网对齐盖在PCB上刮上锡膏锡膏就会通过镂空处漏印到焊盘上之后放上元件用热风枪或回流焊炉加热即可完成焊接。对于有大量贴片元件的板子钢网是必备工具。实操心得第一次在JLCPCB下单时务必仔细检查它们系统生成的3D预览图我曾因为疏忽没发现丝印层一个元件的方向标反了导致焊接时搞错极性。虽然电气连接可能没错但影响美观和后期调试。现在养成了习惯下单前必看3D预览并核对关键元件的封装和方向。4. 焊接组装与生产技巧4.1 回流焊接使用热板进行小批量生产收到PCB和钢网后就进入激动人心的组装环节。对于MLF封装的MCU和0402规格的阻容元件手工烙铁焊接非常困难且容易损坏焊盘。我采用的方法是热板回流焊这是一种低成本、适合极客和小批量制作的方法。所需材料和工具焊锡膏我选用的是Chip Quik SMDLTLFP10T5这是一种低熔点138°C的锡膏对热板非常友好。刮刀用于将锡膏刮过钢网。热板一个普通的恒温加热板即可。镊子高精度防静电镊子用于拾放元件。放大镜或台灯便于观察微小元件。洗板水或异丙醇焊接后清洗板子。步骤固定与对位将PCB放在平稳台面上用胶带稍微固定。将钢网小心地盖在PCB上确保每个焊盘孔都精确对准。印刷锡膏取一小团锡膏放在钢网一端用刮刀以大约45度角均匀用力将锡膏刮过整个钢网。抬起钢网你会看到PCB每个焊盘上都留下了一个大小均匀的锡膏点。贴装元件借助放大镜和镊子按照从中间MCU到外围、从小元件到大元件的顺序将所有贴片元件放到对应的锡膏上。MLF封装的MCU对准是关键引脚大致对准焊盘即可锡膏熔化时的表面张力会将其自动“拉正”。回流焊接将贴好元件的PCB小心移到预热好的热板上。观察锡膏的变化先会变亮然后慢慢熔化变成光滑的液态最后冷却凝固。整个过程大约2-3分钟。看到所有焊点的锡都变得圆润光亮后用镊子轻轻将板子夹起放在耐热垫上冷却。清洗与检查冷却后用棉签蘸取洗板水或异丙醇轻轻擦拭焊点周围去除残留的助焊剂。然后在放大镜下仔细检查每个焊点看是否有虚焊、连锡、元件立碑等问题。避坑指南热板温度不均匀是常见问题。可能导致一边的锡熔化了另一边还没化。解决方法是将PCB放在热板中心区域并在加热过程中用镊子轻轻拨动板子边缘使其受热更均匀。另外锡膏量很重要太多容易连锡太少则焊接不牢。初次尝试可以先在废板上练习。4.2 通孔元件与后期装配回流焊完成后板上剩下的就是USB-C接口、按钮、电池插座等通孔元件了。这些可以用普通烙铁进行焊接。焊接USB-C接口这是一个难点因为引脚密集。使用尖头烙铁和细焊锡丝并配合助焊剂可以让你事半功倍。先固定两个对角的位置引脚再焊接其他引脚。焊接按钮和插座这些就相对简单了。注意按钮不要长时间加热以免塑料部分熔化。连接电池最后将锂聚合物电池的插头连接到PCB的电池插座上。务必注意正负极通常红色线是正极BAT黑色线是负极BAT-。接反可能会损坏充电芯片甚至电池。焊接全部完成后先不要急着装外壳进行下一步的软件烧录和功能测试。5. 固件开发Arduino程序逻辑详解5.1 开发环境搭建与库依赖编程使用我们熟悉的Arduino IDE。首先需要确保你的IDE支持Atmega328PB。由于328PB不是官方Arduino核心默认包含的型号你需要安装一个第三方核心。我使用的是MiniCore这是一个非常优秀的第三方硬件支持包。安装步骤打开Arduino IDE进入“文件”-“首选项”在“附加开发板管理器网址”中添加https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json打开“工具”-“开发板”-“开发板管理器”搜索“MiniCore”找到并安装。安装完成后在“工具”-“开发板”菜单下选择“MiniCore”然后选择“ATmega328PB”。进一步在“工具”菜单下选择正确的时钟频率内部8MHz、编程器USBasp或你使用的ISP编程器和端口。接下来安装WS2812B的驱动库。在库管理器中搜索“Adafruit NeoPixel”并安装。这个库封装了复杂的时序控制让我们可以用简单的API来控制LED。5.2 程序结构与核心逻辑剖析完整的程序代码我会在文末提供下载链接这里拆解几个关键部分。初始化与定义#include Adafruit_NeoPixel.h #define LED_PIN 9 // WS2812B数据线连接的引脚 #define NUM_LEDS 12 // LED总数 #define TARGET_BUTTON_PIN 3 // “目标组数”按钮 #define DONE_BUTTON_PIN 4 // “完成组数”按钮 Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB NEO_KHZ800); int targetSets 0; // 目标组数范围0-6 int doneSets 0; // 已完成组数范围0-6 bool exerciseComplete false; // 训练是否完成的标志这里定义了硬件连接和全局变量。strip对象是我们控制所有LED的接口。按钮检测与消抖 机械按钮在按下和弹起时会产生一段时间的抖动导致MCU误判为多次按下。我们需要在软件中消抖。bool readButton(int pin) { static int lastState HIGH; // 按钮上一次稳定状态 static unsigned long lastDebounceTime 0; int reading digitalRead(pin); if (reading ! lastState) { lastDebounceTime millis(); // 重置消抖计时器 } if ((millis() - lastDebounceTime) 50) { // 消抖时间50ms // 如果当前读取的状态与保存的稳定状态不同 if (reading ! buttonState) { buttonState reading; if (buttonState LOW) { // 按钮被按下低电平有效 return true; } } } lastState reading; return false; }这个函数在每次循环中被调用检查指定引脚的电平。只有当低电平状态稳定超过50毫秒才认为是一次有效的按键。主循环逻辑void loop() { // 1. 检查目标组数按钮 if (readButton(TARGET_BUTTON_PIN)) { targetSets (targetSets 1) % 7; // 循环增加0-6 updateDisplay(); exerciseComplete false; // 修改目标后重置完成状态 } // 2. 检查完成组数按钮 if (readButton(DONE_BUTTON_PIN) !exerciseComplete) { doneSets; if (doneSets 6) doneSets 6; // 限制最大值 updateDisplay(); // 3. 检查是否完成 if (doneSets targetSets targetSets 0) { exerciseComplete true; celebrateAnimation(); // 播放庆祝动画 } } // 4. 长按完成按钮重置可选功能 if (checkLongPress(DONE_BUTTON_PIN)) { targetSets 0; doneSets 0; exerciseComplete false; updateDisplay(); } }主循环清晰明了检测两个按钮更新计数刷新显示判断是否完成。updateDisplay()函数根据targetSets和doneSets的值控制左边6颗和右边6颗LED的亮灭与颜色。显示更新函数void updateDisplay() { strip.clear(); // 先关闭所有LED // 显示目标组数左边蓝色 for (int i 0; i targetSets; i) { strip.setPixelColor(i, strip.Color(0, 0, 150)); // 蓝色 } // 显示已完成组数右边绿色 for (int i 0; i doneSets; i) { strip.setPixelColor(i 6, strip.Color(0, 150, 0)); // 绿色 } // 如果已完成等于目标且不为零将已完成的灯变为黄色提示 if (doneSets targetSets targetSets 0) { for (int i 0; i doneSets; i) { strip.setPixelColor(i 6, strip.Color(150, 150, 0)); // 黄色 } } strip.show(); // 发送数据到LED }strip.show()是实际将颜色数据发送到LED链的命令在此之前的所有setPixelColor操作都只是在内存中准备数据。庆祝动画 当训练完成时调用一个简单的彩虹循环动画增加趣味性。void celebrateAnimation() { for (int j 0; j 256 * 5; j) { // 循环5次彩虹 for (int i 0; i strip.numPixels(); i) { strip.setPixelColor(i, Wheel((i j) 255)); } strip.show(); delay(20); // 在动画期间如果按下任意按钮则退出动画 if (readButton(TARGET_BUTTON_PIN) || readButton(DONE_BUTTON_PIN)) { break; } } }5.3 程序烧录与Bootloader如何把写好的程序刷进板子上的Atmega328PB有两个常见方法使用ISP编程器这是最直接的方法。将USBasp等ISP编程器的6根线VCC GND RESET MOSI MISO SCK连接到PCB上预留的ICSP焊盘。在Arduino IDE中选择编程器为“USBasp”然后点击“烧录引导程序”。这会同时完成两个动作一是给MCU设置正确的熔丝位如选择内部8MHz时钟二是写入Arduino Bootloader。之后就可以像普通Arduino一样通过串口需要接一个USB转TTL模块到MCU的TX/RX引脚上传程序了。预烧录Bootloader的芯片如果你有另一块Arduino板如Uno可以将其作为ISP编程器先给新的ATmega328PB芯片烧录好Bootloader和程序再焊接到PCB上。这样PCB板上甚至可以省去ICSP接口。我选择了第一种方法因为更灵活便于后续调试和更新程序。6. 3D打印柔性外壳与总装6.1 使用Solidworks设计表带式外壳硬件和软件都准备好了需要一个“家”来容纳它们并让我能戴在手上。设计原则是紧凑、轻便、佩戴舒适、易于装配。我使用Solidworks进行建模导入参考将PCB的STEP文件或精确尺寸图导入Solidworks作为设计参考。创建主体设计一个底部敞开的盒状主体内部空腔尺寸比PCB四周大0.2-0.3mm作为装配公差。厚度要能容纳PCB、电池以及按钮的行程。开孔在对应USB-C接口、两个按钮以及12颗LED的位置开出精确的孔。按钮孔需要比按钮柱直径稍大确保按压顺畅。LED孔要做成“聚光筒”状让光线更集中地透出避免侧面漏光。设计表带从主体两侧延伸出表带。采用常见的针扣式结构一端有多个调节孔另一端是扣针。表带的宽度、曲率要符合手腕的生理结构。添加固定结构在主体内部设计几个小的立柱柱子上有螺丝孔。对应的在PCB的四个角设计通孔。这样可以用短小的自攻螺丝将PCB固定在壳体内部防止晃动。分件考虑为了便于放入PCB和电池我将外壳设计为底盖主体两部分通过四周的卡扣或螺丝连接。底盖上预留电池仓的位置。设计心得3D打印件尤其是FDM打印存在一定的收缩和尺寸误差。在设计卡扣、螺丝柱等配合结构时必须留出足够的间隙通常0.2mm-0.4mm的配合间隙。对于按钮孔直径最好比按钮实际尺寸大0.5mm以上否则很容易卡住。6.2 选择打印材料与切片设置对于可穿戴设备柔性材料TPU/TPE是首选。它有一定的弹性佩戴舒适抗冲击也能更好地适应不同粗细的手腕。我选用的是95A硬度的TPU材料在柔韧性和支撑性之间取得了很好的平衡。在Cura等切片软件中打印柔性材料需要特殊设置打印速度要慢通常20-40mm/s。速度太快容易导致挤出不稳定或层间粘合差。回抽Retraction需要开启但回抽距离不宜过大1-2mm速度也要慢否则容易拉断柔软的耗材。构建板附着一定要使用** brim裙边** 而不是 skirt 或 raft。Brim能增加底部接触面积防止翘边且比raft更容易剥离对柔性材料友好。层高和壁厚层高0.2mm壁厚建议至少3条线宽约1.2mm以保证强度。填充20%-30%的网格填充即可既能减轻重量也能保证抗压性。打印完成后小心地移除支撑如果用了的话和裙边。由于是柔性材料可以用锋利的刀片或剪刀进行修剪。6.3 最终总装与测试最后一步将所有部件组装起来安装PCB将PCB对准外壳内部的定位柱用M2*6mm的自攻螺丝固定。确保USB口和按钮从对应的孔中露出。安装电池将锂电池放入底盖的电池仓内。可以用一小块双面胶固定电池防止其移动。连接与闭合将电池插头连接到PCB上。然后合上底盖用螺丝或卡扣固定。佩戴将尼龙表带或橡胶表带穿过外壳两侧的耳孔调整到合适的长度。上电测试 按下电源开关或插入USB设备应该启动WS2812B会执行一个初始化的彩虹灯效。然后你可以测试按“目标”按钮左边的蓝色LED应逐个点亮到第6个后循环回0。按“完成”按钮右边的绿色LED应逐个点亮。当右边绿灯数等于左边蓝灯数时触发彩虹庆祝动画。测试长按“完成”按钮是否能够清零计数器。7. 常见问题排查与优化建议在实际制作和测试中你可能会遇到以下问题这里提供我的排查思路和解决方案问题现象可能原因排查步骤与解决方案上电无任何反应1. 电池没电或接反。2. 电源路径有问题如MOS管损坏。3. MCU未正确供电或短路。1. 用万用表测量电池电压检查电池插头极性。2. 测量TP4056的输出电压BAT引脚应有~4.2V。测量MCU的VCC引脚电压应有~3.7V-4.2V。3. 检查PCB是否有短路特别是电源和地触摸MCU是否异常发热。按钮按下无反应1. 按钮焊接不良或损坏。2. 上拉电阻未正确连接。3. 程序引脚定义错误或消抖逻辑问题。1. 用万用表通断档测量按钮按下时两端是否导通。2. 测量按钮引脚在未按下时是否为高电平~VCC。3. 检查程序#define的引脚号是否与原理图一致。简化程序只做一个按钮测试灯。WS2812B不亮或乱闪1. 数据线DIN连接错误或虚焊。2. 电源电压不足低于3.5V。3. 时序问题特别是高速MCU下。1. 用示波器或逻辑分析仪查看D9引脚是否有数据信号输出。检查LED链顺序是否与程序设定一致。2. 测量LED的VCC引脚电压确保在3.5V以上。尝试外接5V电源测试。3. 在strip.begin()后添加一小段延时delay(10);。确保程序中未在strip.show()前使用delay()打断时序。USB无法充电1. USB-C接口焊接不良。2. TP4056外围电路错误如PROG引脚电阻。3. 电池保护板触发。1. 检查USB-C接口的CC引脚是否通过5.1k电阻下拉。2. 测量TP4056的VCC接USB 5V和BAT引脚电压。检查PROG引脚到地的电阻是否为1.2kΩ设定1A充电。3. 断开电池测量电池两端电压是否过低如低于3.0V过放可能导致保护板锁死。设备功耗过大待机时间短1. WS2812B在未显示时未彻底关闭。2. MCU未进入睡眠模式。3. 其他外围电路漏电。1. 在不需要显示时调用strip.clear(); strip.show();并将数据引脚设置为输入防止电流倒灌。2. 在循环中添加LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);等睡眠函数需LowPower库。3. 用万用表电流档串联测量整机静态电流应低于1mA。逐段排查。功能优化建议增加振动马达在完成一组或全部完成时不仅亮灯还通过一个小型振动马达如1020扁平马达提供触觉反馈在嘈杂的健身房尤其有用。增加蓝牙模块加入一个HC-05或更低功耗的BLE模块如HM-10可以将训练数据同步到手机App进行长期记录和分析。改用低功耗MCU如果对续航有极致要求可以考虑将Atmega328PB换成更擅长低功耗的MCU如ATtiny系列或STM32L0系列并配合深度睡眠模式。改进外观使用半透明或磨砂的柔性材料打印外壳让LED光线更柔和、有质感。或者设计一个更时尚、更像商业手环的外观。这个项目从电路设计到最终戴在手上涵盖了硬件产品开发的主要环节。它不仅仅是一个计数器更是一个如何将想法一步步实现为实物的完整案例。最大的成就感莫过于在健身房举起哑铃时瞥一眼手腕上自己创造的小设备清晰地知道自己的进度。希望这个详细的分享能给你带来启发和帮助祝你制作顺利