google-site-verification: google3bd66dd162ef54c7.html

ArduinoのCPU温度センサーの値を読む

 Arduino UNOのCPUであるAtmega328Pのデーターシート(和訳版)を読んでいたら、ADコンバーターの入力セレクターに面白い信号が接続されていることに気付きました。

▼ADCのブロック図 Atmelのデータシートの日本語翻訳版から転載しています
AtmegaのADCブロック図
 左の緑の枠内に注目。1.1V内蔵基準電圧と温度感知器(ADC8)の値が読めるようになっています。

▼指定方法
ADCMUXレジスタ

 ADCMUX(ADCマルチプレクサレジスタ)の下位4ビットで入力切替が出来るようになっていて、温度感知器は0b1000、1.1VのVrefは0b1110を指定すれば読めます。なお、このレジスタの上位はADCのVrefの切り替えなどに使われています。

 それならということで、まずはダメ元でanalogRead(8)とかanalogRead(14)とやって読み出しを試みるとコンパイルエラーになります。Arduino UNOにそんな番号のポートは無いので当然の結果でしょう。どこかの定義ファイルをいじればanalogReadで読めるようになる気もしますが、後で変なことが起きちゃいそうです。

 そこでプログラムでCPUのレジスタを操作して読み出すことにします。

 今回の記事では温度センサーの値を読んでみます。

 温度センサー読み取りのデモプログラム
/*
 CPU内蔵温度計の読み出し
 2014/7/16
 ラジオペンチ http://radiopench.blog96.fc2.com/
 */

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  Serial.begin(9600); 
  lcd.begin(16, 2);
  lcd.print("Starting...");
  delay(1000);
}

void loop() {
  long sumd=0;
  float temp;
  adcSetup(0xC8);                         // ADC初期設定
  for(int n=0; n < 1000; n++){
    sumd = sumd + adc();                  // adcの値を読んで積分
  }
  temp = (sumd * 1.1 / 1024.0) - 336.5;   // 温度に換算(1mV=1℃)
  Serial.print("Temp = ");                // シリアルに温度を出力
  Serial.println(temp);
  lcd.setCursor(0, 0);                    // 液晶に温度表示
  lcd.print("Temp = ");
  lcd.print(temp,1);                      // 小数点以下1桁表示
  lcd.print("  ");                        // ゴミ消し
  delay(100);
}

unsigned int adc(){                       // ADCの値を読む
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);                 // AD変換開始
  while(ADCSRA & ( 1 << ADSC) ){          // 変換完了待ち
  }
  dL = ADCL;                              // LSB側読み出し 
  dH = ADCH;                              // MSB側
  return dL | (dH << 8);                  // 10ビットに合成した値を返す
}

void adcSetup(byte data){                 // ADコンバーターの設定
  // data -> ADMUX                       
  // input select
  //0bxxxx0000 A0
  //0bxxxx0001 A1
  //0bxxxx0010 A2
  //0bxxxx0011 A3
  //0bxxxx0100 A4
  //0bxxxx0101 A5
  //0bxxxx1000 Temp Sensor  <-- 温度センサー  
  //0bxxxx1110 1.1V Vref    <-- 内部1.1V基準電圧
  // Vref select
  //0b00xxxxxx Ext
  //0b01xxxxxx AVcc
  //0b10xxxxxx Reserve
  //0b11xxxxxx Internal 1.1V

  ADMUX = data;                           // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);                 // ADC イネーブル
  ADCSRA |= 0x07;                         // AD変換クロック CK/128
}
 このプログラムはArduinoとIDEさえあれば液晶が無くても動きます。ぜひ試してみてください。

▼液晶シールドとUSBバッテリーで駆動
液晶シールドで動かす
 こんなことも出来ます。

 データーシートによると、CPU内蔵の温度センサの感度はおよそ1mV/℃。室温付近だと300mV程度の値になり、個体によって±10℃くらいのばらつきがあることになっています。プログラムの24行目の -336.5という値は各自で修正が必要になります。

 ということで、外付け部品はおろかI/Oポートすら使わずに温度測定が出来るようになりました。

 測定した温度にはCPUの発熱などの影響が加わっているため、正確な気温の測定は難しいと思います。また、本物の温度センサーと比べると精度やレスポンスなども劣っているはずです。
 でもプログラムを書くだけでおよその温度が判るのはすごく便利なので、今後何かを作る時に利用してみたいと思います。

 次回の記事では、内蔵の1.1VのVref電圧の測定機能の使い道について書いてみたいと思います。それとせっかく判った面白い機能なのでもっと使い易い関数の形に仕上げてみたいと思います。

 この記事の続編はこちら。プログラムの修正版もあります
関連記事

tag : ATmega328P ADコンバーター

コメントの投稿

管理者にだけ表示を許可する

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード