AVRを使ったコンデンサーESRメーターの製作

[公開:any]

[電子工作/AVR]
[電子工作/測定器]
[AVR,ATmega88,ICL7660,LCメーター,容量計,測定器]

origin 2010-07-08


 「3端子レギュレータを使ったトラッキング電源の製作」の最後に劣化した(・・と思われる)電解コンデンサを容量で比較してみましたが、いつもこのWebサイトをご覧になっている方から、「コンデンサの優劣判別はESRメーターが便利」とのご指摘をメールにて頂きました。ついでにWebでの参考になるリンクを紹介していただきました。
 ESRメーターについて、あちこちのWebサイトを見たのですが、動作原理の説明や再現性のよさそうな回路を公開されているBob's blogさんの「Experiments of ESR(Equivalent Series Resistor) meter with PIC16F819」を参考に・・・・というか、ほぼそのまま作成することにしました。

ESR meterの開発

 Bob's blogさんも整流回路をいろいろと試行されています。ダイオードを利用した全波整流では、ESRが大きくなると誤差が大きくなります。
 オペアンプを利用した理想ダイオードの回路等も同じように試してみたのですが、100KHzという比較的高い周波数を整流するのは難しそうです。オペアンプにLMC6482を使用した回路では、20KHz程度でスルーレート不足となって出力波形がひずみます。手持ちの2回路入りオペアンプを片っ端から試したのですがうまくいきませんでした。オペアンプに高スルーレートでバンド幅の大きなものを利用する必要があります。

理想ダイオードのスルーレート不足波形

 結局、オペアンプによる増幅+ダイオード全波整流で作成することにしました。使用するダイオードは、小信号用ダイオードの1S1588と小信号用SBD(ショットキー・バリア・ダイオード)の1SS108をLTspiceでシミュレーションして比較してみました。信号が小さいとき(・・つまりESRが大きいとき)の直線性が良い1SS108を使用することにしました。

ダイオード整流回路比較

 交流測定信号の周波数は、他のESRメーターで採用されている100KHzとしました。オペアンプを利用してウィーンブリッジ発振回路よりひずみが小さいといわれるブリッジドT型発振回路を使用しました。実測では96KHzの発振となりました。オシロスコープのFFTからもきれいな正弦波が確認できました。

ブリッジドT発振回路出力波形

CH1がブリッジドT型発振回路出力。CH2がオペアンプ増幅出力

 測定端に挿入する高圧カット用のコンデンサは、耐圧の関係から手持ちのメタライズド・フィルムコンデンサを利用します。最初は0.22uFを使用していたのですが、ESRが4Ω近くあって高ESRコンデンサ測定時には合計抵抗値が大きくなり、結果としてESRの測定誤差が大きくなりました。できれば1uF以上の大きなものを使用したほうが測定誤差を減らすにはよさそうです。

メタライズドフィルムコンデンサ

参考までに、完成したESRメーターで手持ちのメタライズド・フィルムコンデンサのESRを測定してみると、2.2uFが0.16Ω、1uFが0.41Ω、0.68uFが0.62Ω、0.1uFが12.46Ωとなりました。


 回路図です。Bob's blogさんのとほぼ同じ構成です。マイコンはAVRのATmega88Pを使用します。当初、負電圧生成にスイッチドキャパシタ電圧コンバータICのICL7660を使用したのですが、出力容量不足で整流前の増幅で波形ひずみが大きくなりました。波形ひずみの増大は、結果として測定誤差を大きくします。急遽、秋月電子でICL7660の高出力版であるLT1054CN8を調達して置き換えました。これでもオペアンプで増幅率を大きくとると波形がひずむので、Max2.5Vになるように増幅率を5倍程度としました。AD変換のリファレンスも2.5Vとして10ビットがフルに利用できるようにしました。

ESR meter回路図

 基板への実装図です。部品数が多いのでかなりタイトです。秋月電子のポリカーボネートケース中サイズに入れるために共立オリジナルのユニバーサル基板を使用しています。+5Vの3端子レギュレータの電源も含めました。入力にはブリッジを入れて外部電源ソースの±がどちらでも対応可能としています。

