PIC microcontroller用交流電流センサー

戻る一つ前のメニューに戻る

目次

ソースコード

  • 開発言語 Microchip XC 8
  • ターゲットMPU Enhanced Mid-Range 12F1822, 12F1827等

Subversion ブラウザでソースコードを参照する

交流電流センサー CT

ct-6ph.jpg

AC電流測定用の変流器を用いて、PICでAC電流を測る。この測定変流器は抵抗付きのものと、抵抗を自分で用意して取り付けなければならないものがある。日本の電子部品屋で売っているものは抵抗なしの変流器のみが多く、中国の商社から直接輸入する時は抵抗付きのものが多い。

今回はURD社のCTL-6-P-Hという小型変流器を用いた。どのような範囲の電流値でも測定したいため、可変抵抗器を取り付けている。なお、PIC microcontroller用センサー汎用ライブラリには、理想的な正弦波曲線で電流値が振幅する場合のプログラムを掲載したが、実際は次に示すような歪んだ電流波形の場合が多い。

ct-ammeter-v2-wave.jpg

こういう場合の電流値の求め方は、「瞬時の電流値を一定時間足し合わせた平均値」のほうがふさわしい。

サンプル回路図

ct-ammeter-v2-circuit.png

ct-ammeter-v2-board.png

BSch3V用回路図ファイルをダウンロードする, PasS用プリント基板ファイルをダウンロードする

ct-ammeter-v2-photo.jpg

ソースコード主要部

4秒毎に電流測定し、シリアル伝送するプログラム

main.c の処理主要部抜粋
// A/D サンプル数
#define AD_SAMPLE 2500
// データ送信の間の待ち時間(ミリ秒)
#define WAIT_MSEC 1510
// ステータスLED発光時間(ミリ秒)
#define STATUS_BLINK_MSEC 5
 
/* printf関数の出力先のスタブ関数を定義する */
void putch(unsigned char ch){
        rs232c_putch(ch);
        return;
}
 
void main(void) {
    // 基本機能の設定
    OSCCON = 0b01101010;        // 内部オシレーター 4MHz
    TRISA = 0b00101001;         // IOポートRA0(AN0),RA5(RX)を入力モード(RA3は入力専用)、RA1,RA2,RA4(TX)を出力モード
    APFCONbits.RXDTSEL = 1;     // シリアルポート RXをRA5ピンに割付
    APFCONbits.TXCKSEL = 1;     // シリアルポート TXをRA4ピンに割付
    ANSELA = 0b00000001;        // A/D変換をAN0を有効 AN1,AN2,AN4を無効
    PORTA = 0;
    ADCON0 = 0;                 // AN0選択, A/D機能停止
    ADCON1 = 0b10010000;        // 変換結果右詰, クロックFOSC/8, 比較対象VDD
 
    // 1秒待つ
    __delay_ms(1000);
    rs232c_init(9);             // init 9600bps
    TRISAbits.TRISA5 = 0;       // RA5(RX)は使わないので、消費電力低減のため出力モードにしておく
 
    while(1) {
        unsigned int value_max = 0, value_min = 0xffff;      // 検出電流の最大・最小値
        float value_sum = 0.0;              // 中間計算(合計値)
        for(unsigned int i = 0; i < AD_SAMPLE; i++){
            ADCON0bits.ADON = 1;            // A/D機能ON
            __delay_us(10);                 // A/D変換器チャージ時間待つ
            ADCON0bits.GO = 1;              // A/D開始
            while(ADCON0bits.GO_nDONE){}    // A/D変換完了を待つ
            unsigned int value = ADRESH << 8 | ADRESL;
            ADCON0 = 0;                     // AN0選択, A/D機能停止
 
            if(value > 512) value_sum += (value - 512);
            else value_sum += (512 - value);
 
            if(value > value_max) value_max = value;
            if(value_min > value) value_min = value;
 
            __delay_us(10);
        }
 
        // サンプル数で割って平均値を求める。なお、0 - 1024のレンジに調整するため、sin正弦波平均値2/piを考慮し、
        // 1024 / (512 * 2/pi) を調整する
        int value_average = (int)((value_sum / AD_SAMPLE) * (1024 / 325));
        // 効率。最大振幅の綺麗なsin波だった場合の平均値2/piで割る(実際は352で割ればよい)
        int value_efficiency = (int)((value_sum / AD_SAMPLE) / ((value_max - value_min)*0.3185) * 100);
        // Status LED ON
        PORTAbits.RA2 = 1;
        // データ送信 (to Serial)
        printf("%d,%d,%d,%d\r\n", value_min, value_max, value_average, value_efficiency);
        __delay_ms(STATUS_BLINK_MSEC);
        // Status LED OFF
        PORTAbits.RA2 = 0;
 
        // 2秒に1回データ送信する
        __delay_ms(WAIT_MSEC);
    }
}