AVR で A/D 変換その2

「AVR で A/D 変換その1」では、リファレンス電圧として Vcc そのまま Aref に入力して基準電圧としていました。そのため、出力値のふらつきが大きいです。今度は基準電圧を「シャント・レギュレータ」で作り(2.5V)、それを Aref に入力します。なお測定対象は内部基準電圧1.1Vのままです。この場合、出力値は (1.1/2.5*1024)=450 が想定されます。

「シャント・レギュレータは」『昼夜逆転』工作室さんのページで初めて耳にする素子でした。3端子レギュレータと同じように安定した電圧を出力しますが、電流を実際にとる目的ではなく、このA/D変換のように、精度の高い「基準電圧が欲しい」ときに使うもののようです。秋月のTL431ACZ が10個100円と安かったので、これを使います。回路は『昼夜逆転』工作室さんのページにあるように、カソードとRefを直結し、Vcc の入力側に 1KΩを接続します。

これを AREF 21番ピンの入力にするだけですが、劇的に値が安定します!!

画像

値は 430 台になり、計算値と合いません。なぜか。。不明です。が、値そのものは安定しているのでよしとしておきます。

コードは前回と同じです。

//

//試しながら学ぶAVR入門

//WinAVR A-Dテストプログラム prg0501.c より

// [Current Configration Options]に mega88 を設定すること

// コンパイラオプション:最適化なし -O0

#define F_CPU 1000000UL //1MHz

#include

#include

#include "7seg.h"

void wait( unsigned char );

void segout2( int );

unsigned char segdat[10]={0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,

0b01101101, 0b01111101, 0b00100111, 0b01111111, 0b01100111 };

int main( void )

{

initled();

int n,i;

ADCSRA = 0b10000100; // ADイネーブル

// | +++-------1/16クロック,1/16=62.5kHz。1/128で最遅7.8125KHz。これでも電話音声程度なら十分。

// +--------------ADイネーブル

ADMUX = 0b00001110; // 基準,入力選択

// || ++++-------内部1.1V選択

// |+------------右そろえ

// +-------------基準電圧の内部接続切り,Arefピンの電圧を使う

wait(2); // マルチプレクサが安定するまで待つ

while ( 1 ) { // 無限ループ,周期約1秒 

ADCSRA = 0b11000100; //(クロック変更の場合こちらも変更必要)

// +---------変換開始

while( ADCSRA & 0b01000000 ) // 変換終了待ち

;

n = ADC; // 2回読み出しに展開される

for( i =0 ;i < 200;i++){ // 3桁表示

//segout2( n );

display(n);

seg_n = (seg_n + 1) % 4;

wait(2); // 約5ミリ秒

//つまりこの for ループで1秒になるので、AD変換値取得の分解能も1秒となる。

}

}

}

void segout2( int i )

{

unsigned char j,x;

static unsigned char cir=0;

PORTC = PORTD =0;

if( cir == 0){

PORTB = 0b00000001; // 1の桁点灯

j = i % 10;

}

if( cir == 1){

PORTB = 0b00000010; // 10の桁点灯

j = (i / 10 )% 10;

}

if( cir == 2 ){

PORTB = 0b00000100; // 100の桁点灯

j = (i / 100 )% 10;

}

x = segdat[ j];

PORTC= x & 0b00001111; // ポートCに出力

PORTD= x & 0b11110000; // ポートDに出力

cir++;

if(cir == 3)

cir = 0;

}

void wait( unsigned char time ) // 2500クロック単位のwaitルーチン

{

unsigned char j,k;

for( j= 0;j< time ; j++)

for( k = 0; k < 250; k++) // 10 * 250 = 2.5 msec

; // WinAVR 20070525の場合,

// 最適化なしで,6命令10クロック

}

ここで、AD変換周期をためしに変えて実験してみます。AD変換周期は1秒間に何回サンプリングするか、を指定するもので、変換する対象信号の周波数が高ければ高いほど、変換周期も高くする必要があります。標本化定理で検索すると詳しくわかります。

デフォルト:

ADCSRA = 0b10000100; 1/16=62.5KHz

最遅:

ADCSRC = 0b10000111; 1/128=7.8125KHz

というわけで、一番遅いクロックを指定しても、CPUスピード=1MHz の場合は約8キロヘルツでサンプリングされます。これは、半分の 4KHz までの信号をサンプリングできる、ということになるので、電話音声程度までの品質ならAD変換ができるということになります。

私の当面の目標は、電灯線の電力測定なので、50Hz 程度は余裕です。(高調波の観測は制限がありそうですが。) 

ちなみに、上記のように変換周期を両方で試してみましたが、今回は内部基準電圧を測定しているので、値は変わりませんでした。