ESR meter基板実装図

 測定端のコンデンサやダイオードは基板外でもよかったかもしれません。スイッチはLED内蔵のプッシュスイッチを基板上に実装しました。オペアンプは秋月電子で4個200円のNJM072Dを使用しましたが、JFET入力タイプならなんでもOKです。

ESR meter基板裏ESR meter基板表

 ケースに入れました。測定は、最初にリードをショートして測定ボタンを長押し、リードを含めた抵抗値を測定するキャリブレーションを実行します。キャリブレーションが完了するとプッシュスイッチのLEDが点灯します。

ESR meterキャリブレーション

 直流抵抗と交流抵抗は厳密には異なると思いますが、電流検出用の高精度チップ抵抗40mΩを測定してみました。数回測定すると、たまに0.03Ωとなりますが、ほぼ正確な0.04Ωを表示します。なお、10ビットのAD変換値からの計算値なので、最小解像度はもっとも小さくても12mΩ程度となります。0.1Ωのメタルクラッド抵抗も直流抵抗値と同じ値が測定できます。

ESR meter測定風景1ESR meter測定風景2

 数Ω以上の大きな抵抗では誤差が大きくなるはずです。ためしに普通のカーボン抵抗を測定すると、10Ωの抵抗では10%以上も大きな値が表示されます。L成分による抵抗の増大なのかもしれませんが、絶対値測定ではないことに注意が必要です。

ESR meter測定風景3ESR meter測定風景4

 電源の逆接で高温発熱したコンデンサと正常なものを比較してみました。容量の低下(1048uF→920uF)も見られますが、ESRも若干大きく(0.10Ω→0.16Ω)なっています。

ESR測定1ESR測定2

 小容量フィルムコンデンサなどはESRが大きいので測定できません。プログラムでは20Ω以上をエラー処理しています。

ESR meterエラー表示

 交流の小信号による測定なのでインサーキット測定が可能です。対象装置の電源を落とした状態で測定しますが、チャージされたコンデンサの測定は注意が必要です。測定端に入れたコンデンサの耐圧を超えなければ大丈夫だと思いますが、真空管回路などの高電圧回路を測定する場合は、別途放電リード(抵抗内蔵リード)で放電後に測定するのが安全でしょう。

ESR meterインサーキット測定

 ブレッドボードでの回路実験に使用している電解コンデンサを測定しました。古いものや電源の逆接で性能劣化したものが含まれるため代表値ではありません。Bob's blogさんのサイトからリンクされているESR標準値と比較してみました。容量の小さなコンデンサは、やや低い値が表示されますが、おおむね問題なさそうです。

capacitance ESR[Ω] note
0.47uF/50V 3.94
1uF/50V 2.84
2.2uF/50V 1.81
4.7uF/50V 1.64
10uF/25V 1.21
10uF/16V 4.83 小型
22uF/50V 1.71
47uF/25V 0.92
100uF/16V 0.68
100uF/25V 0.31 電源用低ESR
220uF/25V 0.36
470uF/10V 0.19
1000uF/25V 0.13
2200uF/35V 0.06
3300uF/50V 0.03

 積層セラミックコンデンサも測定してみました。積層コンデンサは周波数によってESRが大きく変化すると聞いているので測定自体にあまり意味はありません。ただ、同容量の電解コンデンサよりは低いESRが測定できました。

capacitance ESR[Ω] note
0.1uF 15.20
0.1uF 13.36
0.47uF 1.22
1.5uF 0.20
4.7uF 0.13
10uF 0.10
100uF 0.03

 コンデンサー容量計と組み合わせて使用すれば、コンデンサの良否判別には問題なく使用できると思います。また、インサーキット測定は、電解コンデンサ劣化による機器の故障時に役に立つでしょう。

 AVRのプログラムソースです。AVRStudio + WinAVRで開発しました。プッシュボタンを押すと測定します。電源投入時は、測定リードをショートした状態でプッシュスイッチを長押し(2秒程度押し続ける)してキャリブレーションする必要があります。このキャリブレーションで測定用リードや高圧カット用コンデンサを含めた抵抗分を測定し、実測時に減算しています。キャリブレーションが完了していない状態ではエラーを表示し測定することができません。なお、ESRの計算方法はBob's blogさんを参考にAD変換値をそのまま計算に使用する方法としました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**********************************************************************
    ESR Meter
        AVR: atmega88p
    2010.06.17 www.henteko.org
