PICを使った電気柵用電源

PICを使った電気柵用電源

市販パーツで構成した電気柵用電源に関してはこちらに書いた。
電源部以外の電気柵に関すること、リークやイグニションコイルに関することも同ページを参照されたい。
その時にも触れたが、PICを使ったものを製作したのでまとめておく。

入手しにくいDC-DCコンバータ部のトランスは、中華HIDのバラストをバラして使った。
中華HIDを解体するとMOS FETもファストリカバリダイオードも、電解コンデンサも手に入る。

写真右は薄型のもの、左側はスタンダードサイズだ。
トランスはどちらも同じように見える。

充填されているのは発泡性のシリコンみたいな感じで、むしり取るように剥がすことが出来る。

FETもゲート電圧が5VでONになるものならそのまま使える。
このT428は5Vでは完全にONにはならなかった。
ドレイン耐圧は75Vである。

全体の回路は以下のようにした。
PICKIT3との接続用の配線もしてある。

FETのゲートに付けたLEDは、その点灯の仕方で動作が分かる。
ダイアグ用LEDは点滅回数で異常が分かるようになっている。

SCRは品番によってはゲート電流をかなり流す必要があり、エミッタフォロワを入れた。
コレクタを12Vのラインに接続したのは、下品な電流を5V系から取りたくなかったためである。エミッタフォロワなのでエミッタ電圧の最大値は5V弱にしかならない。
PICのソース電流は20mAなので、この電流でターンオン出来るSCRならばトランジスタは不用になる。
以前に使ったSCRは12Vから470Ωの抵抗でターンONさせる事が出来たので、約26mAである。

なお実験に使ったSCRは結構電流を流す必要があり、2SC2120のエミッタとSCRのゲート間に入っている抵抗は100Ωまで小さくする必要があった。

またSCRのアノードカソード間に0.1μFと22Ωを直列にしたものを入れた。
これはSCRに関係するものではなく、スイッチングノイズでPICのADCの読み取り値が安定しなかったからだ。

元の図は大きいのだが、WordPressに載せるとこのサイズになり、縦横比もおかしい。
画像を保存して別のビューワで見ると大きなサイズで見られる。

柵線電圧チェック用分圧器の10MΩの抵抗は高耐圧品を使わないと放電する。
一般抵抗1MΩの10本直列で使えているが、これでも耐圧は大幅に不足している。

分圧器が1/1000なので、柵線電圧が2.5kV以下では判定が出来ない。
柵線電圧は8kV程度必要と言われているのと、この回路でイグニションコイルを使うと10kVは超えるはずだ。

MOS FETは回路図の品番のものでは耐圧がギリギリなのでやめた方が良い。
手持ちの関係でこれを使ったが、新たに組むのならドレイン耐圧400V位のFETの方が安心出来る。
2SK3115あたりが使えるはずだ。

MOS FETの駆動周波数は100kHzで、デューティーは5%~20%の可変である。
2kΩのVR(R4)で出力電圧を300V~400Vに調整する。
いたずらに電圧を上げても要らぬ放電をするだけなので、電気柵用電圧計で柵の電圧を見ながら調整するのが良い。

OLYMPUS DIGITAL CAMERA

PICはPIC12F683を使った。
プログラムは以下の通りである。
PICのプログラムは初めて作ったので、要らぬヘッダファイルや要らぬ設定、冗長な部分、無駄なメモリの使用があると思う。

柵電圧をAD変換して読みたいところだが、端子の関係でレベル判定だけにしている。
DIAG LEDはPICKIT3の線とダブっているが、LEDの電流制限抵抗を大きめにしておけば、このままの回路で問題なく書き込みが出来る。
10kΩとジャンパは、PICKITを接続する時には10kΩでプルアップしろとなっているので付けた。
実際にはプルアップ無しでも書き込めた。

プログラムは非常に簡単なものである。
メインルーチンではDC-DCコンバータの出力電圧制御を行っている。
電圧が低い場合は通電時間を長くし、電圧が上がってくると5%までデューティーを下げ、規定電圧になったらFETドライブを止める。

