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月号の記事および上記ファイル中のコメントを参照してください。

AD7714/AD7714.cpp

Committer:
Dance
Date:
2014-08-29
Revision:
0:de885a6da962

File content as of revision 0:de885a6da962:

#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());
}