让 LED 闪烁无疑是任何新兴电子专家要解决的首批问题之一,无论是使用古老的 NE555 还是最近的微控制器来控制 LED。事实证明,我们可以通过改变约束条件将任何微不足道的问题变成更困难的问题。
那么,让 LED 尽可能长时间地闪烁的挑战又如何呢?当然,这也不是一个新的问题。我过去遇到过两种有趣的方法:1) Burkhard Kainkas Ewiger Blinker(“永恒的闪烁”)和 2) Ted Yapos TritiLED。
B. Kainkas 项目是一个由分立晶体管制成的 LED 闪光器电路,消耗约 50µA 电流,可使用一节 AA 电池运行数年。Ted Yapo 将标准提高了一点,并详细研究了如何让 LED 在非常低的强度下使用 CR2032 纽扣电池发光数年。他的项目日志绝对值得一读。一个非常有趣的细节是,他得出结论,使用低功耗微控制器来控制 LED 实际上是最有效的选择。这可能有点违反直觉,但在查看他构建离散版本的尝试时,这一点似乎更加明显。
许多微控制器提供高度优化的低功耗睡眠模式,可用于在闪烁之间等待。微控制器仅在 LED 需要闪烁时才会激活。此时,微控制器的有效功耗是多少并不重要,因为 LED 需要几毫安的电流才能发出足够水平的光。
进入臭名昭著的“3 美分” Padauk 微控制器系列,我之前在几个项目中使用过它。令我惊讶的是,这些设备提供了非常有竞争力的低功耗睡眠模式,似乎与价格高出十倍的几个“低功耗” 8 位微控制器不相上下。我研究了如何在 PFS154 上实现超低功耗 LED 闪光灯。
实施
降低 MCU 功耗的第一步是使用低速振荡器作为时钟源。在 PFS154 中,这被称为“ILRC”,根据电源电压提供大约 52 kHz 的时钟。我发现一个奇怪的现象是,第一步必须同时激活高速和低速振荡器,第二步只禁用高速振荡器。直接切换到 ILRC 会暂停 MCU。下面的代码示例基于 free-pdk 包含的内容。
/* Activate low frequency oscillator as main clock. */
CLKMD = CLKMD_ILRC | CLKMD_ENABLE_ILRC | CLKMD_ENABLE_IHRC;
CLKMD = CLKMD_ILRC | CLKMD_ENABLE_ILRC ;
// Note: it is important to turn off IHRC only after clock
// settings have been updated. Otherwise the CPU stalls.
以如此低的时钟频率运行 PFS154 已经可以将功耗降低到远低于 100 µA。并非所有这些都是随时钟频率变化的动态功耗,因此唯一能进一步降低功耗的方法是激活其中一种睡眠模式。
睡眠模式
PFS154 支持两种睡眠模式:“STOPSYS”和“STOPEXE”。
STOPSYS 完全停止内核和所有振荡器。从此状态唤醒的唯一方法是通过引脚更改。
STOPEXE 停止内核,但低频振荡器保持活动状态,可用于为定时器计时。内核可以通过引脚更改或定时器事件唤醒。看起来,尽管数据表中没有明确说明,但 8 位定时器和 16 位定时器都可以生成唤醒事件。请注意,看门狗定时器在 STOPEXE 期间也会停止。这与其他微控制器上的行为形成对比。
第一步,我使用万用表验证了睡眠模式下的电流消耗与电源电压的关系,如上所示。我基本上能够重现数据表中的曲线,这证实了数据表是正确的,而且我的手持式万用表实际上能够准确测量低至几百纳安的电流!老实说,这不是我所期望的。
在此期间,我发现了 PFS154 的一个奇怪行为。重置后,引脚更改唤醒始终默认启用。看来引脚上的非常小的变化可以产生唤醒。如果它们悬空,只需触摸引脚即可唤醒核心。有趣的是,这甚至适用于未布线到封装外部的引脚,这些引脚仍作为芯片上的焊盘存在。通过触摸 IC 的表面,可以生成唤醒事件!因此,除非您有兴趣构建一个 hacky 触摸传感器,否则建议禁用所有引脚作为唤醒源。
定时器唤醒的实现
因为我想构建一个 LED 闪光器,所以我使用 Timer2 以大约 1.6Hz 的频率生成唤醒事件。您可以在下面看到 STOPEXE 配置和定时器初始化的完整代码。
/* Configure STOPEXE mode and set up Timer 2 as wake up source */
PADIER = 0;
// disable pins as wakeup source
PBDIER = 0;
// Also port B needs to be disabled even if it is
// not connected to the outside of the package.
// Touching the package can introduce glitches and wake
// up the device
INTEN = 0;
// Make sure all interrupts are disabled
INTRQ = 0;
MISC = MISC_FAST_WAKEUP_ENABLE;
// Enable faster wakeup (45 clocks instead of 3000)
// This is important to not waste energy, as 40µA bias
// is already added during wakeup time
TM2C = TM2C_CLK_ILRC | TM2C_MODE_PWM;
// Oscilator source for timer 2 is LRC (53 kHZ)
TM2CT = 0;
TM2S = TM2S_PRESCALE_DIV16 | TM2S_SCALE_DIV8;
// Divide clock by 16*7=112 -> 53 kHz / 122 = 414 Hz
TM2B = 1;
// PWM threshold set to 1.
// The PWM event will trigger the wakeup.
// Wakeup occurs with 414 Hz / 256 = 1.66 Hz
一个重要的优化是打开“快速唤醒模式”。正常唤醒模式需要大约 3000 个时钟周期,在此期间消耗大约 40µA 的电流。我发现 8 位定时器在 STOPEXE 模式下也可以用作 PWM 发生器。但是无法阻止它们唤醒 CPU,因此它们不能自主使用。
LED 闪烁代码
剩下的唯一部分是实际闪烁 LED 的代码。这相当简单,如下所示。
/* Initialize LED I/O and flash the LED */
PA = 1<<4; // LED is on PA4, set all other output to zero.
PAPH = 0; // Disable all pull up resistors
PAC = 0; // Disable all outputs
// Note: There is no series resistor for the LED
// The LED current is limited LOW IO driving setting
// See Setction 4.14 (p24) in PFS154 manual
// The output is disabled when the LED is off
// to avoid leakage
for (;;) {
PAC |=1<<4;
// Enable LED output (It's set to High)
__nop();
__nop();
__nop();
PAC &=~(1<<4);
// Disable LED output after 4 cycles => 4/53 kHz = 75.5 µS
__stopexe();
}
处理器核心将在定时器 2 生成的每个事件后唤醒,打开 LED 75.5µS,然后再次让核心进入休眠状态。LED 直接连接到没有串联电阻的输出引脚,同时引脚配置为低 I/O 驱动强度以限制最大电流。这有点冒险,但允许将 LED 降至最低电压 - 对于我使用的绿色 LED,大约为 2.1V。
电流消耗性能
好吧,代码运行良好,在电压降至略高于 2V 时以 1.6 Hz 的频率闪烁 LED。您可以在此处找到完整的源代码。
为了评估一切是否正常工作,我建立了一个简单的电源模型,该模型考虑了睡眠模式电流、有功电流和 LED 使用的电流。通过测量连接到微控制器的 LED 在不同电源电压下的导通电流并将其乘以占空比来确定 LED 电流。对 MCU 的有功电流也采取了相同的方法。您可以在上面看到模型的输出并与测量值进行比较。我必须使用几千欧姆的串联电阻和并联电容器来确保电流纹波足够平滑,以便在万用表上获得稳定的读数。
如您所见,模型和测量值之间有很好的一致性。由于 LED 的占空比极低,主要功耗仍然是 MCU 和定时器。这一贡献高度依赖于电源电压,因此在最低电压下实现最节能的操作。
3V 时的总电流消耗仅为 1 µA 左右!这小于许多电池的自放电电流。一块容量约为 200 mAh 的 CR2023 电池理论上可以为该闪光灯供电 200000 小时,即 22 年!基于充电至 5V 的 330µF 电容器的电量,我能够操作电路(如标题图所示)超过 10 分钟。
摘要
尽管成本低廉,但 Padauk MCU 可用于极低功耗操作。当然,还有更多方法可以进一步改进闪光灯电路,例如使用电感升压转换器,以允许 LED 在更低的电压下进行恒流操作。