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

Committer:
Dance
Date:
Fri Aug 29 08:38:36 2014 +0000
Revision:
0:de885a6da962
Transistor Gijutsu, October 2014, Special Features Chapter 8; ????????2014?10??????8????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Dance 0:de885a6da962 1 #include "AD7714.h"
Dance 0:de885a6da962 2
Dance 0:de885a6da962 3
Dance 0:de885a6da962 4 #define MAINCLKF (48) // main clock 48MHz
Dance 0:de885a6da962 5 #define CLKFRQ (1000) // clkout の周波数 kHz
Dance 0:de885a6da962 6
Dance 0:de885a6da962 7 /// コンストラクタ
Dance 0:de885a6da962 8 /// - PWMおよびSPIポートを初期化
Dance 0:de885a6da962 9 /// - PWMはAD7714のマスタークロック1MHzを生成する
Dance 0:de885a6da962 10 AD7714::AD7714(void)
Dance 0:de885a6da962 11 {
Dance 0:de885a6da962 12 // CLKOUT を1MHzに設定
Dance 0:de885a6da962 13 // set clock divider
Dance 0:de885a6da962 14 LPC_SYSCON->CLKOUTDIV = (CLKFRQ * MAINCLKF) / 1000;
Dance 0:de885a6da962 15 // main clock -> CLKOUT
Dance 0:de885a6da962 16 LPC_SYSCON->CLKOUTSEL = 0x3;
Dance 0:de885a6da962 17 LPC_SYSCON->CLKOUTUEN = 0;
Dance 0:de885a6da962 18 LPC_SYSCON->CLKOUTUEN = 1;
Dance 0:de885a6da962 19 // P0_1 -> CLKOUT
Dance 0:de885a6da962 20 LPC_IOCON->PIO0_1 |= 0x01;
Dance 0:de885a6da962 21
Dance 0:de885a6da962 22
Dance 0:de885a6da962 23 // SPIポート初期化
Dance 0:de885a6da962 24 spi = new SPI(P0_9, P0_8, P0_10);
Dance 0:de885a6da962 25 // SPI信号のアイドルレベルとクロック位相を設定
Dance 0:de885a6da962 26 LPC_SSP0->CR0 |= 0xc0;
Dance 0:de885a6da962 27
Dance 0:de885a6da962 28 // ADCのリセットとフィルタ設定
Dance 0:de885a6da962 29 reset();
Dance 0:de885a6da962 30 setFilter(2);
Dance 0:de885a6da962 31
Dance 0:de885a6da962 32 // 各チャネルのゼロ点とフルスケールの校正(キャリブレーション)
Dance 0:de885a6da962 33 // 内部的に入力を短絡してゼロスケールを校正
Dance 0:de885a6da962 34 // 内部的に入力をVrefに接続してフルスケールを校正
Dance 0:de885a6da962 35 // 他のチャネルを使う場合は、コメントを外す
Dance 0:de885a6da962 36 // キャリブレーションには時間がかかるので必要なチャネルだけ初期化
Dance 0:de885a6da962 37 channel = Ch.A1A2;
Dance 0:de885a6da962 38 calib();
Dance 0:de885a6da962 39 //channel = Ch.A3A4;
Dance 0:de885a6da962 40 //calib();
Dance 0:de885a6da962 41 //channel = Ch.A5A6;
Dance 0:de885a6da962 42 //calib();
Dance 0:de885a6da962 43 };
Dance 0:de885a6da962 44
Dance 0:de885a6da962 45 /// キャリブレーション
Dance 0:de885a6da962 46 /// チャネル、ゲイン、フィルタ周波数を変更したあと必ず実行せよ
Dance 0:de885a6da962 47 void AD7714::calib(void)
Dance 0:de885a6da962 48 {
Dance 0:de885a6da962 49 write(Reg.Mode, 0x20);
Dance 0:de885a6da962 50 while(isBusy()){
Dance 0:de885a6da962 51 }
Dance 0:de885a6da962 52 }
Dance 0:de885a6da962 53
Dance 0:de885a6da962 54 /// SPI通信ポートの初期化
Dance 0:de885a6da962 55 void AD7714::reset(void)
Dance 0:de885a6da962 56 {
Dance 0:de885a6da962 57 for(int a = 0; a < 5; a++){
Dance 0:de885a6da962 58 writeByte(0xff);
Dance 0:de885a6da962 59 }
Dance 0:de885a6da962 60 }
Dance 0:de885a6da962 61
Dance 0:de885a6da962 62 /// 変換中なら真を返す
Dance 0:de885a6da962 63 bool AD7714::isBusy(void)
Dance 0:de885a6da962 64 {
Dance 0:de885a6da962 65 writeByte(CRegister::Comun | CmdRead | channel);
Dance 0:de885a6da962 66 return (writeByte(CmdRead) & 0x80) != 0;
Dance 0:de885a6da962 67 }
Dance 0:de885a6da962 68
Dance 0:de885a6da962 69 /// 1バイト送信
Dance 0:de885a6da962 70 /// @param txd 送信データ
Dance 0:de885a6da962 71 /// @return 受信データ
Dance 0:de885a6da962 72 int AD7714::writeByte(int txd)
Dance 0:de885a6da962 73 {
Dance 0:de885a6da962 74 return spi->write(txd);
Dance 0:de885a6da962 75 };
Dance 0:de885a6da962 76
Dance 0:de885a6da962 77 /// レジスタの内容を読む
Dance 0:de885a6da962 78 /// @param reg レジスタを指定する値 Reg構造体のメンバー
Dance 0:de885a6da962 79 /// @return レジスタの内容
Dance 0:de885a6da962 80 int AD7714::read(int reg)
Dance 0:de885a6da962 81 {
Dance 0:de885a6da962 82 int r, cmd;
Dance 0:de885a6da962 83 cmd = reg | CmdRead | channel;
Dance 0:de885a6da962 84 writeByte(cmd);
Dance 0:de885a6da962 85 r = writeByte(cmd);
Dance 0:de885a6da962 86 if(reg >= Reg.Data){
Dance 0:de885a6da962 87 r = (r<<8) | writeByte(cmd);
Dance 0:de885a6da962 88 r = (r<<8) | writeByte(cmd);
Dance 0:de885a6da962 89 }
Dance 0:de885a6da962 90 return r;
Dance 0:de885a6da962 91 }
Dance 0:de885a6da962 92
Dance 0:de885a6da962 93 /// 指定レジスタに書き込む
Dance 0:de885a6da962 94 /// 指定レジスタが8bitか24bitがを判別して書き込む
Dance 0:de885a6da962 95 /// @param reg レジスタを指定する値 Reg構造体のメンバー
Dance 0:de885a6da962 96 /// @param data 書き込むデータ
Dance 0:de885a6da962 97 /// @return なし
Dance 0:de885a6da962 98 void AD7714::write(int reg, int data)
Dance 0:de885a6da962 99 {
Dance 0:de885a6da962 100 writeByte(reg | CmdWrite | channel);
Dance 0:de885a6da962 101 writeByte(data & 0xff);
Dance 0:de885a6da962 102 if(reg >= Reg.Data){
Dance 0:de885a6da962 103 data >>= 8;
Dance 0:de885a6da962 104 writeByte(data & 0xff);
Dance 0:de885a6da962 105 data >>= 8;
Dance 0:de885a6da962 106 writeByte(data & 0xff);
Dance 0:de885a6da962 107 }
Dance 0:de885a6da962 108 }
Dance 0:de885a6da962 109
Dance 0:de885a6da962 110 /// フィルターノッチ周波数の設定(19Hz - 4000Hz)
Dance 0:de885a6da962 111 ///-# 周波数を上げると変換時間は短縮されるがノイズが増える
Dance 0:de885a6da962 112 ///-# 60に設定すると60Hzの電源ノイズのキャンセルに有効
Dance 0:de885a6da962 113 /// @param freq ノッチ周波数[Hz]
Dance 0:de885a6da962 114 /// @return なし
Dance 0:de885a6da962 115 void AD7714::setFilter(int freq)
Dance 0:de885a6da962 116 {
Dance 0:de885a6da962 117 int code = (FclkIn / 128) / freq;
Dance 0:de885a6da962 118 if(code < 19){
Dance 0:de885a6da962 119 code = 19;
Dance 0:de885a6da962 120 }else if(code > 4000){
Dance 0:de885a6da962 121 code = 4000;
Dance 0:de885a6da962 122 }
Dance 0:de885a6da962 123 // バイポーラ入力に設定
Dance 0:de885a6da962 124 write(Reg.FltHi, 0x40 | ((code >> 8) & 0x0f));
Dance 0:de885a6da962 125 write(Reg.FltLo, code & 0xff);
Dance 0:de885a6da962 126 }
Dance 0:de885a6da962 127
Dance 0:de885a6da962 128
Dance 0:de885a6da962 129 /// レシオメトリックADCクラスのコンストラクタ(初期化に数秒を要する)
Dance 0:de885a6da962 130 /// @param Rpu プラス入力のVcc側抵抗値、GND側抵抗としてセンサを接続する。
Dance 0:de885a6da962 131 /// @param Rmu マイナス入力のVcc側抵抗値
Dance 0:de885a6da962 132 /// @param Rml マイナス入力のGND側抵抗値
Dance 0:de885a6da962 133 /// @param Rru リファレンス入力のVcc側抵抗値
Dance 0:de885a6da962 134 /// @param Rrl リファレンス入力のGND側抵抗値
Dance 0:de885a6da962 135 RatioMetric7714::RatioMetric7714(double Rpu, double Rmu, double Rml, double Rru, double Rrl)
Dance 0:de885a6da962 136 {
Dance 0:de885a6da962 137 af = 1 << bits;
Dance 0:de885a6da962 138 rpu = Rpu; rmu = Rmu; rml = Rml; rru = Rru; rrl = Rrl;
Dance 0:de885a6da962 139 }
Dance 0:de885a6da962 140
Dance 0:de885a6da962 141 /// 与えられたADC値をレシオメトリックにより抵抗値に変換する
Dance 0:de885a6da962 142 /// @param int adVal AD変換値
Dance 0:de885a6da962 143 /// @return 変換さた抵抗値
Dance 0:de885a6da962 144 double RatioMetric7714::toResistorValue(int adVal)
Dance 0:de885a6da962 145 {
Dance 0:de885a6da962 146 return -((rpu*(2*adVal*(rml + rmu)*rrl + af*(-(rmu*rrl) + rml*rru)))
Dance 0:de885a6da962 147 /(2*adVal*(rml + rmu)*rrl - af*(rml*rrl + rmu*(2*rrl + rru))));
Dance 0:de885a6da962 148
Dance 0:de885a6da962 149 }
Dance 0:de885a6da962 150
Dance 0:de885a6da962 151 /// 現在のADC値を抵抗値に変換して返す
Dance 0:de885a6da962 152 /// @return 測定された抵抗値
Dance 0:de885a6da962 153 double RatioMetric7714::getResistorValue(void)
Dance 0:de885a6da962 154 {
Dance 0:de885a6da962 155 return toResistorValue(getValue());
Dance 0:de885a6da962 156 }