Transistor Gijutsu, October 2014, Special Features Chapter 8,Software of the thermistor thermometer of 0.001 ° resolution, トランジスタ技術2014年10月号 特集第8章のソフトウェア 0.001℃分解能で気配もキャッチ「超敏感肌温度計」
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月号の記事および上記ファイル中のコメントを参照してください。
Diff: AD7714/AD7714.cpp
- 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()); +}