1. 项目概述:一个会呼吸的枕头
几年前,我为了给家里的小朋友做一个特别的睡前玩具,萌生了制作一个“会呼吸”的枕头的想法。它不能只是一个简单的夜灯,而应该是一个能与孩子互动的、有生命感的伙伴。按下按钮,灯光就像潮汐一样缓缓流动,从静谧的蓝色过渡到柔和的白色,再缓缓褪去,这个过程本身就充满了安抚的魔力。这个基于Arduino的LED流光枕头项目,正是这个想法的落地。
这个项目本质上是一个融合了基础电子电路、嵌入式编程和简单手工的DIY作品。它的核心是利用Arduino微控制器,通过编程产生PWM(脉冲宽度调制)信号,来控制多颗LED的亮度和颜色,从而模拟出“流光”的动态效果。一个按钮作为交互入口,让用户可以切换不同的灯光模式。对于初学者而言,这是一个绝佳的入门项目:硬件上,它涵盖了电源、微控制器、输入(按钮)、输出(LED)和限流电阻等最基础的电子模块;软件上,它涉及了数字输入读取、PWM输出、状态机逻辑和延时控制等嵌入式开发的核心概念。最终,我们将这些电子元件巧妙地藏进一个柔软的枕头里,让冷冰冰的技术变得温暖而触手可及。
无论你是对Arduino感兴趣的爱好者,想为孩子制作一个独特玩具的家长,还是寻找一个综合性实践课题的学生,这个项目都能带你完整地走一遍从电路设计、代码编写到产品集成的全过程。接下来,我将以Arduino Leonardo为例,拆解每一个步骤,并分享我在多次制作中积累的实操细节和避坑经验。
2. 核心硬件解析与物料清单
在动手之前,透彻理解每一件物料的作用,远比盲目连接更重要。这能确保电路工作的稳定性,并在出现问题时,你能快速定位根源。
2.1 主控板:为什么是Arduino Leonardo?
市面上常见的Arduino Uno和Leonardo在核心功能上相似,但我推荐Leonardo用于此项目,主要基于两点实战考量:
- USB通信芯片集成:Leonardo使用了ATmega32U4芯片,该芯片原生支持USB通信。这意味着它在电脑上会被识别为一个标准的键盘或鼠标设备(HID)。虽然本项目用不到这个特性,但其带来的一个隐形好处是,在烧录程序后,串口通信(Serial)的稳定性通常更好,减少了某些情况下串口监视器意外断连的几率。
- 引脚布局与PWM资源:Leonardo提供了7个PWM引脚(3, 5, 6, 9, 10, 11, 13),而Uno是6个。对于控制4-5个LED的简单流光效果,两者都绰绰有余。选择Leonardo更多是个人习惯和未来可扩展性的预留(例如未来想增加更多LED或舵机)。
注意:如果你手头只有Uno,完全没问题。只需在后续代码中,将LED连接的PWM引脚对应修改为Uno上可用的PWM引脚(3, 5, 6, 9, 10, 11)即可。核心逻辑完全通用。
2.2 发光单元:LED的选择与限流计算
LED是本项目的明星,选择不当会导致亮度不足、寿命缩短甚至烧毁。
- 颜色选择:原文使用了2白2蓝。白色LED通常色温较高,光线明亮;蓝色LED光线柔和,营造宁静氛围。这种搭配能形成鲜明的对比和过渡。你也可以尝试暖白+橙黄,营造日落效果。
- 规格参数:务必查看LED的数据手册或商品描述,找到两个关键参数:正向电压(Vf)和最大正向电流(If)。常见的5mm草帽LED,Vf约为2.0V-3.6V(白色和蓝色通常较高,约3.0V-3.4V),If一般为20mA。
限流电阻的计算是硬件部分最重要的环节。Arduino的IO引脚输出电压为5V,直接连接LED会导致电流过大。电阻的作用就是“限流”。
计算公式为:R = (Vcc - Vf) / If
Vcc:电源电压,Arduino引脚为5V。Vf:LED正向电压,假设我们取3.2V。If:期望的工作电流,为了安全和寿命,我们通常取额定最大电流的60%-80%,这里取15mA(0.015A)。
代入公式:R = (5 - 3.2) / 0.015 = 1.8 / 0.015 = 120Ω
计算结果是120Ω。那么为什么原文推荐使用220Ω的电阻呢?这里就体现了工程实践中的“安全余量”思想。
- 电压波动:USB供电的5V并非绝对稳定,可能存在微小波动。
- 参数离散性:不同批次甚至同一批次的LED,Vf值都有微小差异。
- 保护引脚:Arduino单个IO引脚的绝对最大电流是40mA,但推荐持续电流不超过20mA。使用稍大的电阻(220Ω),可以将电流限制在更安全的水平:
I = (5-3.2)/220 ≈ 8.2mA。这个电流足以让LED清晰可见(尤其在暗光环境下),同时极大降低了芯片过热的风险,也延长了LED寿命。因此,对于大多数标准LED,使用220Ω电阻是一个兼顾亮度、安全和通用性的稳妥选择。
2.3 交互与连接:按钮与电路搭建
- 按钮:使用最常见的4脚轻触开关。其内部结构是对角相通。我们使用上拉电阻接法:按钮一端接GND,另一端接Arduino的输入引脚,同时该引脚通过一个10kΩ电阻连接到5V(Arduino内部可软件启用上拉电阻,更简便)。
- 面包板与杜邦线:面包板是原型搭建的神器,方便测试和修改。务必使用质量可靠的杜邦线,劣质线材内部铜丝易断,会导致接触不良,这种故障最隐蔽也最让人头疼。
- 枕头:选择填充物饱满、面料有一定厚度但不透光的枕头。太薄会透出电路板轮廓,太厚则光线效果大打折扣。棉质或绒面材质是较好的选择。
物料清单(优化版):
- Arduino Leonardo 开发板 x1
- USB数据线(方口B型) x1
- 220Ω 碳膜电阻(1/4W) x4
- 5mm LED(白色) x2
- 5mm LED(蓝色) x2
- 830孔无焊面包板 x1
- 公对公杜邦线 若干
- 轻触开关(6x6mm四脚) x1
- 10kΩ 电阻(用于按钮上拉,可选) x1
- 柔软枕头(约30x30cm) x1
- (可选)热缩管、绝缘胶带,用于整理和保护线路。
3. 电路搭建详解与实测要点
电路是项目的骨架,稳定的连接是成功的一半。让我们一步步搭建并理解其中的原理。
3.1 核心电路连接图与步骤
虽然原文没有提供原理图,但根据描述,我们可以还原并优化出一个更可靠的连接方案。假设我们使用引脚3, 5, 6, 9分别控制4个LED。
连接步骤:
- 安置主控与电源:将Arduino Leonardo和面包板并排摆放。用一根杜邦线将Arduino的
5V引脚连接到面包板的红色正极排孔,另一根线将GND引脚连接到面包板的蓝色负极排孔。这样就在面包板上建立了全局的电源和地。 - 连接LED电路(以引脚3控制的白灯为例):
- 将白色LED的长脚(正极,阳极)插入面包板的一个独立行(例如第10行A列)。
- 将一颗220Ω电阻的一端插入与该LED正极同一行的另一列(例如第10行F列),电阻的另一端插入任意空行。
- 用一根杜邦线,从Arduino的数字引脚3连接到电阻所在的空行。这样,电流路径为:Pin3 -> 电阻 -> LED正极 -> LED负极 -> GND。
- 将LED的短脚(负极,阴极)用一根杜邦线直接连接到面包板的负极排孔(蓝色)。
- 重复此过程,将另一白灯接至引脚5,蓝灯接至引脚6和引脚9。确保每个LED都独立串联一个220Ω电阻。
- 连接按钮电路:
- 将轻触开关跨接在面包板的中缝上(例如横跨第20-21行)。
- 用一根杜邦线,将开关一端(例如第20行)连接到面包板的负极(GND)。
- 用另一根杜邦线,将开关的另一端(第21行)连接到Arduino的数字引脚2(或其他任意数字引脚,代码需对应修改)。
- 启用内部上拉电阻:在代码中,我们将引脚2的模式设置为
INPUT_PULLUP。这意味着芯片内部在引脚2和5V之间连接了一个约20kΩ-50kΩ的电阻。当按钮未按下时,引脚通过上拉电阻接到5V,读取为HIGH;当按钮按下时,引脚直接短路到GND,读取为LOW。这种方法省去了外接10kΩ物理电阻,更加简洁。
实测要点与避坑指南:
- 通电前目视检查:这是黄金法则。对照连接图,逐一检查是否有短路(如正负极导线直接碰在一起)、虚接(线没插到底)或错接(LED正负极反了)。
- 先分步测试,再整体集成:不要一次性接好所有线再通电。可以先只接一个LED电路,上传一个简单的闪烁程序测试该路是否正常。然后再接按钮,测试按钮读取是否正常。最后再整合所有功能。这种“分治”策略能极大简化故障排查。
- LED不亮怎么办?:
- 检查极性:LED正负极接反是新手最常见错误。长脚为正,短脚为负。面包板插反了肯定不会亮。
- 检查电阻:确认电阻是220Ω,并且两端接触良好。可以用万用表测量。
- 检查引脚定义:确认代码中控制的引脚号与实际连接的引脚号完全一致。
- 测量电压:用万用表直流电压档,黑表笔接GND,红表笔依次测量LED正极(连接电阻的那端)的电压。当程序设置该引脚为高电平(5V)时,此处应接近5V;设置为低电平(0V)时,此处应接近0V。如果电压变化正常而LED不亮,则问题在LED或其后线路。
- 按钮反应不灵或一直触发:
- 检查按钮是否可靠地连接在了GND和信号引脚之间。
- 确认代码中使用了
INPUT_PULLUP模式,并且判断逻辑是检测LOW(按下)。 - 按钮存在“抖动”。机械触点闭合瞬间会产生多次快速通断,程序可能误判为多次按下。这需要通过软件“消抖”解决,我们将在编程部分详细实现。
4. 编程逻辑深度解析与代码实现
硬件是身体,软件是灵魂。让灯光“流”起来的奥秘,全在代码之中。
4.1 核心概念:PWM与模拟输出
Arduino的数字引脚只能输出0V(LOW)或5V(HIGH)。要控制LED的亮度,我们需要模拟出中间电压。这就是PWM(Pulse Width Modulation,脉冲宽度调制)技术。
想象一下快速开关电灯。如果一秒钟内,开灯时间占0.5秒,关灯占0.5秒,你看到的是半亮的灯。如果开0.8秒,关0.2秒,灯就更亮。PWM就是以极高的频率(对于Arduino是490Hz或980Hz)进行这种开关,通过调整一个周期内高电平所占的比例(占空比,Duty Cycle)来模拟出不同的平均电压。
在Arduino代码中,我们使用analogWrite(pin, value)函数来输出PWM。其中value范围是0-255。0对应0%占空比(常闭),255对应100%占空比(常开),127则大约对应50%占空比,LED半亮。
4.2 状态机:管理灯光模式的核心思想
我们需要用按钮在几种流光模式间切换。最清晰的方法就是使用“状态机”编程模型。
状态机概念:将系统行为定义为一系列“状态”。在任何时刻,系统只处于其中一个状态。当发生某个“事件”(如按下按钮)时,系统会根据当前状态和发生的事件,决定执行什么“动作”,并迁移到下一个“状态”。
对于本项目:
- 状态:模式0(呼吸灯)、模式1(交替渐变)、模式2(追逐流光)、模式3(全亮夜灯)等。
- 事件:按钮被按下。
- 动作:改变LED的PWM值,实现对应的灯光效果。
- 迁移:按钮按下后,从当前模式切换到下一个模式。
使用状态机,代码结构会非常清晰,易于扩展新的模式。
4.3 完整代码实现与逐行解读
下面是一个融合了状态机、按钮消抖和多种流光模式的完整示例代码。我将在注释中详细解释关键部分。
/* * LED流光枕头控制器 * 引脚定义: * LED: 白1(Pin3), 白2(Pin5), 蓝1(Pin6), 蓝2(Pin9) * 按钮: Pin2 (内部上拉) */ // 1. 引脚常量定义 const int BUTTON_PIN = 2; const int LED_PINS[] = {3, 5, 6, 9}; // 4个LED引脚数组 const int LED_COUNT = 4; // 2. 全局变量定义 int ledMode = 0; // 当前灯光模式,0/1/2/3... int lastButtonState = HIGH; // 上一次读取的按钮状态(内部上拉,默认HIGH) int buttonPressCount = 0; // 用于简单消抖和模式切换的计数器 unsigned long lastDebounceTime = 0; // 上次消抖时间戳 const unsigned long DEBOUNCE_DELAY = 50; // 消抖延时(毫秒) void setup() { // 3. 初始化串口,用于调试(可选) Serial.begin(9600); Serial.println("LED Pillow Started."); // 4. 初始化LED引脚为输出模式 for (int i = 0; i < LED_COUNT; i++) { pinMode(LED_PINS[i], OUTPUT); analogWrite(LED_PINS[i], 0); // 初始化为熄灭 } // 5. 初始化按钮引脚为输入上拉模式 pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { // 6. 核心:读取按钮并处理模式切换 handleButton(); // 7. 根据当前模式执行对应的灯光效果 switch (ledMode) { case 0: modeBreathing(); break; case 1: modeAlternateFade(); break; case 2: modeChasingFlow(); break; case 3: modeNightLight(); break; default: ledMode = 0; // 防止模式值越界,归零 break; } } // 8. 按钮处理函数(含消抖) void handleButton() { int reading = digitalRead(BUTTON_PIN); // 读取当前按钮状态 // 消抖逻辑:如果读取状态发生变化,则重置消抖计时器 if (reading != lastButtonState) { lastDebounceTime = millis(); } // 如果状态变化后的稳定时间超过了消抖延时 if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) { // 确认按钮状态已稳定 // 如果当前是低电平(按下),且之前保存的状态是高电平(未按下) if (reading == LOW && lastButtonState == HIGH) { // 按钮被有效按下! ledMode++; // 切换到下一个模式 if (ledMode > 3) { // 假设我们有4种模式(0-3) ledMode = 0; // 循环回模式0 } Serial.print("Mode changed to: "); Serial.println(ledMode); // 模式切换时,可以快速闪烁一下所有LED作为视觉反馈 for (int i = 0; i < LED_COUNT; i++) { analogWrite(LED_PINS[i], 255); } delay(100); for (int i = 0; i < LED_COUNT; i++) { analogWrite(LED_PINS[i], 0); } delay(100); } } // 保存本次读取状态,用于下次比较 lastButtonState = reading; } // 9. 模式0:同步呼吸效果(所有LED同步明暗变化) void modeBreathing() { // 使用sin函数产生平滑的亮度波浪,值域[-1, 1] float breathValue = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0; // 将计算值映射到PWM范围0-255 int brightness = constrain(int(breathValue), 0, 255); // 应用到所有LED for (int i = 0; i < LED_COUNT; i++) { analogWrite(LED_PINS[i], brightness); } // 微小延时,控制循环速度,避免过快 delay(20); } // 10. 模式1:交替渐变(白蓝两组交替呼吸) void modeAlternateFade() { unsigned long currentTime = millis(); // 计算主相位,周期4秒 float phase = (currentTime % 4000) / 4000.0 * TWO_PI; // 白色LED组(索引0,1)亮度随sin(phase)变化 int whiteBrightness = (sin(phase) + 1) * 127.5; // 映射到0-255 // 蓝色LED组(索引2,3)亮度与白色相反,随cos(phase)变化 int blueBrightness = (cos(phase) + 1) * 127.5; // 应用亮度,确保值在有效范围内 whiteBrightness = constrain(whiteBrightness, 0, 255); blueBrightness = constrain(blueBrightness, 0, 255); analogWrite(LED_PINS[0], whiteBrightness); analogWrite(LED_PINS[1], whiteBrightness); analogWrite(LED_PINS[2], blueBrightness); analogWrite(LED_PINS[3], blueBrightness); delay(30); } // 11. 模式2:追逐流光(灯光像波浪一样依次点亮再熄灭) void modeChasingFlow() { int chaseSpeed = 100; // 追逐速度(毫秒),值越小越快 int trailLength = 100; // “拖尾”亮度衰减因子,值越大拖尾越长 // 遍历每个LED,计算其亮度 for (int i = 0; i < LED_COUNT; i++) { // 计算该LED在追逐波中的位置 unsigned long wavePosition = (millis() / chaseSpeed + i * (255 / LED_COUNT)) % 256; // 利用三角波函数模拟一个移动的光点及其衰减的拖尾 int brightness = 255 - abs(wavePosition - 128) * 2; // 应用衰减,使拖尾效果更自然 brightness = brightness - (i * trailLength / LED_COUNT); brightness = constrain(brightness, 0, 255); analogWrite(LED_PINS[i], brightness); } delay(50); } // 12. 模式3:全亮夜灯模式(所有LED以50%亮度常亮) void modeNightLight() { for (int i = 0; i < LED_COUNT; i++) { analogWrite(LED_PINS[i], 127); // 50%亮度 } // 此模式无需动态更新,但loop()仍在运行,需处理按钮事件 // 因此这里只设置亮度,不进行延时,让loop尽快循环回去检测按钮 }关键代码解读与实操心得:
- 数组的使用:
LED_PINS[]数组将4个引脚号组织在一起。这样在循环中可以用LED_PINS[i]来统一操作所有LED,代码简洁且易于修改。如果想增加LED,只需修改数组和LED_COUNT即可。 - 消抖的重要性:
handleButton()函数中的消抖逻辑是工业级可靠性的关键。millis()函数获取Arduino开机后的毫秒数,通过比较时间差来过滤掉按钮抖动产生的短时间脉冲。DEBOUNCE_DELAY设置为50ms是一个经验值,能过滤绝大多数机械抖动。 - 非阻塞延时:注意在
modeBreathing()等效果函数中,我们使用的是millis()进行时间计算,而不是delay()长延时。delay()会阻塞整个程序,导致按钮检测不灵敏。我们的写法保证了灯光动画流畅的同时,按钮响应依然实时。 - 数学函数创造效果:
sin(),cos(),exp()等数学函数是创造平滑动画效果的利器。modeBreathing()中的公式是一个经典的“呼吸灯”算法,能产生非常自然平滑的明暗变化。理解这些公式可能需要一些数学基础,但即使不理解,也可以将其视为一个“黑盒”效果发生器直接使用。 - 视觉反馈:在
handleButton()函数中,当模式切换时,我让所有LED快速闪烁一下。这是一个非常重要的用户体验设计。它给了操作者一个明确的“我已收到指令”的反馈,尤其是在枕头内部、看不到电路的情况下,这个反馈至关重要。
5. 系统集成、封装与优化
当电路和代码都在面包板上稳定运行后,我们就需要将其“产品化”,塞进枕头里,并考虑长期使用的可靠性。
5.1 从面包板到永久电路
面包板适合原型验证,但其内部的金属簧片长时间使用可能会松动,导致接触不良。对于要放进枕头里长期使用的项目,建议进行“半永久”或永久性连接。
- 焊接:最可靠的方法。你可以购买一块洞洞板(万能板),将Arduino、电阻、按钮插座焊接在上面,并用排针固定LED引线。焊接前务必再次测试所有功能。
- 焊接注意事项:
- LED、电阻等元件的引脚在焊接前最好先穿上热缩管,焊好后用热风枪或打火机(小心)加热收缩,起到绝缘和保护作用。
- 按钮最好使用带引脚的插座焊接,而不是直接焊按钮本身,方便日后更换。
- 为USB接口留出足够长的线,或者考虑在枕头侧面开一个隐蔽的缝隙让线伸出。
- 绝缘与固定:用扎带或胶带将电路板固定好,避免在枕头内晃动。所有裸露的焊点和导线连接处都必须用热缩管或绝缘胶带包裹严实,防止短路。
5.2 LED在枕头内的布局技巧
灯光效果的好坏,很大程度上取决于LED在枕头内部的布局。
- 均匀分布:不要将4个LED都挤在一起。可以将两个白色LED分别放置在枕头的左上和右下角,两个蓝色LED放在右上和左下角,形成交叉分布。
- 朝向:LED的发光角度通常有120度。为了让光线更均匀地透过面料散发出来,应将LED的发光面(通常是头部较圆的一面)朝向枕头中心或上方,而不是直接贴着面料。
- 固定与导光:可以用一小块白色半透明的塑料片或磨砂亚克力板盖在LED上方,作为简易的“导光板”,使光斑更柔和、更大。用不透明的胶带或布料将LED侧面包裹,防止光线从侧面泄漏,形成难看的光点。
- 测试:在缝合枕头前,接好所有线路,通电测试不同模式下的光线效果。在暗室环境下观察,调整LED的位置和朝向,直到获得满意的、均匀的流光效果。
5.3 电源与续航考量
本项目通过USB供电,通常连接电脑、充电宝或手机充电器。
- 电流估算:每个LED工作在约8mA,4个共32mA。Arduino Leonardo自身消耗约30-50mA。总电流约80mA。一个普通的5000mAh充电宝,理论上可以供电超过60小时,完全满足整夜甚至数天的使用需求。
- 低功耗优化(进阶):如果你希望用电池供电并追求极致的续航,可以考虑以下方法:
- 降低亮度:将PWM最大值从255降低到150或100,能显著减少电流。
- 使用睡眠模式:在灯光效果循环中,当处于稳定状态(如夜灯模式)时,可以让Arduino进入空闲睡眠模式,仅通过外部中断(按钮)唤醒。这需要更复杂的编程和硬件连接(将按钮连接到中断引脚)。
- 选择更高效的LED:使用高光效的贴片LED,在相同亮度下电流更小。
5.4 扩展思路与个性化定制
基础版本完成后,你可以尽情发挥创意:
- 增加LED数量:使用更多的PWM引脚,或者采用WS2812B等智能RGB LED灯带。只需一个数据引脚就能控制上百个灯珠,每个灯珠可独立编程显示1600万色,效果会非常炫酷。但需要学习对应的库(如FastLED)。
- 增加传感器:加入光敏电阻,实现环境光暗时自动开启夜灯模式;加入声音传感器,拍一下枕头就切换模式。
- 改变交互方式:将按钮换成触摸传感器、滑动变阻器(调节亮度)甚至蓝牙模块,用手机App控制。
- 丰富灯光模式:在代码中增加更多
mode函数,比如模拟星光闪烁、彩虹渐变、根据音乐节奏变化等。
6. 常见问题排查与维护心得
即使按照教程操作,也可能会遇到一些问题。这里汇总了我遇到过的典型情况及其解决方法。
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 所有LED都不亮 | 1. 电源未接通或USB线损坏。 2. Arduino未正确烧录程序或复位。 3. 公共地线(GND)未连接好。 | 1. 检查USB线连接,尝试更换线或USB口。观察Arduino板上的电源指示灯是否亮起。 2. 重新烧录最简单的Blink示例程序,测试板子是否正常。 3. 用万用表通断档,检查面包板负极排孔到每个LED负极、再到Arduino GND引脚是否连通。 |
| 部分LED不亮 | 1. 该路LED或电阻虚焊、损坏。 2. 该路连接导线断路。 3. 代码中该引脚未正确初始化或控制。 | 1. 将不亮的LED与正常亮的LED交换位置测试,判断是LED问题还是电路问题。 2. 检查该路电阻、杜邦线连接是否牢固。 3. 检查代码中 LED_PINS数组定义和pinMode初始化是否包含了该引脚。 |
| LED亮度异常(太暗或闪烁) | 1. 限流电阻值过大(太暗)或过小(有烧毁风险)。 2. PWM值设置过低。 3. 电源供电能力不足(如使用劣质充电宝)。 | 1. 确认使用的是220Ω电阻。测量电阻实际阻值。 2. 在 modeNightLight()中尝试将analogWrite值改为255测试最大亮度。3. 换用电脑USB口或品牌充电宝供电测试。 |
| 按钮无反应或反应混乱 | 1. 按钮引脚接触不良或接错。 2. 消抖逻辑参数不当或代码有误。 3. 引脚模式未设置为 INPUT_PULLUP。 | 1. 用万用表通断档检查按钮按下时两端是否导通。 2. 在 handleButton()函数开头添加Serial.println(reading);,观察串口监视器按钮按下时的读数是否稳定地从1变0。3. 确认 setup()中设置了pinMode(BUTTON_PIN, INPUT_PULLUP)。 |
| 灯光效果卡顿、不流畅 | 1. 代码中使用了delay()长延时,阻塞了其他操作。2. 循环中的计算过于复杂,导致单次循环时间过长。 | 1. 检查所有mode函数,确保动画效果是基于millis()计算的,避免使用长delay()。2. 简化效果计算。对于Leonardo,处理简单的PWM计算绰绰有余,此问题较少见。 |
| USB供电正常,但程序不运行 | 1. 开发板型号选择错误。 2. bootloader损坏(罕见)。 | 1. 在Arduino IDE的“工具”->“开发板”中,确认选择的是“Arduino Leonardo”。 2. 尝试通过ICSP给Leonardo重新烧录bootloader(需要额外编程器)。 |
维护心得:
- 定期检查:作为儿童玩具,建议每隔一段时间检查一下枕头内部的线路,是否有导线被弯折过度、焊点松动的情况。
- 清洗须知:绝对不可以将整个枕头放入水中清洗!如果需要清洗枕套,必须将内部的电子部件整体取出。最好的设计是将电路部分封装在一个可拆卸的小布袋里,缝在枕头一角,方便分离。
- 安全第一:尽管是5V低压电路,相对安全,但仍要确保所有绝缘措施到位,避免儿童拆解导致小零件误吞。使用过程中如有异常发热,应立即断电检查。