在线工博会

低功耗LED照明应用的电源管理技术
Microchip模拟和接口产品部 Ezana Haile
为节省流量,手机版未显示文章中的图片,请点击此处浏览网页版
当控制一组 LED 来实现照明应用时,LED 亮度与电功率的关系是决定可见光质量的关键技术指标。在低功耗应用中,由于电流源有限,同时点亮整套 LED 以达到最大亮度可能无法实现。为了在使用低功率电源时获得最佳亮度,必须有效管理每个LED 的功耗。这需要一种电源管理技术,实现在给定时间内只为一套 LED 中的一组供电。还要对该时间间隔进行管理,以实现所需的发光强度,而在视觉上不会发现各组 LED 是交替点亮的。
要确定给定时间间隔内点亮的 LED 数量,必须确定应用的可用功率和发光强度。必须仔细查看 LED 数据手册中发光强度与正向电流特性的关系,以选择满足所需亮度级别的 LED。确定了应用为达到所需亮度级别而需要的 LED 数量后,可通过如下方式计算 LED 所需的总电流与可用电流的比值,来确定在给定时间间隔内可供电的LED 数量:
一组 LED 的数量 = LED 所需的总电流/可用的电源总电流
此外,必须调整点亮/熄灭一组 LED 的频率。点亮时间应足以使一组 LED 全部点亮,熄灭时间受限于该组 LED 在开始明显变暗前耗费的时间。熄灭时间限制了当一组 LED 处于熄灭状态时,应用中可以控制的其他 LED 组的数量。因此,熄灭时间限制了可通过时间间隔管理的 LED 组的数量。
这种技术的低成本实现需要一个时钟源、用于控制若干组 LED 的数字单稳态触发器,以及可通过简单的 On/Off 开关来检测启动条件的或门。图 1 给出了用于控制4 组 LED 的 D 单稳态触发器配置框图。

(图片)

(图片)

图 1:使用单稳态触发器电路控制 LED 点亮时间间隔

单稳态触发器最初处于无变化状态,需要一个启动脉冲。启动脉冲的持续时间必须至少为一个时钟周期,以便第一个触发器能够在时钟的上升沿检测到该脉冲。此外,启动信号必须为瞬时信号。它不能超过一个时钟周期,否则前两个触发器输出将同时置 1;而且由于源电流有限,照明应用将无法正常工作。因此,采用这种配置,在每个时钟的上升沿可确保一组 LED 完全点亮。但在人眼看来,就像所有 LED同时完全点亮一样。
这种实现的局限性在于它是单调的,设计缺乏灵活性。它仅有一个点亮或熄灭状态。对于某些应用(如 LCD 背光),该电路可能够用。但是,如果需要调光或产生模式,则基于单片机(MCU)的电路可提供最大的灵活性,且对解决方案的总成本影响最小。而且该电路更易于构建,元件更少。MCU 控制每组 LED,同时可检测用户输入以进行调光控制和模式选择。
以一个经济高效的实现为例,它采用低成本和低引脚数 8 位单片机(如 Microchip的 PIC10F 或 PIC12F 系列)以及 I/O 端口扩展器(如 Microchip 的 MCP23018)。当发光电路与 MCU 距离较远时,I/O 端口扩展器也可用于驱动 LED。
I/O 端口扩展器是用于扩展单片机 I/O 端口的器件。在此应用中,MCU 通过 I2C™协议控制 I/O 扩展器端口,以驱动 LED 点亮或熄灭。可以使用 MCU 的 I/O 引脚检测按钮开关的用户输入,或使用内置模数转换器检测电位器电平来实现调光控制。
I/O扩展器提供漏极开路或推挽式输出配置。如今的单片机工作在3.3V或更低的电压,漏极开路输出I/O扩展器非常适合此应用。使用漏极开路输出I/O扩展器的优势是,它允许LED工作在5V或更高电压,而单片机和I/O扩展器以较低电压供电。MCP23018是一款16位I/O端口扩展器,带有一个漏极开路输出和一个I2C接口。图2给出了将电压上拉至高于MCU电源电压的漏极开路输出I/O扩展器的电路图。