青い線が高圧、水色の線がFETに流れる電流である。
デューティー20%の時には約1.3Aが流れ、デューティー10%で600mA程になり、ディーティー5%では約300mAに、その後は規定電圧に達してON/OFFを繰り返している。

青い線が0Vまで下がっていないのは、SCRが正しくターンオン出来ていない為だ。
SCRの通電時間は、プログラムで10msに変更した。

電圧検出抵抗で放電するので電圧が下がり、DC-DCコンバータは完全停止にはならない。
青い線が高圧、水色は(サンプリングレートの関係で正しい表示ではないが)FETのドライブパルスだ。

その後微調整を行いデューティー20%での動作はなくした。
全て5%でも良いが、チャージ時間が少し長くなる。
デューティー5%以下ではチャージ出来なくなった。

デューティー20%をなくしたことでピーク電流は減少した。
SCRの通電時間を長くしたので完全にONになっている。

SCRのトリガはタイマ割り込みで行っている。
割り込みは約10msごとに発生し、それをカウントする。
980ms時点でDC-DCコンバータをOFFにし、1000msの時点でSCRをトリガし、
1010msでSCRのゲート電圧をゼロにして電圧をチェックし、1020msでDC-DCコンバータの動作を再開する。

SCRのゲートは1ms程度Hレベルにすれば十分なので、10msはやり過ぎ(電流がもったいない)ではある。
割り込みタイミングを10msではなく1msごとにする手もあるし、10msのまま500μs割り込みを使ってゲート通電を切る手もある。
その500μs割り込みも、割り込みが不要な時は止めておいても良い。

今回は処理時間が空いているので無駄も沢山ある。

DC-DCコンバータの駆動パルスはPWMで出力しているので、プログラムが止まってもハードウエアが生きていれば、FETは駆動される。
ただしSCRがトリガされなければ高圧は発生しないので、連続的に高圧が柵線にかかりっぱなしになる可能性は低い。

PICのウォッチドッグタイマは有効化している。
割り込みルーチンとメインルーチンの両方が正しく動いていないとPICにリセットがかかる。

PICの近くで放電させたりするとノイズで簡単に暴走する。
DC-DCコンバータの駆動ノイズやSCRのトリガで暴走することはないが、放電によるノイズは強大である。

FETの駆動パルス幅は使用するトランスによって変える必要がある。
PWMの周波数とデューティーの調整だ。
トランスに品番が付いているものならまだしも、中華HIDのトランスを流用するわけだから、ものによる違いもある。

デューティーは小さめからテストしないとFETやトランスに過大な電流が流れる可能性もある。

DC-DCコンバータ用として規格のハッキリしたトランスも売られている
こうしたトランスを使う場合は、トランスに合わせてドライブ波形などを調整すれば良い。

柵線の状態のチェックはリンギングを見ている。
正常な場合の多くは下のような波形になる。

リンギングはイグニッションコイルによっても異なり、開磁路型のコイルだと2つめの山が出ない場合もある。
柵線のチェックは山の数を数えているので、使用するコイルや使用する柵線によって判定を変える必要があるかも知れない。
山の数はpulse_cnt変数に入っている。
柵線がオープンになると以下のような波形になることが多い。

LEDは正常動作の場合は点灯しない。
1回点滅なら柵線が断線している可能性を示す。
2回点滅なら柵線が短絡している可能性を示す。
3回点滅ならSCRがターンオンしていない可能性がある。
4回点滅ならDC-DCコンバータの出力電圧が規定値まで上がっていない。
5回点滅ならDC-DCコンバータの電圧が中途半端に上がっていて、SCRがターンオンしない可能性がある。
プログラムの最初にLEDを速く点滅させるルーチンがあり、ウォッチドッグタイマーなどが働いてリスタートを繰り返している場合は、LEDは速く点滅する。

スピーカを接続すれば、起動時とエラー発生時に音が出る。

/* 
 * File:   newmain.c
 * Author: F&F
 *
 * 
 */

#include <stdio.h>
#include <stdlib.h>
// PIC12F683 Configuration Bit Settings

// 'C' source line config statements

