サーミスタで遊んでみたが分圧抵抗の決め方が分からない&温度が正しいかどうかわからない
こないだカホパーツで買った102AT-1というサーミスタをarduinoにつないで温度計をつくってみようと思い立った。
Arduino Playgroundで見つけたサンプルを参考にしてこの記事の下のほうにあるスケッチを作った。
サーミスタは温度によって抵抗値が変化するセンサーで、以下のような配線をした上で、AnalogInputの値から抵抗値を計算できれば温度を計算することができる。
//Schematic: // [Ground] ---- [10k-Resister] -------|------- [Thermistor] ---- [+5v] // | // Analog Pin 0http://www.arduino.cc/playground/ComponentLib/Thermistor2
このスケッチの中ではthermistor.hの関数Thermistor()で、抵抗値への変換を行っていて、Wikipediaによれば、数式は次のような形になる(はず)。
Resistance = ((analogMax * divReg / RawADC) - divReg); // Resistance : サーミスタの抵抗値 // analogMax : AnalogInputが返す最大値(1023) // divReg : 分圧抵抗の値(10K = 10000) // RawADC : AnalogInputから取得した値
抵抗値が取得できれば抵抗値と温度との対応表を使って温度が取得できる。
対応表はデータシートに書いてあるB定数(3100)、基準温度(25)、基準温度の時の抵抗(1000)を以下のページで入力すると得られる。
念のため、サーミスタについていた温度特性グラフと見比べてみたが、大体あっているようだった。
ここで得られた表を配列にして抵抗値に応じて温度を返すような関数を作ればいい。
ただ、疑問が2つ。
1つ目。分圧抵抗はここでは10KΩを使用しているが、分圧抵抗の値が変われば計算結果も変わってくるはず。こういう時の分圧抵抗ってどのように決めたらいいんだろうか。一応回路の中の抵抗を1kΩに取り替えて、プログラムも書き換えてみたがそんなに大きな違いにはならなかった。あまり気にしなくてもいいんだろうか。
2つ目。動かしてみると室温17℃のところで20℃前後の値を返してくる。これは誤差の範囲なんだろうか、それとも回路やプログラムに問題があるんだろうか。
識者の方の意見が聞きたいところです。
以下ソース。
// // thermistor.h // // B定数3100(K)で標準温度25c のとき1kΩであるようなサーミスタ102AT-1における // 抵抗値と温度の関係 // // const double temperature[] = { -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21, 21.5, 22, 22.5, 23, 23.5, 24, 24.5, 25, 25.5, 26, 26.5, 27, 27.5, 28, 28.5, 29, 29.5, 30, 30.5, 31, 31.5, 32, 32.5, 33, 33.5, 34, 34.5, 35, 35.5, 36, 36.5, 37, 37.5, 38, 38.5, 39, 39.5, 40, 40.5, 41, 41.5, 42, 42.5, 43, 43.5, 44, 44.5, 45, 45.5, 46, 46.5, 47, 47.5, 48, 48.5, 49, 49.5, 50, 50.5, 51, 51.5, 52, 52.5, 53, 53.5, 54, 54.5, 55, 55.5, 56, 56.5, 57, 57.5, 58, 58.5, 59, 59.5, 60, 60.5, 61, 61.5, 62, 62.5, 63, 63.5, 64, 64.5, 65, 65.5, 66, 66.5, 67, 67.5, 68, 68.5, 69, 69.5, 70, 70.5, 71, 71.5, 72, 72.5, 73, 73.5, 74, 74.5, 75, 75.5, 76, 76.5, 77, 77.5, 78, 78.5, 79, 79.5, 80, 80.5, 81, 81.5, 82, 82.5, 83, 83.5, 84, 84.5, 85, 85.5, 86, 86.5, 87, 87.5, 88, 88.5, 89, 89.5, 90, 90.5, 91, 91.5, 92, 92.5, 93, 93.5, 94, 94.5, 95 }; const double resistance[] = { 3200.29, 3132.20, 3065.74, 3000.96, 2937.78, 2876.16, 2816.05, 2757.41, 2700.20, 2644.38, 2589.91, 2536.76, 2484.89, 2434.26, 2384.84, 2336.59, 2289.50, 2243.51, 2198.62, 2154.77, 2111.96, 2070.14, 2029.30, 1989.40, 1950.43, 1912.36, 1875.16, 1838.81, 1803.29, 1768.58, 1734.66, 1701.50, 1669.09, 1637.41, 1606.44, 1576.16, 1546.55, 1517.60, 1489.29, 1461.60, 1434.53, 1408.04, 1382.13, 1356.79, 1332.00, 1307.74, 1284.00, 1260.78, 1238.05, 1215.81, 1194.04, 1172.73, 1151.87, 1131.46, 1111.47, 1091.90, 1072.74, 1053.98, 1035.61, 1017.62, 1000.00, 982.74, 965.84, 949.28, 933.06, 917.17, 901.61, 886.35, 871.41, 856.76, 842.41, 828.34, 814.56, 801.04, 787.80, 774.81, 762.09, 749.61, 737.37, 725.38, 713.61, 702.08, 690.76, 679.67, 668.79, 658.12, 647.65, 637.38, 627.30, 617.42, 607.72, 598.20, 588.87, 579.71, 570.72, 561.89, 553.23, 544.73, 536.39, 528.20, 520.16, 512.27, 504.52, 496.91, 489.44, 482.11, 474.90, 467.83, 460.89, 454.06, 447.36, 440.78, 434.32, 427.97, 421.73, 415.60, 409.58, 403.67, 397.85, 392.14, 386.53, 381.01, 375.59, 370.26, 365.03, 359.88, 354.82, 349.85, 344.96, 340.16, 335.43, 330.79, 326.22, 321.73, 317.32, 312.97, 308.70, 304.50, 300.37, 296.31, 292.32, 288.39, 284.52, 280.72, 276.98, 273.30, 269.68, 266.11, 262.61, 259.16, 255.76, 252.42, 249.14, 245.90, 242.72, 239.59, 236.50, 233.47, 230.48, 227.54, 224.64, 221.79, 218.99, 216.22, 213.50, 210.83, 208.19, 205.59, 203.03, 200.52, 198.04, 195.59, 193.19, 190.82, 188.48, 186.19, 183.92, 181.69, 179.49, 177.33, 175.19, 173.09, 171.02, 168.98, 166.97, 164.99, 163.04, 161.12, 159.22, 157.35, 155.51, 153.70, 151.91, 150.15, 148.41, 146.70, 145.01, 143.34, 141.70, 140.08, 138.49 }; //以下のような回路においてAnalogInputの値を温度(セ氏)に変換する関数 //Schematic: // [Ground] ---- [10k-Resister] -------|------- [Thermistor] ---- [+5v] // | // Analog Pin 0 // Inputs ADC Value from Thermistor and outputs Temperature in Celsius // requires: include <math.h> //102AT-1 サーミスタを使用 #include <math.h> #define num_keys (sizeof resistance) / (sizeof resistance[0]) #define divReg 10000.0 // 分圧抵抗の大きさ(10kΩ) #define analogMax 1023 // AnalogReadが返す最大値 double Resistance; double Thermistor(int RawADC) { Resistance = ((analogMax * divReg / RawADC) - divReg); double Temp = 0; int i = 0; for (i = 0; i < num_keys ; i++) { Temp = temperature[i]; if (resistance[i] <= Resistance) { break; } } return Temp; }
//thermo.pde #include "thermistor.h" void setup() { Serial.begin(9600); } void loop(){ int val = analogRead(0); Serial.println(Thermistor(val)); Serial.println(Resistance); delay(500); }
2010/07/08追記
コメント欄のほか、Twitterやメールでも色々な方からサーミスタについていろいろ役に立つ情報を教えていただいています。本当にありがとうございます。
工作のほうはその後進んでいない状態で少し申し訳ない気持ちです。チャレンジしたいと思ってはいるのですが。。。ごめんなさい。