(图片)

图2:使用I/O端口扩展器的低成本、基于单片机的照明解决方案

在本例中,当I/O端口设置为低电平时,I/O扩展器端口的电压为0V,电流正向偏置并点亮LED。LED偏置电阻也可用作漏极开路输出的上拉电阻,限制LED电流以实现所需的发光强度。
当I/O扩展器输出端口设置为高电平时,漏极开路输出关闭或处于高阻态,I/O扩展器端口的电压被上拉电阻上拉至5V。这时LED处于熄灭状态,因为电流不会流入。漏极开路输出配置的另一个优势是,当端口配置为高阻抗时,由于存在寄生电容,熄灭LED耗时更长。这使得点亮下一组LED的时间稍长于使用推挽式输出的类似应用。
MCP23018的16个I/O端口最多可以驱动16个LED。I/O扩展器的输出驱动能力还限制了LED完全点亮时可流入I/O端口的电流量。I/O端口的低电平电压规定为最大0.6V,电流为8.5 mA。如果电流高于8.5 mA,低电平电压将成指数级增大,绝对最大电流规定为25 mA。
例如,如果电源电流限制为5V/50 mA,而用于检测用户输入的单片机、I/O扩展器和电阻的电流预算为大约2 mA,则其余的可用电流可专用于LED照明。如果在电流在10 mA左右时LED的发光强度已足够,则每组可控制4个LED。限流电阻阻值约为440・。
图 1 所示的时序可使用相对较短的 MCU 指令代码重现。例如,参考伪代码 1,main子程序可以是一个无限 while 循环。在 MCU 定时器间隔(Timer0),中断服务程序向 I/O 扩展器发送一个 I2C 命令,以仅点亮一组 LED。中断服务程序进行计数或跟踪 LED 组的状态,例如当前点亮的组,以及相应的 I/O 扩展器端口配置为高电平还是低电平。初始状态或 MCU 复位后,在第一个 Timer0 中断,第 1 组点亮。在第二个中断,第 1 组熄灭,第 2 组点亮。然后,在第三个中断,第 2 组熄灭,第 3 组点亮。最后,在第四个中断,第 3 组熄灭,第 4 组点亮,组计数器变量清零。在下一个中断,重复从第 1 组点亮到第 4 组熄灭的循环。 Command_byte 、Address_pointer_bank1n2 和 Address_pointer_bank3n4 等其他变量是在头文件中定义的常量。利用这种实现,电路可输出所需的发光强度,并且看上去所有 LED 使用可用电源同时点亮。
伪代码 1:单片机中断服务程序代码流
void main (Void){
initialize(); //初始化 PIC MCU 中的外设,包括 Timer0 和 I/O 扩展器外设
bank_counter = 0; //组计数器变量清零
while(1){} //无限 while 循环
}
Void Interrupt int_service(void){
TurnOffAll_LEDs(); //用于熄灭之前点亮的所有 LED 的子程序
I2C_start(); //I2C 协议——启动信号子程序
I2C_send(Comand_byte); //I2C 协议——发送字节子程序
If(bank_counter == bank1){ // bank1 为常量,定义为 0
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
I2C_send(‘0000 1111’); //I2C 协议——发送组状态(第 1 组点亮,第2 组熄灭)
bank_counter = bank_counter + 1;
}
If(bank_counter == bank2){ // bank2 为常量,定义为 1
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
I2C_send(‘1111 0000’); //I2C 协议——发送组状态(第 2 组点亮,第1 组熄灭)
bank_counter = bank_counter + 1;
}
If(bank_counter == bank3){ // bank3 为常量,定义为 2
I2C_send(Address_pionter_bank3n4); //发送外设寄存器地址指针
I2C_send(‘0000 1111’); //I2C 协议——发送组状态(第 3 组点亮,第4 组熄灭)
bank_counter = bank_counter + 1;
}
If(bank_counter == bank4){ // bank4 为常量,定义为 3
I2C_send(Address_pionter_bank3n4); //发送外设寄存器地址指针
I2C_send(‘1111 0000’); //I2C 协议——发送组状态(第 4 组点亮,第3 组熄灭)
bank_counter = 0;
}
I2C_stop(); //I2C 协议——停止信号子程序
}
LED 模式生成和调光控制
在基于单片机的应用中,可轻松生成有趣的发光模式。I/O 端口扩展器的输出状态从 RAM 变量中标记为 Bank1n2_pattern 和 Bank3n4_pattern 的 2 个字节中加载。每个字节的半字节对应一个组。预定义的查找表包含每个组要产生各个模式应点亮和熄灭的 LED。
在 MCU 代码(main 子程序的无限 while 循环)中添加 IF THEN 语句,以持续监视按钮开关的开/关状态。当短暂按下按钮时,查找表中的一个模式将加载到 RAM 中标记为 Bank1n2_pattern 和 Bank3n4_pattern 的两个字节中。当发生 Timer0 中断时,新模式发送到 I/O 扩展器,LED 按照该模式点亮。用户连续短暂按下按钮开关时,main 子程序将循环遍历查找表。要显示交替光线,只需发送前一个模式的补码。例如,如果第 1 组的模式为‘0101’,则补码为‘1010’,如伪代码 2 所示(伪代码 2 是伪代码 1 中的一段)。
伪代码 2:模式生成
*
*
*
If(bank_counter == bank1){ // bank1 为常量,定义为 0
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
Bank1n2_pattern = ~Bank1n2_pattern; //用“~”取变量的补码
I2C_send((Bank1n2_pattern | ‘0000 1111’)); //I2C 协议——发送组状态
//(使用或“|”将第 1 组点亮,第 2 组熄灭)
bank_counter = bank_counter + 1;
}
*
*
*
但是,必须添加延时,视觉能感受到模式的交替。延时添加在中断子程序中,在组点亮/熄灭的 IF THEN 语句之前。为此,需添加 Delay_ON 标志,以便在接下来的中断中,只有延时计数器递减以倒计数延时的中断数目。延时值也可以是用户使用电位器选择的值,电位器的中间抽头连接到 MCU 的片上模数转换器(ADC)的输入。最小到最大延时均可换算成 ADC 的数字数据,只需检测前四位(提供 16 个级别)。检测前五位(或 32 个级别)可设置更精细的比例。延时最大时,LED 闪烁最慢,延时最小时,看上去所有 LED 均完全点亮。图 3 中的时序图显示了延时长度tDELAY。
伪代码 3:用于查看发光模式的延时代码实现
*
*
*
Void Interrupt int_service(void){
TurnOffAll_LEDs(); //用于熄灭之前点亮的所有 LED 的子程序
If (Delay_ON == ON){ // ON 为常量,定义为 1
Update_Timer0_Counter(Timer0delay_interval); //用 于更新Timer0 的子程序
// Timer0delay_interval 为常量,用于设置最小延时
Delay_Counter = Delay_Counter – 1; //倒计数延时的中断数目
If(Delay_Counter == 0){
Delay_ON = OFF; //清除下一个中断的延时标志
Delay_Counter = Get_Delay_Counter(); //用于检测用户输入
//并设置延时计数器变量的子程序
}else{
Delay_ON = ON; //将延时标志保留为 ON
Return; //退出中断服务程序
}
}
I2C_start(); //I2C 协议——启动信号子程序
I2C_send(Comand_byte); //I2C 协议——发送字节子程序
If(bank_counter == bank1){ // bank1 为常量,定义为 0
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
Bank1n2_pattern = ~Bank1n2_pattern; //用“~”取变量的补码
I2C_send((Bank1n2_pattern | ‘0000 1111’)); //I2C 协议——发送组状态
//(使用或“|”将第 1 组点亮,第 2 组熄灭)
bank_counter = bank_counter + 1;
Delay_ON = ON; //开启延时标志
}
*
*
*
调光控制使用脉宽调制(PWM)来控制每个组的时间间隔持续时间。在本例中,Timer0 中断持续时间有两个值,一个表示高电平持续时间,一个表示低电平持续时间,与 PWM 百分比成正比。比率通过拨轮电位器设置,电位器的中间抽头连接到ADC 输入。通过选择 ADC 输出的前 4 位或前 5 位可调整分辨率级别。Timer0 计数器位置可按照换算后的 ADC 数据按比例调整,其中 100% PWM 等于最大计数器位置(完全点亮),0%等于最小或最暗级别。伪代码 4 显示了 16 个级别的 PWM 换算公式,图 3 显示了 PWM 持续时间 tPWM_LOW和 tPWM_HIGH的时序图。
伪代码 4:用于计算 PWM 比的子程序
Void get_PWM_ratio(void) {
Double PotScale; //局部变量,用于存储 ADC 输出范围
Double PWM_Percentage; //局部变量,用于存储 PWM 变化百分比
PotScale = (ADRESH)/16 + 1; //换算 ADC 输出高字节
PWM_Percentage = 1/16 * PotScale; //换算从 0 到1(相当于 100%)的输出
PWM_High = Frequency_counter * PWM_Percentage; // 设 置 PWM 高
Timer0 值 PWM_Low = Frequency_counter * (1 – PWM_Percentage);
//设置 PWM 低 Timer0 值
//PWM_High 和 PWM_Low 是全局变量,
//Frequency_counter 是恒定的 Timer0 值,用于设置频率。
}

(图片)

图 3:PWM 输出和延时的时序图

在本例中,中断服务程序必须为下一个中断更新 Timer0 计数器位置。还必须检测持续时间是 PWM 高时间还是低时间。因此,除了检测 LED 组状态,必须添加几条指令来检测用于调光控制的电位器电平,并且如伪代码 4 所示根据 PWM_High 和PWM_low 值按比例调整 Timer0 计数器位置。伪代码 5 显示了用于调整 PWM 的代码,IF THEN 语句用于检测 PWM 状态。
伪代码 5:PWM 比例设置的代码流
*
*
*
If(bank_counter == bank1){ // bank1 为常量,定义为 0
If (PWM_High_Low_flag == OFF){ //检查 PWM 状态标志
get_PWM_ratio(); //检测用户输入,获得 PWM 比例
Timer0_counter = 65535 – PWM_High; //设置 Timer0 计数器变量
Update_Timer0_Counter(Timer0_counter); //用于更新 Timer0 的子程序
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
Bank1n2_pattern = ~Bank1n2_pattern; //用“~”取变量的补码
I2C_send((Bank1n2_pattern | ‘0000 1111’)); //I2C 协议——
发送组状态
//(使用或“|”将第 1 组点亮,第 2 组
熄灭)
PWM_High_Low_flag = ON; //设置标志
Delay_ON = OFF;
}else{
Timer0_counter = 65535 – PWM_Low; //设置 Timer0 计数器变量
Update_Timer0_Counter(Timer0_counter); //用 于更 新Timer0 的子程序
I2C_send(Address_pionter_bank1n2); //发送外设寄存器地址指针
I2C_send(‘1111 1111’)); //I2C 协议——熄灭所有 LED
bank_counter = bank_counter + 1;
PWM_High_Low_flag = OFF; //清除标志
Delay_ON = ON;
}
}
*
*
*
此方法也可以在具有额外程序存储器的中档 8 位单片机(如 Microchip 的 PIC16F系列)上实现。这种升级使 main 子程序能够处理复杂的发光模式,如追光。该MCU 的 Timer1 模块可用来改变针对追光模式更新 2 个 RAM 字节的持续时间。
总之,尽管有多种方法可有效驱动 LCD 背光或发光模式应用中的各组 LCD,但设计人员一直在寻找新方法以在不影响性能的情况下消减成本。在低功耗应用中,可通过管理每组 LED 点亮的时间间隔来控制 LED,从而实现高效照明。此外,低引脚数单片机和 I/O 端口扩展器提供了低成本且具有高度设计灵活性的替代照明解决方案。 12/9/2013


电脑版 客户端 关于我们
佳工机电网 - 机电行业首选网站