#include <htc.h>
// PIC12F683 Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = ON        // Watchdog Timer Enable bit (WDT Enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

#define         _XTAL_FREQ 4000000
#define         THRESHOLD   200
#define         THRESHOLD5   50
#define         THRESHOLD10  20

#define         DUTY1   0b00000101      // Duty 5%
#define         DUTY2   0b00001000      //
#define         DUTY3   0b00001010;     // Duty 10%

unsigned char   ledcount;
unsigned char   intcount;
unsigned char   intcount_old;
unsigned char   pwm_stop;
unsigned char   chg_ok;
unsigned char   dchg_ok;
unsigned char   pulse_ok;
unsigned int    avolt;
unsigned int    volt;
unsigned char   LED_stat;
unsigned char   adc_count;
unsigned char   init1;
unsigned char   toneh;
unsigned char   tonel;
unsigned char   beep;
unsigned char   wdtctl;
unsigned char   pulse_cnt;

void main(void)
{
        
    
    //クロック数(4MHz)
    IRCF2 = 1;
    IRCF1 = 1;
    IRCF0 = 0;
    //ピンの入出力(GPIO4(AN3)=IN/他は出力)
    TRISIO = 0b00010000;
    //アナログ入力(AN3のみ使う)
    ANS3 = 1;
    ANS2 = 0;
    ANS1 = 0;
    ANS0 = 0;
    ADCON0 = 0b00001101;                //Vref=Vdd:{xxx=CH}:DONE:ADON
    CMCON0  =0b0111;                    // Compalator Disable
    //PWM設定
    CCP1CON = 0b1100;                   //PWM Enable 11xx
    PR2 = 100;                          //PWM Period = 1.01 * 10E-4
    T2CON = 0b00000100;                 //TMR2 enable Prescaler=1
    GPIO = 0b00000000;
    
    //タイマー1設定
    T1CON   = 0b01000101;               //TMR1 Fosc/4*1/1
    TMR1H   = 254;                      //500μs
    TMR1L   = 40;
    
    OPTION_REG = 0b00000101;            // Timer2 Prescaler 1/64
    TMR0    = 100;                      // 9.984ms
    T0IF    = 1;                        // タイマ0割込フラグを0にする
    T1IF    = 1;                        // タイマ1割り込み許可
    GPIF    = 1;                        // GP3割り込み許可
    IOC     = 0b00001000;
    PEIE    = 1;                        // 周辺割り込み
    GIE     = 1;                        // 全体割り込み
    T0IE    = 1;
    T1IE    = 1;                        // タイマ1割り込み許可
    CCPR1L  = 0b0000000;                // Duty = 0%
    T2CON   = 0b00000000;               // PWM停止            
    CCP1CON = 0b0000;                   // PWM Disable
    
    init1   =   15;
    T1IE = 1;
    while(init1){
        GP0 = 1;                        // LED ON
        __delay_ms(50);
        GP0 = 0;                        // LED OFF
        __delay_ms(50);
        init1 --;
    }
    T0IE  = 1;                           // タイマ0割り込み許可
    toneh = 252;
    tonel = 119;
    beep  = 1;
    __delay_ms(100);
    toneh = 252;
    tonel = 219;
    __delay_ms(100);
    toneh = 253;
    tonel = 65;
    __delay_ms(100);
    toneh = 253;
    tonel = 95;
    __delay_ms(100);
    toneh = 253;
    tonel = 171;
    __delay_ms(500);
    beep  = 0;
    __delay_ms(500);
    wdtctl = 1;
    while(1)                            // メインループ 1周 800μs程度
    {
        
        if(intcount != intcount_old){   //割り込みルーチンは動いているか?
            intcount_old = intcount;
            CLRWDT();                   //動いていればウォッチドッグクリア
        }
        adc_count    = 8;               // 8回の平均を取る
        avolt = 0;
        while(adc_count){
            GO = 1;                     //ADC Start
            while(GO);                  //EOC?
            avolt += ADRESH;            //ANS3 8Bit
            adc_count -=1;
            __delay_us(50);
        }
        volt = avolt >> 3;              // volt = avolt÷8
                
        if (volt >= THRESHOLD || pwm_stop ==1){
                                        //STOP
            CCPR1L  = 0b0000000;        // Duty = 0%
            T2CON   = 0b0000000;        // PWM停止            
            CCP1CON = 0b0000;           // PWM Disable
            GP2 = 0;
        } else {
            T2CON   = 0b00000100;       // PWM 開始
            CCP1CON = 0b1100;           // PWM Enable
                 
            if (volt >= THRESHOLD5){
                //DUTY 1
                CCPR1L = DUTY1;    
                       
            }
            else if (volt >= THRESHOLD10){
                //DUTY 2
                CCPR1L = DUTY2;
                           
            }
            else {
                //DUTY 3
                CCPR1L = DUTY3;
            }
        }
        __delay_us(10);
    }
}
                                        //タイマ割り込み 処理時間10μs程度
