记一次有趣的LED闪屏消除及模拟PWM降低尖峰电流

 

        我们的体温计项目中,显示屏上边有背光可以点亮。硬件的同事在设计的时候,最开始是直接将led接到了回路上。当电压变化的时候,会导致led的亮度跟随变化。我们的产品上使用的电池是1620,驱动能力不足,当时用saadc采集温度或者广播、扫描等操作的时候,都会产生较大的电流,使电路上出现无法忽视的压降,于是led也不停的闪烁~

        出于成本上的考虑,硬件最初不同意做任何改变,然后只能软件上想办法解决。

        因为要做预测算法,所以产品采样的频率特别高,每秒钟会进行10次采样,每次采样都会出现较大的压降,也就是说,采样会导致LED屏幕疯狂闪烁!但是屏幕每次都会持续亮好几秒,不可能在亮屏的时候中断采样,看起来是一个无解的问题。

        这里我们有一个逗比同事提出了一个特别有灵性的办法:加快采样频率!理论是人眼的分辨率是64Hz,如果屏幕每秒钟闪烁的次数超过了64次,那么眼睛就不会被闪瞎了。emmm,经过验证,这是一个可行的解决办法,但是此方法仍然会导致屏幕轻微的闪烁,毕竟每次的压降并不完全一致。但是在辅以降低亮度后,勉强让眼神不好的看不出来了。。。

        然后,体温计设计有蓝牙主从一体的功能,广播和扫描带来的电流尖峰都会导致屏幕闪烁。这里的话,只能在屏幕LED亮起的时候,关闭广播和扫描,屏幕不亮的时候重新打开,然后不亮的时候,还需要将采样频率恢复到1秒10次以节省电量。

        我这边软件的实现方式是:在LED模块中添加一个点亮和关闭的回调接口来通知所有注册过的模块,然后还需要添加一个查询当前点亮状态的函数。

        这里的话,由于整个项目都是自己做的,需要多少个回调接口很清楚,所以直接在这里简单定义了一个数量。如果是多人合作或者暂时不清楚需要通知多少个模块的话,最好采用动态分配的方式来实现。

#define LED_CHANGE_CB_CNT  3
typedef struct{
	uint8_t size;
	on_led_state_changed cb[LED_CHANGE_CB_CNT];
}led_change_cbs;
led_change_cbs g_led_change_cbs={0};

        定义回调函数接口:

typedef void(*on_led_state_changed)(bool is_on);

        添加接口用于注册回调函数:

void set_on_led_state_changed_cb(on_led_state_changed cb){
	if(g_led_change_cbs.size==LED_CHANGE_CB_CNT){
		return;
	}
	for(int i=0;i

        这样,其他模块需要在LED状态发生变化的时候得到通知,就可以使用set_on_led_state_changed_cb这个接口来注册一个回调,从而进行相应的处理。具体到我们项目中就是,调整采样频率,开启或关闭广播和扫描。

        

        由于加快频率的方法并不完美,仍然能看到少许的闪烁,很久以后...决定增加一个LDU模块,据硬件的同事说,这个模块可以稳定LED的电压,只要电压高于LDU设计的水平,就可以让LED的输入电压稳定下来,不再闪烁。增加LDU之后,看起来挺完美的,确实不闪了。硬件又说,加了LDU之后,不可以再使用PWM模式驱动了,说是高频PWM可能会损坏LDU,必须直接连通。软件改为直接连通之后,当电池电量充足的时候,屏幕可以正常点亮,当消耗掉部分电量的时候,开机后居然立即重启了。

        百思不得其解,接上电源分析仪器,发现亮屏的一瞬间,有一个尖峰电流居然高达0.11A。对比了一下使用PWM的情况,亮屏的时候也很大,48mA,但是比直接接通要低很多。其实48mA也是不能接受的,硬件解释了一下,说LDU有一个充电的过程巴拉巴拉,导致电池放电。

        好吧,什么方案都有利弊,但是软件必须得解决这个问题。

        仔细对比使用和不使用PWM,这其中的区别,唯一的点就在于PWM是间歇性的接通的,不使用的时候,是持续接通的。那么,是否是因为PWM将LDU充电的过程分为了好几段,连通一段时间,断开一段时间,给了电池恢复的时间呢?那么解决方案就是,亮屏的一瞬间,模拟一小段PWM的操作呗。

static void patch_for_ldu_high_elec(void){
#if (LED_ENABLE)
	#if (!LED_USE_PWM)
		for(int i=0;i<200;i++){
			nrf_gpio_pin_clear(LED_PIN);
			nrf_delay_us(1);
			nrf_gpio_pin_set(LED_PIN);
			nrf_delay_us(50);
		}
	#endif
#endif	
}

        这里的话,数据是通过反复试验得来的,测得最终的尖峰电流是16mA,平均电流6.8mA,持续约10ms。上边的代码模拟了一个大约19K频率,占空比为1.9%的PWM,持续时间为10ms。如果将占空比调整得更低,可以将尖峰电流降到更低的地步,但是这样的话,会相应的增加需要持续的时间。

        这个问题的解决原理是,将LDU的充电过程分散到200个周期中,每个周期都短暂接通1us然后断开50us。当LDU充电完成,不再大幅度影响电路电压的时候,就可以正常接通LED了。

 

 

       

 

你可能感兴趣的:(#,BLE,物联网,压降,尖峰电流,LED闪烁,Nordic,Ble)