ちょっと表示の怪しいアナログメータ持った安定化電源があります。電圧を調整するたびにテスターを当てており大変面倒です。勉強を兼ねてPICを使ったデジタル電圧計を取り付けることにしました。
カソードコモンの7セグを使用、ドットを含めB0〜7に割り当てます。A1〜3はコモンでトランジスタをドライブします。この回路は、7セグを一桁ずつ時分割し高速に点滅させることで3桁表示を実現するものです。ダイナミックドライブと呼ばれます。
◆デジタル電圧計作り(ソフト編)
ソフトはC言語を使って作成します。CCSのCコンパイラを使用します。タイマー割り込みを使用して約4.7msec単位に表示を切り替えます。3桁を有効活用するために10V未満の場合は、小数点以下2桁を表示できるようにしました。
◆ソフト作りで嵌ったところ
初心者ゆえに嵌ってしまったことが一点あります。CCSのコンパイラ固有の仕様でoutput_a(a[cc])を行うとAN0にLowが出力されてしまい、ADの入力インピーダンスが100Ω程度になってしまう現象に悩まされました。#use fast_io(a)を入れることで解決します。この宣言を入れないとset_tris_a(0x01)の指定がoutput_a(a[cc])でset_tris_a(0)に戻ってしまうのです。参考までにソースコードを公開します。
#use fast_io(a)
#use fast_io(b)
int16 c=0;
/*
_
|_|
|_|.
000
1 7
666
2 4
333 5
*/
char pat(int8 _n)
{
switch(_n)
{
case 0: return 0x9f;
case 1: return 0x90;
case 2: return 0xcd;
case 3: return 0xd9;
case 4: return 0xd2;
case 5: return 0x5b;
case 6: return 0x5f;
case 7: return 0x91;
case 8: return 0xdf;
case 9: return 0xd3;
}
return 0;
}
// ポートAの値を決める配列
const int a[3]={2,8,4};
// 桁の値を求めるための除数の配列
const int div[3]={1,10,100};
// ドットの位置を決める配列
int dot[3]={0,0x20,0};
// 表示桁を決めるためのカウンタ
int col=0;
// 4.7msec間隔のタイマー
#int_TIMER0
void TIMER0_isr()
{
int cc;
cc=(col++)%3;
output_b(pat((c/div[cc])%10)|dot[cc]);
output_a(a[cc]);
set_timer0(210); // 102.4*(256-210) = 4710.4(usec)
}
void main()
{
float val;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
// 1/10MHz*4*256=102.4(usec)
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
setup_oscillator(False);
set_tris_a(0x01);
set_tris_b(0);
output_a(0x0);
output_b(0x0);
set_adc_channel(0);
delay_ms(1);
while(1)
{
// フルスケールが21Vになるように計算
val = (float)read_adc() * (210.0 / 1023.0);
if(val<100)
{ // 10V未満の場合は値を10倍しドットの位置を左に移動
dot[2]=0x20; dot[1]=0;
c = (int16)(val*10.0);
}else{
dot[2]=0; dot[1]=0x20;
c = (int16)(val);
}
delay_ms(100);
}
}
安定化電源のアナログメータを取り外しデジタル電圧計を埋め込みます。手持ちのマルチメータとの誤差も10mV程度でAD変換の直線性も良いみたいです。リファレンス電圧はPICの電源と共有で5Vのレギュレータを使用しています。そのためか、若干の温度ドリフトが感じられますが、実用上まったく問題ありません。