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月号の記事および上記ファイル中のコメントを参照してください。
AD7714/AD7714.cpp@0:de885a6da962, 2014-08-29 (annotated)
- 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?
User | Revision | Line number | New 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 | } |