**********************************************************************/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <math.h>

#include "lcd.h"

#define cbi(addr, bit)     addr &= ~(1<<bit)
#define sbi(addr, bit)     addr |=  (1<<bit)

#define ADC_ENABLE (_BV(ADEN)|_BV(ADIF)|0b110)
#define ADC_START  (ADC_ENABLE|_BV(ADSC))

#define RC 9.938        // RC 10Ωの実測値
//#define DEBUG

FILE *fp;                            // File descriptor for LCD

/**********************************************************************
    milisecond order delay
***********************************************************************/
void delay_ms(unsigned int t) {    while(t--)  _delay_ms(1); }

/**********************************************************************
    AD convert
***********************************************************************/
unsigned int get_adc(unsigned char ch)
{
    ADMUX = ch;
    ADCSRA = ADC_START;
    loop_until_bit_is_set(ADCSRA, ADIF);
    return ADCW;
}


/**********************************************************************
    main routine
**********************************************************************/
int main(void)
{
    unsigned char sw0_state;
    double Zo;
    unsigned int E, Ec;
    unsigned int org;
    unsigned int tim;

     DDRB = 0b11111111;        // LCD
    DDRC = 0b00000000;        // A/D input 
    DDRD = 0b00001000;        // PD4 SW input

    PORTD = 0b00010000;    // PD4 pull up
    DIDR0 = 0b11111111;

    ADCSRA = ADC_ENABLE;

    lcd_init();
    lcd_cls();
    fp = fdevopen(lcd_putch, NULL);        // Open File descriptor for LCD
    lcd_goto(0, 0);
    fprintf(fp, "ESRmeter");

    sw0_state = 0;
    org = 0;
    tim = 0;

    while(1) {
        if(bit_is_clear(PIND, PD4)) {
            sw0_state = 1;            
            delay_ms(25);
            tim++;
        }
        if(sw0_state && bit_is_set(PIND, PD4)) {
            sw0_state = 0;
            tim = 0;
            if(org == 0) {
                lcd_goto(0, 0);
                fprintf(fp, "ESRmeter");
                lcd_goto(1, 0);
                fprintf(fp, "CalError");
                continue;
            }
            delay_ms(500);
            E = get_adc(5);
            delay_ms(200);
            Ec = get_adc(4);

            Zo = RC * (E - Ec - org) / Ec;
            if(Zo > 20.0) {
#ifdef DEBUG
                lcd_goto(0, 0);
                fprintf(fp, "%4d:%3d", E, Ec);
#endif
                lcd_goto(1, 0);
                fprintf(fp, "MesError");
                continue;
            }
            lcd_goto(0, 0);
#ifdef DEBUG
            fprintf(fp, "%4d:%3d", E, Ec);
#else
            fprintf(fp, "ESRmeter");
#endif
            lcd_goto(1, 0);
            fprintf(fp, "%7.2f%c", Zo, 0xf4);
        }

        if(tim > 60) {        // Calibration
            sw0_state = 0;
            tim = 0;
            lcd_goto(1, 0);
            fprintf(fp, "Cal.....");
            loop_until_bit_is_set(PIND, PD4);
            delay_ms(500);
            E = get_adc(5);
            delay_ms(200);
            Ec = get_adc(4);
            org = E - Ec;
            if(org > 400 || org < 10) {        // calibration error
#ifdef DEBUG
                    lcd_goto(0, 0);
                    fprintf(fp, "%4d:%3d", E, Ec);
#else
                    lcd_goto(0, 0);
                    fprintf(fp, "NotShort");
#endif
                lcd_goto(1, 0);
                fprintf(fp, "Re Exec ");
                org = 0;
                cbi(PORTD, PD3);
                continue;
            }
#ifdef DEBUG
            lcd_goto(0, 0);
            fprintf(fp, "%4d:%3d", E, Ec);
            lcd_goto(1, 0);
            fprintf(fp, "%8d", org);
#else
            lcd_goto(0, 0);
            fprintf(fp, "ESRmeter");
            lcd_goto(1, 0);
            fprintf(fp, "Cal OK  ");
#endif
            sbi(PORTD, PD3);
        }

    }
}

▲ページ Top へ...