Transistor Gijutsu, October 2014, Special Features Chapter 8,Software of the thermistor thermometer of 0.001 ° resolution, トランジスタ技術2014年10月号 特集第8章のソフトウェア 0.001℃分解能で気配もキャッチ「超敏感肌温度計」

Dependencies:   USBDevice mbed

Information

tg_201410s8_AD7714 トランジスタ技術 2014年 10月号 第8章のソフトウェア

Program for Section 8 in October. 2014 issue of the Transistor Gijutsu
(Japanese electronics magazine)

概要

このプログラムは、サーミスタの抵抗値変化をAD7714(24bitADC)で測定し、抵抗値を温度値に変換することで、0.001℃程度の分解能で温度変化を測定します。

ファイル

このソフトウエアは、次のファイルから構成されています。

  • AD7714.cpp - AD7714の内部レジスタを設定
  • Thermistor.cpp - サーミスタの抵抗値から温度値に変換
  • ExpAvr.cpp - 指数平均によるソフトウエアLPF
  • main.cpp - main()関数

詳細については、10月号の記事および上記ファイル中のコメントを参照してください。

Revision:
0:de885a6da962
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD7714/AD7714.cpp	Fri Aug 29 08:38:36 2014 +0000
@@ -0,0 +1,156 @@
+#include "AD7714.h"
+
+
+#define MAINCLKF (48)   // main clock 48MHz
+#define CLKFRQ (1000)   // clkout の周波数 kHz
+
+/// コンストラクタ
+/// - PWMおよびSPIポートを初期化
+/// - PWMはAD7714のマスタークロック1MHzを生成する
+AD7714::AD7714(void)
+{
+    // CLKOUT を1MHzに設定
+    // set clock divider
+    LPC_SYSCON->CLKOUTDIV = (CLKFRQ * MAINCLKF) / 1000;
+    // main clock -> CLKOUT
+    LPC_SYSCON->CLKOUTSEL = 0x3;
+    LPC_SYSCON->CLKOUTUEN = 0;
+    LPC_SYSCON->CLKOUTUEN = 1;
+    // P0_1 -> CLKOUT
+    LPC_IOCON->PIO0_1 |= 0x01;
+
+
+    // SPIポート初期化
+    spi = new SPI(P0_9, P0_8, P0_10);
+    // SPI信号のアイドルレベルとクロック位相を設定
+    LPC_SSP0->CR0 |= 0xc0;
+
+    // ADCのリセットとフィルタ設定
+    reset();
+    setFilter(2);
+
+    // 各チャネルのゼロ点とフルスケールの校正(キャリブレーション)
+    // 内部的に入力を短絡してゼロスケールを校正
+    // 内部的に入力をVrefに接続してフルスケールを校正
+    // 他のチャネルを使う場合は、コメントを外す
+    // キャリブレーションには時間がかかるので必要なチャネルだけ初期化
+    channel = Ch.A1A2;
+    calib();
+    //channel = Ch.A3A4;
+    //calib();
+    //channel = Ch.A5A6;
+    //calib();
+};
+
+/// キャリブレーション
+/// チャネル、ゲイン、フィルタ周波数を変更したあと必ず実行せよ
+void AD7714::calib(void)
+{
+    write(Reg.Mode, 0x20);
+    while(isBusy()){
+    }
+}
+
+/// SPI通信ポートの初期化
+void AD7714::reset(void)
+{
+    for(int a = 0; a < 5; a++){
+        writeByte(0xff);
+    }
+}
+
+/// 変換中なら真を返す
+bool AD7714::isBusy(void)
+{
+    writeByte(CRegister::Comun | CmdRead | channel);
+    return (writeByte(CmdRead) & 0x80) != 0;
+}
+
+/// 1バイト送信
+/// @param txd 送信データ
+/// @return 受信データ
+int AD7714::writeByte(int txd)
+{
+    return spi->write(txd);
+};
+
+/// レジスタの内容を読む
+/// @param reg レジスタを指定する値 Reg構造体のメンバー
+/// @return レジスタの内容
+int AD7714::read(int reg)
+{
+    int r, cmd;
+    cmd = reg | CmdRead | channel;
+    writeByte(cmd);
+    r = writeByte(cmd);
+    if(reg >= Reg.Data){
+        r = (r<<8) | writeByte(cmd);
+        r = (r<<8) | writeByte(cmd);
+    }
+    return r;
+}
+
+/// 指定レジスタに書き込む
+/// 指定レジスタが8bitか24bitがを判別して書き込む
+/// @param reg レジスタを指定する値 Reg構造体のメンバー
+/// @param data 書き込むデータ
+/// @return なし
+void AD7714::write(int reg, int data)
+{
+    writeByte(reg | CmdWrite | channel);
+    writeByte(data & 0xff);
+    if(reg >= Reg.Data){
+        data >>= 8;
+        writeByte(data & 0xff);
+        data >>= 8;
+        writeByte(data & 0xff);
+    }
+}
+
+/// フィルターノッチ周波数の設定(19Hz - 4000Hz)
+///-# 周波数を上げると変換時間は短縮されるがノイズが増える
+///-# 60に設定すると60Hzの電源ノイズのキャンセルに有効
+/// @param freq ノッチ周波数[Hz] 
+/// @return なし
+void AD7714::setFilter(int freq)
+{
+    int code = (FclkIn / 128) / freq;
+    if(code < 19){
+        code = 19;
+    }else if(code > 4000){
+        code = 4000;
+    }
+    // バイポーラ入力に設定
+    write(Reg.FltHi, 0x40 | ((code >> 8) & 0x0f));
+    write(Reg.FltLo, code & 0xff);
+}
+
+
+/// レシオメトリックADCクラスのコンストラクタ(初期化に数秒を要する)
+/// @param Rpu プラス入力のVcc側抵抗値、GND側抵抗としてセンサを接続する。
+/// @param Rmu マイナス入力のVcc側抵抗値
+/// @param Rml マイナス入力のGND側抵抗値
+/// @param Rru リファレンス入力のVcc側抵抗値
+/// @param Rrl リファレンス入力のGND側抵抗値
+RatioMetric7714::RatioMetric7714(double Rpu, double Rmu, double Rml, double Rru, double Rrl)
+{
+    af = 1 << bits;
+    rpu = Rpu; rmu = Rmu; rml = Rml; rru = Rru; rrl = Rrl;  
+}
+
+/// 与えられたADC値をレシオメトリックにより抵抗値に変換する
+/// @param int adVal AD変換値
+/// @return 変換さた抵抗値
+double RatioMetric7714::toResistorValue(int adVal)
+{
+    return  -((rpu*(2*adVal*(rml + rmu)*rrl + af*(-(rmu*rrl) + rml*rru)))
+            /(2*adVal*(rml + rmu)*rrl - af*(rml*rrl + rmu*(2*rrl + rru))));
+
+}
+
+/// 現在のADC値を抵抗値に変換して返す
+/// @return 測定された抵抗値
+double RatioMetric7714::getResistorValue(void)
+{
+    return toResistorValue(getValue());
+}