まごころせいじつ堂

浜町庄金 研究開発  マイコンで遊んでばっかりで

温度センサ

温度センサLM35DZを複数Arduinoに繋いだ時のトラブル

※プログラムに誤りがありました。ADC0〜ADC5までなのにADC6相当を読んでいた。
続き↓
LM35DZを複数つないだ時の問題 お詫びとハードでの解決


環境:
Arduino UNO R3,Leonardo / IDE 1.0.1

 前回、LM35DZの動作確認をしたのでArduinoのアナログポートに複数個接続してみた所、測定値が時々跳ね上がる現象が発生。
LM35DZはA0〜A5に約50cmのケーブルで接続。パソコン筐体内の複数箇所の温度を測定するつもりで作った。

温度センサを同じ所にまとめて動作確認をした時に以下の現象が発生。

現象:時々、A0ポートに接続したLM35DZが6℃、A5ポートに接続したのが330℃を表示。測定間隔は約1分。
最初、Arduino Leonardo(ATmega 32U4)で確認したがArduino UNO R3(ATmega328)でも再現。こちらで調査開始。
アナログポートに接続したLM35DZを入れ替えても現象同じ。センサ個別についてまわる問題ではない。

 以前見かけたこの記事が詳しい。これに当たったようだ。これがなければわからなかっただろう。

// LM35DN x6 Thermal Logger

// http://arduino.cc/en/Reference/AnalogReference

unsigned int t,c;
float sc;
unsigned long time;
#define NUM_LM35 6
int LM35[NUM_LM35];
int Shuffle[NUM_LM35] ; // shuffle LM35 port 0-5 

// initialize the library with the numbers of the interface pins
///LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

float temp5v(int ain) {  // analog 0-1023 10mV/Celsius ,5V*100/1024
  return ain*5.0*100/1024;
}

float temp3v3(int ain) {  // analog 0-1023 10mV/Celsius,3.3V*100/1024
  return ain*3.3*100/1024;
}

float temp2v56(int ain) {  // analog 0-1023 10mV/Celsius,2.56V*100/1024
  return ain*2.56*100/1024;
}

float temp1v1(int ain) {  // analog 0-1023 10mV/Celsius,1.1V*100/1024
  return ain*1.1*100/1024;
}

void setup() {
  // set up the LCD's number of columns and rows: 
  // lcd.begin(16, 2);
  Serial.begin(9600);
  // External Aref(3.3V)
  // analogReference(EXTERNAL);//3.3V
  // Internal Aref(1.1V) ATmega328 ???
  analogReference(INTERNAL);
/*
  Shuffle[0]=A0;
  Shuffle[1]=A1;
  Shuffle[2]=A2;
  Shuffle[3]=A3;
  Shuffle[4]=A4;
  Shuffle[5]=A5;
*/
/*
  Shuffle[0]=A4;
  Shuffle[1]=A2;
  Shuffle[2]=A5;
  Shuffle[3]=A0;
  Shuffle[4]=A3;
  Shuffle[5]=A1;
*/
//  for (int i=0; i<=NUM_LM35;i++) LM35[i]=Shuffle[i] ;
/*
  LM35[0]=A0;
  LM35[1]=A1;
  LM35[2]=A2;
  LM35[3]=A3;
  LM35[4]=A4;
  LM35[5]=A5;
*/
  LM35[0]=A4;
  LM35[1]=A2;
  LM35[2]=A5;
  LM35[3]=A0;
  LM35[4]=A3;
  LM35[5]=A1;
}

void loop() {
    time=millis();Serial.print(time);Serial.print(" ");

    for(int i=0;i<=NUM_LM35;i++) {
      t=analogRead(LM35[i]); // (0...1023)
      sc=temp3v3(t); // Selcius
      // Serial.print(sc);
      // Serial.print(":");
      Serial.print(t);
      if (i<NUM_LM35) Serial.print(" ");
      delay(100);
    }
    Serial.println("");
    delay(60000); // 1000
} 
(1)A/Dコンバータ(ADC)のリファレンス電圧による違い→ 3.3Vより1.1Vの方が発生頻度が上がる
analogReference(EXTERNAL); // 3.3VをAREF端子に接続
analogReference(INTERNAL); // 1.1V内部リファレンス

(2)測定間隔による違い→1分間隔よりも1秒間隔の方が頻度が下がる(が発生)

(3)チャネルによる違い
A0,A1,A2,A3,A4,A5の順にリード→ A0で少し下がり、A5で大きく跳ね上がる
A4,A2,A5,A0,A3,A1の順にリード→ A4で少し下がり、A1で大きく跳ね上がる
つまり、ポートに関係なく読み出し順の最初と最後で異常。

(4)チャネルによる違いその2
  Shuffle[0]=A4;
  Shuffle[1]=A2;
  Shuffle[2]=A5;
  Shuffle[3]=A0;
  Shuffle[4]=A3;
  Shuffle[5]=A1;
  for (int i=0; i<=NUM_LM35;i++) LM35[i]=Shuffle[i] ;

として analogRead(LM35[i]);とやってみたら再現しなくなった。Shuffle[i]に代入するポート番号をA0〜A5に整列させても発生しない。

ATmega32U4のデータシートを見てみると、ADCの実体は1つで入力ポートを切り替えている。

きょうはここまで。

LM35DZによる温度測定とanalogReference()

LM35DZという三端子の温度センサを使ってみた。
高精度IC温度センサ LM35DZ 0~100℃ [秋月電子]
【LM35DZ-N】高精度・摂氏直読温度センサーIC [マルツ]
 1℃あたり10mVの出力で、外付け部品なしの測定範囲は+2℃〜。Arduinoだとアナログ入力が使える。
作例はたくさんあるのでLCDに表示してみた。つかったのはLCDシールド
2012LM35DZ

ソースはこちら。https://gist.github.com/3724141 
→ https://gist.github.com/3725477

※A/D入力を℃に変換する箇所:ain*330/1024を修正。(ドライヤーで温めたらマイナス表示になってしまった)
float temp3v3(int ain) { // analog 0-1023 10mV/Celsius,3.3V*100/1024
  return ain*3.3*100/1024;
}



 今回使用したのはArduino UNO R3とArduino IDE1.0.1。A/Dコンバータの基準電圧に外部3.3Vを使用している。AREFピンと3V3ピンを接続し、スケッチ内でanalogReference(EXTERNAL); と指定した。

 ここでちょっと引っかかったのがanalogReference(INTERNAL)の指定。
http://arduino.cc/en/Reference/AnalogReference
これによるとATmega328でINTERNAL指定すると基準電圧は2.56V1.1Vになるらしいのだが、指定してみたらどうも3.3Vみたい。AREFピンに3V3を接続していたが、これを外すと値がおかしくなる。INTERNAL指定のままでAREFを5Vに接続したらそれが基準電圧みたいな動作をする。
Arduino UNO R3/Arduino IDE1.0.1ではINTERNAL指定もEXTERNAL指定も同じみたいだ。 

追記:MacOSXのArduino IDE1.0 と 0023でも同じだった。
解決:INTERNAL指定の時はAREFをつないじゃいけない。

ATmega328Pのデータシート、p.251 Figure 23-1. Analog to Digital Converter Block Schematic OperationをみるとA/Dコンバータの基準電圧はAREF端子に直に出ているので、INTERNALで1.1V指定していてもここに3.3Vをつなぐとそっちが勝つ。
 
記事検索
プロフィール

hardyboy

カテゴリ別アーカイブ
月別アーカイブ
QRコード
QRコード
  • ライブドアブログ