「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 程度は余裕です。(高調波の観測は制限がありそうですが。)
ちなみに、上記のように変換周期を両方で試してみましたが、今回は内部基準電圧を測定しているので、値は変わりませんでした。