SSブログ

Arduinoのバンドギャップの読み出しエラーについて [ATmarquino Arduino]

arduino_003.png
arduino_004.png
このへんでバンドギャップの利用について書きました。

今回は基準電圧をVCC(電源電圧)として変換し、バンドギャップの値を読み出す事で正確な電源電圧を求め、更にアナログ入力0に入った別の電源系統の電圧を求めた電源電圧から算出すると言う処理をし、、、しようと思ったのですが何故か上手く行きません。さて、、、。



例えば以下の様なスケッチを作成してA/D変換した値をシリアルに出力してみます。
すると一枚目の図の様な結果となってしまいました。本来バンドギャップの値は1.1VなのでA/D変換の結果は341近辺である必要があります。ですが実際に読み出した値はその3倍近い値となってしまいました。
/*************************************************************************/
/* バンドギャップの値は読み出せるか?                                  */
/*                                  designed by hamayan since 2009/04/25 */
/*************************************************************************/
#define  BAND_GAP_CH  14
#define  ANALOG_CH_0  0
#define  ANALOG_CH_1  1
#define  ANALOG_CH_2  2
#define  ANALOG_CH_3  3

void setup()   //初期化
{
  pinMode( ANALOG_CH_1 + 14, OUTPUT );  //出力に設定
  pinMode( ANALOG_CH_2 + 14, OUTPUT );  //出力に設定
  pinMode( ANALOG_CH_3 + 14, OUTPUT );  //出力に設定
  digitalWrite( ANALOG_CH_1 + 14, HIGH );  //
  digitalWrite( ANALOG_CH_2 + 14, LOW );  //
  digitalWrite( ANALOG_CH_3 + 14, HIGH );  //

  Serial.begin( 38400 );  //ボーレートは38400bpsとする
}

void loop()  //ループとはなっているが、実際にはここを抜けてからまた戻っている
{
  volatile unsigned short an[4];
  volatile unsigned short gap;

  an[0] = analogRead( ANALOG_CH_0 );
  an[1] = analogRead( ANALOG_CH_1 );
  an[2] = analogRead( ANALOG_CH_2 );
  an[3] = analogRead( ANALOG_CH_3 );
  gap = analogRead( BAND_GAP_CH );

  Serial.print( "AN0=" );
  Serial.print( an[0], DEC );

  Serial.print( " AN1=" );
  Serial.print( an[1], DEC );

  Serial.print( " AN2=" );
  Serial.print( an[2], DEC );

  Serial.print( " AN3=" );
  Serial.print( an[3], DEC );

  Serial.print( " GAP=" );
  Serial.println( gap, DEC );

  delay(1000);//1秒待つ
}


ATmega168のA/D変換器は複数の入力チャンネルの変換を行う事ができますが、複数の入力毎に専用の変換器がある訳でなく、内部でアナログマルチプレクサ(アナログスイッチ)によって入力元を切り替えながら一つの変換器で変換を行っています。また変換中に入力レベルが変動する事を防ぐ為に変換器の直前にはホールドコンデンサが有ります。

複数の入力を切り替えながら使用した場合、スイッチの切り替え時に急に入力レベルが変動したり、場合によっては一瞬ですが、ホールドコンデンサから入力元に電気が逆流する可能性もあります。

こうした変動に対して入力元では出力インピーダンスを低くしてその変動の影響を最小限にしたりするのですが、どうやらそれがバンドギャップでは上手く行かなかったのでは?と想像できます。
つまりバンドギャップの値がANALOG_CH_3の値に影響を受けていると言う事です。

そこで暫定的な対策として一回ダミーの読み出しを行い、さらにちょっとだけ変換開始を遅らせて見ることにしました。
  gap = analogRead( BAND_GAP_CH );

を以下の様にしただけです。
  gap = analogRead( BAND_GAP_CH );  //ダミーの読み出し
  delay( 2 );  //遅延
  gap = analogRead( BAND_GAP_CH );

一回目のダミーの読み出しでスイッチを開き、レベルが安定した頃を見計らって二回目の変換結果を利用しています。
その結果が二枚目の図なのですが、かなり改善されている事が判ります。

そこで気になってArduinoのanalogReadライブラリを見てみました。wiring_analog.cに有ります。
int analogRead(uint8_t pin)
{
	uint8_t low, high, ch = analogInPinToBit(pin);

	// set the analog reference (high two bits of ADMUX) and select the
	// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
	// to 0 (the default).
	ADMUX = (analog_reference << 6) | (pin & 0x0f);

	// without a delay, we seem to read from the wrong channel
	//delay(1);

	// start the conversion
	sbi(ADCSRA, ADSC);

	// ADSC is cleared when the conversion finishes
	while (bit_is_set(ADCSRA, ADSC));

	// we have to read ADCL first; doing so locks both ADCL
	// and ADCH until ADCH is read.  reading ADCL second would
	// cause the results of each conversion to be discarded,
	// as ADCL and ADCH would be locked when it completed.
	low = ADCL;
	high = ADCH;

	// combine the two bytes
	return (high << 8) | low;
}

delay(1)がコメントアウトされています。同様の問題を意識してはいた様ですね。

※アナログ入力で原因不明の怪しげな現象に出くわしたら、ちょっとこの事も思い出してくださいね。

※山根さんは日本のAVR界の第一人者(日本にあまりAVRが普及していない頃、その普及の為に頑張っていた。)なので、以下の本はお勧めです。AVRで判らない事があった時に結構役に立ちます。




Arduinoをはじめよう

Arduinoをはじめよう

  • 作者: Massimo Banzi
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2009/03/27
  • メディア: 単行本(ソフトカバー)



アーデュイーノ互換マイコン・ボードを作る (プリント基板付き電子工作解説書シリーズ)

アーデュイーノ互換マイコン・ボードを作る (プリント基板付き電子工作解説書シリーズ)

  • 作者: 小坂 貴美男
  • 出版社/メーカー: CQ出版
  • 発売日: 2009/04
  • メディア: 単行本



nice!(0)  コメント(2)  トラックバック(0) 

nice! 0

コメント 2

noritan

バンドギャップにバッファがつながっていて、それが働いていない可能性はありませんか?

HCS08の場合、バンドギャップ出力を測定するためには、バッファアンプをイネーブルする必要があります。このアンプは、LVI機能のためにも使用されるので、イネーブルビットはLVIモジュールの近くにあります。

by noritan (2009-05-09 23:50) 

hamayan

おーそうそう、HCS08の場合はバンドギャップを有効にすると言うより、バンド
ギャップのバッファを有効にするのですからね。

AVRの場合はマニュアルのブロック図にも、レジスタの機能にもバッファの存在を見つけられません。
でマニュアルをよく読み直してみると保険の約款の様に以下の記述がありました。

When the bandgap reference voltage is used as input to the ADC, it will take a certain time for
the voltage to stabilize. If not stabilized, the first value read after the first conversion may be
wrong.

「AVRリマイコン ファレンス・ブック」は、著者の山根さんが日本でのAVR普及
の第一人者なのでかなり色々詳しく書いてあるのですが、今読み直したのですが、このバンドギャップのセトリングタイムについては書かれていませんね。

by hamayan (2009-05-10 07:45) 

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。