void __interrupt() t_int(void)
{
    if(GPIF){                           // GP3割り込み
        pulse_cnt ++;          // リンギングを数える 
        GPIF = 0;
    }
    if(T1IF){                           //タイマー1割り込み
        TMR1H   = toneh;
        TMR1L   = tonel;
        if(GP1){
            GP1 = 0;
        }else if(beep){
            GP1 = 1;                    // 音を出す
        }
        if(wdtctl == 0){
            CLRWDT();
        }
        T1IF = 0;                        //クリア
        
    }
     
    if(T0IF){                            //タイマ0割り込み 処理時間40μs程度
        
        TMR0=100;                        //タイマ0初期値初期値に戻す
        intcount +=1 ;
        if(intcount==97){                //980msでPWM停止                
        
            if(volt >= THRESHOLD - 20){  //電圧が規定以上なら
                chg_ok = 1;              // DC-DC動作OK
            }else{
                chg_ok = 0;
            }
            pwm_stop = 1;
        }
        if(intcount==99){                //1秒でSCRトリガ
            GP5 = 1;                     //SCR GATE ON
        }    
        if(intcount==100){               //リセット 
        
            if (volt <= 10){             // 電圧が規定以下なら
                dchg_ok = 1;             // SCR放電回路OK
            }else{
                dchg_ok = 0;
            }
            
            GP5 = 0;
        }    
        if(intcount == 102){
            pwm_stop = 0;                // PWM 開始
            intcount = 0;
        
            ledcount +=1;                // LED点滅用カウンタ
            if(ledcount & 1){
                GP0 = 0;                 //奇数回目は消灯
                beep = 0;
            }else{
                if(LED_stat!=0 ){
                    GP0 = 1;
                    LED_stat -=1;
                }else{
                    GP0 = 0;
                }        
                if((chg_ok || dchg_ok)==0 ){
                    beep = 1;
                }
                
            }    
        }    
        if(ledcount == 10){
            ledcount = 0;
            if(chg_ok == 1 && dchg_ok == 1 && pulse_cnt >=1 && pulse_cnt <=4){
                LED_stat = 0;               //正常なら消灯
            }
            if(chg_ok == 1 && dchg_ok == 1 && pulse_cnt >=5){
                LED_stat = 1;               //柵線断線の可能性なら1回点滅
            }
            if(chg_ok == 1 && dchg_ok == 1 && pulse_cnt ==1){
                LED_stat = 2;               //柵線短絡の可能性なら2回点滅
            }
            if(chg_ok == 1 && dchg_ok == 0){
                LED_stat = 3;               //SCR系不良なら3回点滅
            }
            if(chg_ok == 0 && dchg_ok == 1){
                LED_stat = 4;               //DC-DC系不良なら4回点滅
            }                               //DC-DC系が不良だとSCRも不良判定される
            if(chg_ok == 0 && dchg_ok == 0 && pulse_cnt >=1 && pulse_cnt <=5){
                LED_stat = 5;               //全部不良なら5回点滅
            }
            pulse_cnt = 0;
        }
    T0IF=0;                                 //タイマ0による割り込みリセット
    
    }
}
 

にほんブログ村 その他趣味ブログ 電子工作へ
にほんブログ村