« LTC2460 無駄待ちはダメ! busyチェックで他の仕事をしろ! | トップページ | シミュレーテッド・インダクタを使った60Hzノッチ・フィルタ:これから »

2021年8月11日 (水)

サーミスタ温度計、何ビットのA/Dコンバータがいるか?

サーミスタで温度測定するとき、
 ・A/Dコンバータの分解能の違いで、何度の桁まで測れるか?
あるいは、
 ・何度の桁まで計りたい時は何ビットのA/Dが必要か?

この答えのグラフがトランジスタ技術2012年1月号p89
図3に出ていました。
 ●特集:エレクトロニクス格言集
  3-6 抵抗分圧比をA-D変換する時の
  基準電源ICは無駄遣い  著者:星聡

Ad01
8ビット分解能でも1℃ステップで測れないことはない
というキャプション。

先日作った温度計で使った「103JT」サーミスタの
温度特性から、これと同じような表を作ってみました。

セミテック103JTの温度:抵抗値表

#SEMITEC 103JT 温度・抵抗特性
#温度 抵抗値
#℃ Ω
-20 71020.0
-10 43670.0
0 27700.0
10 18070.0
20 12110.0
25 10000.0
30 8301.0
40 5811.0
50 4147.0
60 3011.0
70 2224.0
80 1668.0
85 1451.0
90 1267.0
100 975.3
110 759.7
120 598.1


それを「gawk」に食わせて1℃ごとのテーブルを作成

#####   サーミスタ抵抗値計算プログラム    #####
# 下間憲行  jh3dbo@jarl.com
# 10℃ごとの温度,抵抗値テーブルから
# 1℃ごとの抵抗値データを作成
# メモ awkのlogは自然対数

BEGIN{
# 定数指定
K_273 = 273.15 # ケルビン温度
Rref = 10.0e3 # 直列抵抗 10kΩ
Aref = 65536 # 16bit A/D max
# タイトル表示
print("* サーミスタ抵抗値計算 (2015-06-10)\n") > "/dev/stderr"
nbr = 1 # 読み込みデータ数
}
# 「BEGIN」おわり (以下、ファイル読み出し処理)

##### 温度,抵抗値テーブルを読み出す #####
# 10℃ごとの温度と抵抗値を順に読む
{
if( $0 ~/^#/ ) next # 先頭文字が「#」ならコメント
# 数値入力
temp[nbr] = $1 # 温度
ohm[nbr] = $2 # 抵抗値
# printf("%d %s %s\n", nbr , temp[nbr], ohm[nbr])
nbr++ # 配列 +1
}
# ファイル処理おわり (以下、END処理)

##### 10℃ごとのB定数計算して1℃ごとの処理 #####
# ※基準は25℃なので、20~25~30℃となっているので注意
END{
# B定数計算 10℃ごと
print("# B定数")
for(i = 1; i < (nbr - 1); i++){
t1 = temp[i]
t2 = temp[i+1]
r1 = ohm[i]
r2 = ohm[i+1]
B[i] = (log(r1 / r2)) / ((1 / (t1+K_273)) - (1 / (t2+K_273)))
printf("# %d℃~%d℃ %3.1fΩ~%3.1fΩ B=%3.1f\n",
t1, t2, r1, r2, B[i])
}
# 1℃ごとの抵抗値を計算
print("# ℃ Ω")
m = 1 # 1℃ごと (0.1℃ステップなら10に)
for(i = 1; i < (nbr - 1); i++){ # 10℃のテーブル
n = (temp[i+1] - temp[i]) * m # 表の温度差
for(j = 0; j < n; j++){ # 1℃ピッチで
R = tohm(temp[i] + (j / m), temp[i], ohm[i], B[i])
ad = Aref * (R / (Rref + R)) # A/D値
printf("%6.1f %12.2f %6d", # 温度と抵抗値
temp[i] + (j / m), R, ad)
if(f){
printf(" %8.2f %8.2f", # 抵抗値とA/D値の差分
r0 - R, ad0 - ad)
}
printf("\n")
r0 = R;
ad0 = ad;
f = 1;
}
}
}

##### 温度による抵抗値計算 #####
# T1 = 計算する温度
# Tm = 基準温度
# Rm = 基準温度での抵抗値,
# Bconst:B定数, 273:ケルビン温度
# 1 1
# R = Rm * exp( Bconst * (--------- - -----------) )
# t1 + 273 Tm + 273
function tohm(T1, Tm, Rm, Bconst){
return(Rm * exp(Bconst*((1.0 / (T1 + K_273)) - (1.0 / (Tm + K_273)))))
}


その結果を「gnuplot」で処理

set term wxt 0
set ytics nomirror
set y2tics
set xrange [-20:110]
set yrange [0.001:10]
set y2range [0:800]
set title "A/D値が1LSB変化したときの温度変化 【サーミスタ103JT Rs=10kΩ】"
set xlabel "温度 (℃)"
set ylabel "1LSB変化したときの温度変化(℃)"
set y2label "16 bit A/Dでの1℃あたりの変換値変化"
set grid
set xtics 10
#set ytics 500
set key right top
set pointsize 0.5
set logscale y
set label "" at second -8, 770
set label "16bit A/D値変化(右目盛)" at second 2, 660
set label "8bit A/D" at second 11, 560
set label "10bit A/D" at second 12, 440
set label "12bit A/D" at second 13, 320
set label "14bit A/D" at second 14, 200
set label "16bit A/D" at second 15, 80
plot "ohm3.txt" using 1:5 with line lw 2 ti "" axes x1y2,\
"ohm3.txt" using 1:(1 / ($5/256)) with line lw 2 ti "",\
"ohm3.txt" using 1:(1 / ($5/64)) with line lw 2 ti "",\
"ohm3.txt" using 1:(1 / ($5/16)) with line lw 2 ti "",\
"ohm3.txt" using 1:(1 / ($5/4)) with line lw 2 ti "",\
"ohm3.txt" using 1:(1 / $5) with line lw 2 ti ""


こんなグラフが得られます。
Cap005_20210811095101
8,10,12,14,16ビットのA/Dコンバータを使った
時の分解能の変化を示しています。
   ※A/D変換器や周辺回路の精度が加味されますんで、
    1bitの変動でもきびしい状態が浮かんでくるかと。

10℃~25℃あたりが良くて、1℃あたりのA/D変換値変化量
が減る高温域(70℃を越える)になると分解能が悪化するのが
見えます。
  ※8bitA/Dで「水温・湯温」を計ろうとしたとき、
   0℃~40℃くらいまでは0.5℃ピッチで読めます。
   しかし、80℃を越えると1℃ピッチでの読みが
   しんどくなります。
   昔々・・・4bitマイコンで電気温水器の仕事をした
   ときは(東芝の8bit A/D内蔵品)、出てきた
   8bit値(256バイト)をそのまま1℃単位の温度に変換する
   テーブルを作って処理しました。
     水温が正しくない上下の値はエラー処理
     (氷温以下と沸騰温度以上)

分解能16bitのA/Dを使っても、A/Dの誤差を考えると「0.01℃」の
測定はなかなかむつかしいということで。


|

« LTC2460 無駄待ちはダメ! busyチェックで他の仕事をしろ! | トップページ | シミュレーテッド・インダクタを使った60Hzノッチ・フィルタ:これから »

Arduino」カテゴリの記事

AWK(GAWK)」カテゴリの記事

gnuplot」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« LTC2460 無駄待ちはダメ! busyチェックで他の仕事をしろ! | トップページ | シミュレーテッド・インダクタを使った60Hzノッチ・フィルタ:これから »