安定化電源にPIC電圧計を

 ちょっと表示の怪しいアナログメータ持った安定化電源があります。電圧を調整するたびにテスターを当てており大変面倒です。勉強を兼ねてPICを使ったデジタル電圧計を取り付けることにしました。

◆デジタル電圧計作り(ハード編)

 10ビットADコンバータ内臓のPIC16F819と7セグLEDを使って3桁の電圧計を作成します。回路の主要な部分はこんな感じです。

 カソードコモンの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のレギュレータを使用しています。そのためか、若干の温度ドリフトが感じられますが、実用上まったく問題ありません。

 

 見た目もそんなにブサイクではありません。


Latest update at 2007/3/6