CC2541之電池電量服務

轉自:http://blog.csdn.net/feilusia

一、簡介

本篇以SimpleBLEPeripheral工程爲例,介紹如何添加一個電池電量服務。


二、實驗平臺

協議棧版本:BLE-CC254x-1.4.0

編譯軟件: IAR 8.20.2

硬件平臺: Smart RF開發板

手機平臺: 紅米1S

安卓系統: Android 4.3

APP: BLE Device Monitor


三、版權聲明

博主:甜甜的大香瓜

聲明:喝水不忘挖井人,轉載請註明出處。

原文地址:http://blog.csdn.net/feilusia

聯繫方式:[email protected]

技術交流QQ羣:127442605


四、CC2541的電池電量服務簡介

1、電池電量服務是什麼?

答:它是電池電量專用的服務,手機能通過這個服務獲取到CC2541的電池電量。


2、爲什麼需要電池電量服務?

答:CC2541一般通過USB直接供電或鈕釦電池供電。其中通過鈕釦電池供電的方式,鈕釦電池的電量使用情況是用戶必須知道的數據。

否則手機與CC2541通信不成功,到底是CC2541死機了還是沒電了,就說不清楚了。


3、通過什麼方式獲取電池電量?

答:

方法一、通過內部的10bit的adc通道採集電池電量(最高位是符號位,所以實際是9bit精度)。


方法二、通過最高12bit的adc通道採集電池電量(最高位是符號位,所以實際是11bit精度)。



4、採集電池電量是如何計算的?

答:

把CC2541的鈕釦電池電壓從2.0v~3.0v,當做電量的0%~100%。(香瓜猜測這麼做是因爲2~3V正好是CC2541的正常工作電壓)

而CC2541的內部帶符號的10bit的adc通道,量程範圍爲0~511,使用的參考電壓爲1.25v。

由於adc只有1.25v的參考電壓,不能採集到2~3v的電壓,因此我們把電池電壓經過分壓後採集,也就是採集1/3的電池電壓,adc把2v/3~3v/3當做電壓的0%~100%。

因此,由以上信息獲得一個公式:(v/3)/ 1.25  = adc/511

其中,v是電池的實際鈕釦電池的電壓,adc是2541採集到的數值。


當v= 2時,adc=273。也就是CC2541採集到的adc值爲273時,電壓值爲2v,是0%的電量。

當v= 3時,adc=409。也就是CC2541採集到的adc值爲409時,電壓值爲3v,是100%的電量。

假設2v~3v時的變化是線性的,則可得到下圖:


其中上圖的Xadc和percentage是當前讀到的adc值和當前電量的百分比。

利用兩個相似三角形的特性,可以得到公式:

Percentage / (X – 273) = 100 / 136


變換後爲:
Percentage = (X - 273) * 25 / 34

由上式四捨五入提高計算精度則有:
Percentage = [(X - 273) * 25 + 33] / 34


五、代碼修改

1、保證項目中有hal_adc.c和hal_adc.h



2、在工程的PROFILES分類中添加battservice.c與battservice.h兩個文件


兩文件路徑:C:\Texas Instruments\BLE-CC254x-1.4.0\Projects\ble\Profiles\Batt


3、IAR設置中添加倆路徑



4、開啓ADC的宏



5、添加電池服務的頭文件(simpleBLEPeripheral.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #include "battservice.h"  

6、定義一個電池默認臨界值的宏(simpleBLEPeripheral.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #define DEFAULT_BATT_CRITICAL_LEVEL  6  

定義爲6,也就是電量低於6%時CC2541會主動notify通知主機電量過低。


7、添加初始化電池電量的代碼(simpleBLEPeripheral.c的SimpleBLEPeripheral_Init()函數中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void SimpleBLEPeripheral_Init( uint8 task_id )  
  2. {  
  3.   simpleBLEPeripheral_TaskID = task_id;  
  4.   
  5.   //電池服務  
  6.   {     
  7.   
  8.     uint8 critical = DEFAULT_BATT_CRITICAL_LEVEL;  
  9.   
  10.     Batt_SetParameter( BATT_PARAM_CRITICAL_LEVEL, sizeof (uint8 ), &critical );/* 設置默認臨界電量 */  
  11.   
  12.   }  
  13.   
  14.   Batt_AddService();  /* 添加電池服務 */  
  15.   
  16.   Batt_Register(BattCB); /* 註冊電池服務的應用回調函數 */  
  17.   
  18.   ……  
  19. }  

8、定義電池電量服務的回調函數(simpleBLEPeripheral.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //******************************************************************************    
  2. //name:             BattCB  
  3. //introduce:        電池電量服務的回調函數  
  4. //parameter:        event:事件               
  5. //return:           none  
  6. //author:       甜甜的大香瓜  
  7. //changetime:       2015.12.13  
  8. //******************************************************************************  
  9. static void BattCB(uint8 event)  
  10. {  
  11.   if (event == BATT_LEVEL_NOTI_ENABLED)  
  12.   {  
  13.     if (gapProfileState == GAPROLE_CONNECTED)  
  14.     {         
  15.   
  16.     }   
  17.   }  
  18.   
  19.   else if (event == BATT_LEVEL_NOTI_DISABLED)  
  20.   {  
  21.      
  22.   }  
  23. }  

回調函數的作用只是在開、關通知時告知應用層。

回調函數是在下面的情況被調用的:



9、聲明電池電量服務的回調函數(simpleBLEPeripheral.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static void BattCB(uint8 event);  


10、添加一段週期監測電量的代碼(simpleBLEPeripheral.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static void performPeriodicTask( void )  
  2. {  
  3.   if ( gapProfileState == GAPROLE_CONNECTED )  
  4.   {  
  5.     // perform battery level check  
  6.     Batt_MeasLevel( );  
  7.   }  
  8. }  
協議棧默認的週期事件是5S。也就是連接狀態下,每5S會執行上面的代碼去更新電量。

當電量小於我們設置的DEFAULT_BATT_CRITICAL_LEVEL(本篇設置爲6)時,會在Batt_MeasLevel( )函數裏主動notify告知主機。


六、實驗結果

1、仿真查看adc採集到的電量

單步執行查看內部adc採集到的電源值爲459


將adc=459,代入公式“(v/3)/ 1.25  = adc/511”中,得到v=3.36839530332681


2、萬用表測試開發板的電源電壓

實測VCC=3.20V


3、用手機app查看電源電量百分比


由於暫時使用USB供電,所以實測電壓在3.20V,大於3V的都算100%電量。

因此讀出了默認值0x64,也就是電量100%。


七、相關問題

1、實測外部電壓2V時,對應爲10%的電量,偏差太大怎麼辦?

答:

1)實測2V、3V時的ADC值(假設測出2V對應爲287、3V對應爲425)。

2)修改宏定義(Battservice.c中)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. // ADC voltage levels  
  2. #define BATT_ADC_LEVEL_3V           425//409  
  3. #define BATT_ADC_LEVEL_2V           287//273  
發佈了84 篇原創文章 · 獲贊 63 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章