電池溫度檢測原理和示例代碼


一、原理

  其實電池內部有個熱敏電阻, 與外部分壓電阻構成一個簡單的分壓電路,  根據ADC采樣得到的電壓j計算熱敏阻值再反推此時的溫度, 首先我們要先了解熱敏電阻阻值和溫度一個公式:

/* NTC熱敏電阻公式 Rt = R * exp(B*(1/T1-1/T2))
Rt:在T1下的電阻值
T1/T2: 指的是K度,即開爾文溫度, T=273.15 + 攝氏度
R: 在T2下的標稱阻值,比如在25攝氏度10000歐, T2=273.15 + 25
B:熱敏電阻一個參數, 比如3950
exp:e的n次方

我們可以通過溫度得到阻值, 也可以通過阻值得到溫度
Rt = 10000 * exp(3950*(1/(273.15+t1) - 1/298.15))
t1=1/(ln(Rt/10000)/3950+1/298.15)-273.15
*/

  我的外部電路如下:

 

   J2是電池插座, 三根線, 中間的就是NTC, BAT_DET連接處理器的ADC采樣引腳, 分壓電阻阻值47k, 參考電壓1.8v, 所以:

Rt = Vadc * Rf / (Vin-Vadc)
Vadc: 熱敏電阻對應的電壓值
Rf: 分壓電阻  對應電路47k
Vin: 參考電壓 1.8v

   至於Vadc采樣電壓就是各個處理器自己的事了, 只要確保采集的電壓是准確的, 可以和萬用表對比

二、示例代碼

  下面就演示溫度從零下-10度到60度 熱敏電阻阻值以及根據采樣電壓反推熱敏電阻的溫度, 需要注意的是,代碼需要包含math.h函數庫的支持, 同時, 數學ln()的叫法在C庫是log()

/* gcc test.c -lm */
#include<stdio.h> #include <math.h> int main() {
  int t1; double Rt, Vadc; /* 溫度從零下-10度到60度 熱敏電阻阻值 */ for(t1=-10; t1<60; t1++) { Rt = 10000 * exp(3950*(1/(273.15+t1) - 1/298.15)); Vadc = 1800*Rt/(Rt + 47000); printf("%d = %.10fmv\n", t1, Vadc); } /* 根據采樣電壓反推熱敏電阻的溫度 */ for(Vadc=100; Vadc<1000; Vadc+=100) { Rt = Vadc * 47000 / (1800-Vadc); t1=1/(ln(Rt/10000)/3950+1/298.15)-273.15; printf("%.10fmv = %d\n", Vadc, t1); } return 0; }

 

對應的log:

-10 = 996.1667819082mv
-9 = 970.8171351943mv
-8 = 945.5463090268mv
-7 = 920.3938859522mv
-6 = 895.3981112286mv
-5 = 870.5956912898mv
-4 = 846.0216150692mv
-3 = 821.7089994324mv
-2 = 797.6889594676mv
-1 = 773.9905039042mv
0 = 750.6404554807mv
1 = 727.6633956682mv
2 = 705.0816327966mv
3 = 682.9151923094mv
4 = 661.1818276246mv
5 = 639.8970498688mv
6 = 619.0741746119mv
7 = 598.7243836333mv
8 = 578.8567997063mv
9 = 559.4785723909mv
10 = 540.5949728601mv
11 = 522.2094958620mv
12 = 504.3239670152mv
13 = 486.9386537600mv
14 = 470.0523784230mv
15 = 453.6626319968mv
16 = 437.7656873959mv
17 = 422.3567110965mv
18 = 407.4298722257mv
19 = 392.9784483112mv
20 = 378.9949270420mv
21 = 365.4711035231mv
22 = 352.3981726282mv
23 = 339.7668161643mv
24 = 327.5672846610mv
25 = 315.7894736842mv
26 = 304.4229946520mv
27 = 293.4572401925mv
28 = 282.8814441428mv
29 = 272.6847363289mv
30 = 262.8561923090mv
31 = 253.3848782846mv
32 = 244.2598914134mv
33 = 235.4703957662mv
34 = 227.0056541849mv
35 = 218.8550563020mv
36 = 211.0081429835mv
37 = 203.4546274551mv
38 = 196.1844133667mv
39 = 189.1876100427mv
40 = 182.4545451581mv
41 = 175.9757750675mv
42 = 169.7420930061mv
43 = 163.7445353679mv
44 = 157.9743862542mv
45 = 152.4231804741mv
46 = 147.0827051655mv
47 = 141.9450001930mv
48 = 137.0023574679mv
49 = 132.2473193230mv
50 = 127.6726760645mv
51 = 123.2714628124mv
52 = 119.0369557321mv
53 = 114.9626677478mv
54 = 111.0423438230mv
55 = 107.2699558814mv
56 = 103.6396974382mv
57 = 100.1459779998mv
58 = 96.7834172883mv
59 = 93.5468393367mv
100.0000000000mv = 57
200.0000000000mv = 37
300.0000000000mv = 26
400.0000000000mv = 18
500.0000000000mv = 12
600.0000000000mv = 6
700.0000000000mv = 2
800.0000000000mv = -2
900.0000000000mv = -6

 

三、其他

  a. 數學中對數用log表示,ln表示以e為底數, C庫使用log()卻表示數學的ln, 如果要表示數學的logab, 由於等效數學的lnb/lna, 即等效C代碼log(b)/log(a)

  b. ADC采樣精度是個問題, 同時最好多次采樣取平均值

  c. 由於我是要在驅動實現這個功能, 內核沒有包含這個math.h和libgcc.a庫, 所以參考網上實現了個差不多精度函數:

double ln(double a)
{
    int N = 15;
    int k,nk;
    double x,xx,y;

    x = (a-1)/(a+1);
    xx = x*x;
    nk = 2*N+1;
    y = 1.0/nk;
    for(k=N;k>0;k--) {
        nk = nk - 2;
        y = 1.0/nk+xx*y;
    }

    return 2.0*x*y;
}
/* https://blog.csdn.net/mike190267481/article/details/7404702 */

對比log如下:

    printf("%.10f, %.10f\n", ln(0.1), log(0.1));
    printf("%.10f, %.10f\n", ln(1), log(1));
    printf("%.10f, %.10f\n", ln(5), log(5));
    printf("%.10f, %.10f\n", ln(10), log(10));
    printf("%.10f, %.10f\n", ln(15), log(15));
    printf("%.10f, %.10f\n", ln(20), log(20));

-2.3023645999, -2.3025850930
0.0000000000, 0.0000000000
1.6094377510, 1.6094379124
2.3023645999, 2.3025850930
2.7053425934, 2.7080502011
2.9856609824, 2.9957322736

尷尬的是內核不支持浮點運算, 所以這個在應用程序調試OK的ln()函數作廢, 只能先在應用程序打出各個采樣電壓對應的溫度, 做成一個表格, 然后驅動再根據電壓查詢表格得到對應溫度了

 

至於為何內核不能進行浮點運算, 這是另一個問題了, 可以參考我另一篇博文:

Linux內核使用浮點運算問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM