4章:床下ファン駆動用タイマーの製作

    作成2014.11.21
     床下ファン駆動用タイマーを製作します。

  1. 床下ファン駆動用タイマーの回路図
     床下ファン駆動用タイマーの回路図を以下に示します。



  2. ファイル構造の変更とカスタマイズ後のファイル構造
     ソース.cファイルとヘッダ.hファイルはシンプルな配置に変更しました。その他は自動生成ファイルです。
     部品の多くは、無線式気象観測レコーダに切替えたため不要となった気象観測レコーダ2型を再利用しました。  使用部品リストを以下に示します。
      ダーリントン・トランジスタ 2SD1590(150V8A)の仕様は下記を参照願います。
    「2SD1590_js.pdf」にいく。
     ダーリントン・トランジスタ 2SD1590のコレクタ飽和電圧Vceは標準で0.9Vですがこの分電圧ロスが発生します。実測では電源電圧12.33V、ファン印加電圧11.56V(コレクタ飽和電圧Vce=0.77V)となりました。
     また、ダーリントン・トランジスタ 2SD1590の表面は若干熱くなります。電流容量的にはあまりマージンはなさそうです。

    記号品名単価個数小計購入先
    ファンDC軸流ファン 60mm角15mm厚 DC12V (送料+¥600)210102100アマゾン
    12V12V5A 汎用 ACアダプター 135011350アマゾン
    3.3V低損失CMOS三端子レギュレータ 3.3V150mA XC6202P332TB 2個入50150秋月電子通商
    PIC18F4553PICマイコンPIC18F4553−I/P4301430秋月電子通商
    -ICソケット (40P) (10個入)30130秋月電子通商
    2SD1590ダーリントン・トランジスタ 2SD1590(150V8A)50150秋月電子通商
    MDIPロータリー・スイッチ(8ステップ)青502100秋月電子通商
    SWタクトスイッチ(黒色)10330秋月電子通商
    LED赤色LED 3mm OSDR3133A 500mcd 30度100個入3.5931.5秋月電子通商
    20MHzクリスタル(水晶発振子) 20MHz(10個入)40140秋月電子通商
    15pF積層セラミックコンデンサー15pF100V±5%10220秋月電子通商
    330Ωカーボン抵抗(炭素皮膜抵抗) 1/4W330Ω (100本入)111秋月電子通商
    1kΩカーボン抵抗(炭素皮膜抵抗) 1/4W1kΩ (100本入)11010秋月電子通商
    10kΩカーボン抵抗(炭素皮膜抵抗) 1/4W10kΩ (100本入)199秋月電子通商
    -片面ガラス・ユニバーサル基板 Bタイプ めっき仕上げ (95x72mm)1201120秋月電子通商
    -アクリルケース SK−161301130秋月電子通商


  3. 床下ファン駆動用タイマーの外観
     床下ファン駆動用タイマーの外観を以下に示します。



  4. 床下ファン駆動用タイマーの操作方法
    (1)電源投入時、またはリセット時の設定
    *STime0 = 0x927Cに設定され、0.025s毎にCCP割込みが発生します。
    *時刻のカウンタはSTime1 = 2400に設定され、1分毎にカウンタアップします。
    *全体の周期はCyTime0=0X5A0に設定され、1440(=0X5A0)分/1日となります。
    *リセット時の時刻はCTime1=540に設定され、540/60=9:00となります。
    *ファンON の時刻はCyTime1=540に設定され540/60=9:00にONします。
    *ファンOFF no時刻はCyTime2=1260に設定され1260/60=21:00にOFFします。
    注(1)9:00に電源投入、またはリセットすると矛盾なく動作するようにしました。

    (2)M0=0モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時現在時刻の下位バイトを8個のLEDで2進表示します。
    *M1=1の時現在時刻の上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すと現在時刻が増加します。(長押しすると変更が早くなります。)
    *SW2ボタンを押すと現在時刻が減少します。(長押しすると変更が早くなります。)
    注(1)M0=0モードは現在時刻の確認と修正に使用します。

    (3)M0=1モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時ファンON の時刻の下位バイトを8個のLEDで2進表示します。
    *M1=1の時ファンON の時刻の上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すとファンON の時刻が増加します。(長押しすると変更が早くなります。)
    *SW2ボタンを押すとファンON の時刻が減少します。(長押しすると変更が早くなります。)
    注(1)M0=1モードはファンON の時刻の確認と修正に使用します。

    (4)M0=2モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時ファンOFF の時刻の下位バイトを8個のLEDで2進表示します。
    *M1=1の時ファンOFF の時刻の上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すとファンOFF の時刻が増加します。(長押しすると変更が早くなります。)
    *SW2ボタンを押すとファンOFF の時刻が減少します。(長押しすると変更が早くなります。)
    注(1)M0=2モードはファンOFF の時刻の確認と修正に使用します。

    (4)M0=3モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時STime0 = 0x927Cの下位バイトを8個のLEDで2進表示します。
    *M1=1の時STime0 = 0x927Cの上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すとSTime0 = 0x927Cが増加します。(長押しすると変更が早くなります。)
    *SW2ボタンを押すとSTime0 = 0x927Cが減少します。(長押しすると変更が早くなります。)
    注(1)M0=4モードは割込み発生周期の確認と修正に使用します。(時計の遅れ、進み調整)

    (4)M0=4モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時CyTime0 = 0x927Cの下位バイトを8個のLEDで2進表示します。
    *M1=1の時CyTime0 = 0x927Cの上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すとCyTime0 = 0x927Cが増加します。(長押しすると変更が早くなります。)
    *SW2ボタンを押すとCyTime0 = 0x927Cが減少します。(長押しすると変更が早くなります。)
    注(1)全体の周期を変更します。

    (5)M0=5モード(DIPロータリー・スイッチ(8ステップ)青)
    *M1=0の時STime1 =0x0960の下位バイトを8個のLEDで2進表示します。
    *M1=1の時STime1 =0x0960の上位バイトを8個のLEDで2進表示します。
    *SW1ボタンを押すとSTime1 =2400となります。(標準設定)
    *SW2ボタンを押すとSTime1 =0x0001となります。(TEST用設定)
    注(1)STime1 =40に設定すると時計の進みがプログラム上では60倍となりますが、実測では60倍とはなりません。これは、ソフト処理が間に合わなくなるためと思われます。

    (6)M0=6モード(DIPロータリー・スイッチ(8ステップ)青)
    *強制的にファンOFFとなります。

    (6)M0=7モード(DIPロータリー・スイッチ(8ステップ)青)
    *強制的にファンONとなります。


  5. ソースプログラムのポイント
    (1)PIC18F4553のOscillatorモード
    *12種のOscillatorモードを選択可能である。
    *#pragma config FOSC = HSPLL_HSでHSPLL_HSモードを指定。
    *FORS=0b111x:HS oscillator, PLL enabled (HSPLL)

    (2)System Clock設定
    *HSPLL_HSモードの場合、96MHz/2、96MHz/3、96MHz/4、96MHz/6が選択可能
    *#pragma config CPUDIV= OSC1_PLL2でCPUDIV=0b00の96MHz/2=48MHzを指定。

    (3)USB Clock設定
    *96MHz/2かプライマリOscillatorダイレクトが選択可能。
    *#pragma config USBDIV = 2で USBDIV=0b1の96MHz/2=48MHzを指定。

    (4)__delay_ms関数用条件設定
    *#define _XTAL_FREQ 48000000でSystem Clockが48MHzを設定。

    (5)CCP割込み設定
    *CCP1CON = 0b00001011;でCCPのモードをコンペアモード(CCP割込み + TMR1クリア)に設定。
    *CCPR1H = STime0 >> 8;とCCPR1L = STime0;でCCP割込み発生のカウント数を設定。
    *CCP1IF = 0;でCCP割込みフラグをクリア
    *CCP1IE = 1;でCCP割込みの許可

    (6)タイマ1設定
    *TMR1CS = 0;でクロック源を内部クロック(48Mhz)に設定
    *T1CKPS1 = 1;とT1CKPS0 = 1;でプリスケーラ値を1/8に設定
    *TMR1H = 0;とTMR1L = 0;でTMRレジスタをクリア
    *TMR1ON = 1;でタイマ1起動

    (7)割込み処理関数
    *void interrupt SYS_InterruptHigh(void)と記載するがSYS_InterruptHighの名称は何でも良い
    *void interrupt 名称(void)はプログラム上1個のみ許される。
    *CCP割込みの場合はCCP1IF==1となる。
    *処理後はCCP1IF = 0;でCCP割込みフラグをクリアする必要がある。
    *USB割込みの場合はUSBIF==1となる。

    (8)CCP割込み発生間隔時間の設定
    *STime0=48MHz*0.025s/(4*8)=37500=0x927Cとした。
    *STime0の値は16bitを越えることができない。

    (9)ソースプログラムのファイル構成
    *newmain18.cのみとしました。


  6. ソースプログラム
     以下にソースプログラムを示します。
    //Timer
    #include <xc.h>
    
    #pragma config PLLDIV   = 5         // Divide by 5 (20 MHz oscillator input)
    #pragma config CPUDIV   = OSC1_PLL2	//[Primary Oscillator Src: /1][96 MHz PLL Src: /2]
    #pragma config USBDIV   = 2         // USB clock source comes from the 96 MHz PLL divided by 2
    #pragma config FOSC     = HSPLL_HS	//HS oscillator, PLL enabled (HSPLL)
    #pragma config FCMEN    = OFF	//Fail-Safe Clock Monitor disabled
    #pragma config IESO     = OFF	//Fail-Safe Clock Monitor disabled
    #pragma config PWRT     = OFF	//PWRT disabled
    #pragma config BOR      = ON	//Brown-out Reset enabled in hardware only (SBOREN is disabled)
    #pragma config BORV     = 3	//Minimum setting
    #pragma config VREGEN   = ON      //USB voltage regulator enabled
    #pragma config WDT      = OFF	//[Watchdog Timer Enable] disabled (control is placed on the SWDTEN bit)
    #pragma config WDTPS    = 32768	//Watchdog Timer Postscale Select bits 1:32768
    #pragma config MCLRE    = ON	//MCLR pin enabled; RE3 input pin disabled
    #pragma config LPT1OSC  = OFF	//Timer1 configured for higher power operation
    #pragma config PBADEN   = OFF	//PORTB<4:0> pins are configured as digital I/O on Reset
    //#pragma config CCP2MX   = ON
    #pragma config STVREN   = ON		//Stack full/underflow will cause Reset
    #pragma config LVP      = OFF	//Single-Supply ICSP disabled
    //#pragma config ICPRT    = OFF       // Dedicated In-Circuit Debug/Programming
    #pragma config XINST    = OFF       // Extended Instruction Set
    #pragma config CP0      = OFF	//Block 0 (000800-001FFFh) is not code-protected
    #pragma config CP1      = OFF	//Block 1 (002000-003FFFh) is not code-protected
    //#pragma config CP2      = OFF
    //#pragma config CP3      = OFF
    #pragma config CPB      = OFF	//Boot block (000000-0007FFh) is not code-protected
    //#pragma config CPD      = OFF
    #pragma config WRT0     = OFF	//Block 0 (000800-001FFFh) is not write-protected
    #pragma config WRT1     = OFF	//Block 1 (002000-003FFFh) is not write-protected
    //#pragma config WRT2     = OFF
    //#pragma config WRT3     = OFF
    #pragma config WRTB     = OFF       // Boot block (000000-0007FFh) is not write-protected
    #pragma config WRTC     = OFF	//Configuration registers (300000-3000FFh) are not write-protected
    //#pragma config WRTD     = OFF
    #pragma config EBTR0    = OFF	//Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks
    #pragma config EBTR1    = OFF	//Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks
    //#pragma config EBTR2    = OFF
    //#pragma config EBTR3    = OFF
    #pragma config EBTRB    = OFF	//Boot block (000000-0007FFh) is not protected from table reads executed in other blocks
    
    #define _XTAL_FREQ  48000000             //48MHz設定__delay_ms
    #define	SW1         PORTEbits.RE0
    #define	SW2         PORTEbits.RE1
    #define	LED         PORTEbits.RE2
    
    
    // プロトタイプ宣言
    void InitInterCCP (void);
    void InitTimer1 (void);
    void init(void);
    void Mood0(void);
    void Mood1(void);
    void Mood2(void);
    void Mood3(void);
    void Mood4(void);
    void Mood5(void);
    
    
    //STime0=48MHz*0.025/(4*8)=37500=0x927C
    unsigned short STime0 = 0x927C; //0.025sサイクルタイム
    unsigned short STime1 = 2400; //60sサイクルタイム
    unsigned short STime1_S = 2400; //60sサイクルタイム2400=0x960
    unsigned short STime1_T = 40; //短縮サイクルタイム(1日を短縮テスト用)
    unsigned short CTime0=0;//0.025sサイクルカウンタ
    unsigned short CTime1=0x021C;//60sサイクルカウンタ(9*60=540=0x021C=9:00スタート)
    unsigned short CyTime0=0X05A0;//サイクルカウンタ値の周期(1日=60*24=1440=0x5A0)
    unsigned short CyTime1=0x021C;//ONする時刻9:00=9*60=540=0x021C
    unsigned short CyTime2=0x04EC;//OFFする時刻21:00=21*60=1260=0x04EC
    unsigned short gDTN=50;//スイッチ操作のディレイ回数
    unsigned char F_Auto=1;//自動タイマーモードフラグ
    
    
    
    
    void main(void)
     {
    	init();//初期化
    	InitInterCCP();// CCP割込み設定関数の呼び出し
    	InitTimer1();// タイマ1設定関数の呼び出し
    	PEIE = 1;// 周辺機能割込みの許可
    	GIE = 1;// 全体の割込み許可
    
            unsigned char MyMood0;//表示・修正モード
    
    	while(1)
    	{
                MyMood0=((~PORTA) >> 2) & 0b00000111;//表示・修正モード読込
                //MyMood0=7;//TEST用
                switch (MyMood0)//モードスイッチ
                {
                    case 0:
                        F_Auto=1;
                        Mood0();//現在時刻カウンタ表示・修正
                        break;
                    case 1:
                        F_Auto=1;
                        Mood1();//スイッチON時刻カウンタ表示・修正
                        break;
                    case 2:
                        F_Auto=1;
                        Mood2();
                        break;
                    case 3:
                        F_Auto=1;
                        Mood3();
                        break;
                    case 4:
                        F_Auto=1;
                        Mood4();
                        break;
                    case 5:
                        F_Auto=1;
                        Mood5();
                        break;
                    case 6:
                        PORTD=0xFF;
                        F_Auto=0;
                        PORTCbits.RC0 = 0;LED=0;//スイッチOFF
                        break;
                    case 7:
                        PORTD=0xFF;
                        F_Auto=0;
                        PORTCbits.RC0 = 1;LED=1;//スイッチOFF
                        break;
                    default:
                    break;
                }
    
    	}
    }
    
    void Mood0(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        //MyMood1=0;//TEST用
        switch (MyMood1)
        {
            case 0:
                Disp=CTime1;
                break;
            case 1:
                Disp=CTime1 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
    
        if(SW1==1 && SW2==1){gDTN=20;}
        if(SW1==0)
        {
            CTime1++;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        if(SW2==0)
        {
            CTime1--;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        for ( int i = 0; i < gDTN; i++ ) __delay_ms( 10 );
    }
    
    void Mood1(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        switch (MyMood1)
        {
            case 0:
                Disp=CyTime1;
                break;
            case 1:
                Disp=CyTime1 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
    
        if(SW1==1 && SW2==1){gDTN=20;}
        if(SW1==0)
        {
            CyTime1++;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        if(SW2==0)
        {
            CyTime1--;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        for ( int i = 0; i < gDTN; i++ ) __delay_ms( 10 );
    }
    
    void Mood2(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        switch (MyMood1)
        {
            case 0:
                Disp=CyTime2;
                break;
            case 1:
                Disp=CyTime2 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
    
        if(SW1==1 && SW2==1){gDTN=20;}
        if(SW1==0)
        {
            CyTime2++;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        if(SW2==0)
        {
            CyTime2--;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        for ( int i = 0; i < gDTN; i++ ) __delay_ms( 10 );
    }
    
    void Mood3(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        switch (MyMood1)
        {
            case 0:
                Disp=STime0;
                break;
            case 1:
                Disp=STime0 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
        
        if(SW1==1 && SW2==1){gDTN=20;}
        if(SW1==0)
        {
            STime0++;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        if(SW2==0)
        {
            STime0--;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        for ( int i = 0; i < gDTN; i++ ) __delay_ms( 10 );
    }
    
    void Mood4(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        switch (MyMood1)
        {
            case 0:
                Disp=CyTime0;
                break;
            case 1:
                Disp=CyTime0 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
    
        if(SW1==1 && SW2==1){gDTN=20;}
        if(SW1==0)
        {
            CyTime0++;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        if(SW2==0)
        {
            CyTime0--;
            gDTN--;
            if(gDTN<1){gDTN=1;}
        }
        for ( int i = 0; i < gDTN; i++ ) __delay_ms( 10 );
    }
    
    void Mood5(void)
    {
        unsigned char MyMood1;
        unsigned char Disp;
        MyMood1=((~PORTB) >> 2) & 0b00000111;
        switch (MyMood1)
        {
            case 0:
                Disp=STime1;
                break;
            case 1:
                Disp=STime1 >> 8;
                break;
            default:
                Disp=0;
                break;
        }
        PORTD = ~Disp;
    
        if(SW1==0)
        {
            STime1=STime1_S;
        }
        if(SW2==0)
        {
            STime1=STime1_T;
        }
    }
    
    void init(void)
    {
        ADCON1  =	0b00001111;	//全チャンネルがデジタルに設定され、VDDとVSSが選択
        TRISA   =	0b00011100;	//A0〜A4を入力に設定
        TRISB   =	0b00111100;	//B0〜B7を入力に設定
        TRISC   =	0b00110000;         //D-,D+(USB用)RC4とRC5を入力に設定
        TRISD   =	0b00000000;	//D0〜D7を出力に設定
        TRISE   =   0b00000011;         //SW1,2=INPUT LED=OUTPUT
        LATA    =	0b00000000;
        LATB    =	0b00000000;
        LATC    =	0b00000000;
        LATD    =	0b00000000;
        LATE    =	0b00000000;
    
        //PORTD=0xFF;//ポートD全ビットON
        PORTCbits.RC0 = 1;LED=1;//スイッチON
    }
    
    // 割込みサービスルーチン
    void interrupt SYS_InterruptHigh(void)
    {
        if(CCP1IF==1)// CCP割込みの場合
        {
            if(CTime0 > STime1)
            {
                if(CTime1 == CyTime1 && F_Auto==1){PORTCbits.RC0 = 1;LED=1;}//スイッチON
                if(CTime1 == CyTime2 && F_Auto==1){PORTCbits.RC0 = 0;LED=0;}//スイッチOFF
                if(CTime1 > CyTime0){CTime1 = 0;}
                CTime0=0;
                CTime1++;
            }
            CTime0++;
    	// CCP割込みフラグをクリア
    	CCP1IF = 0;
        }
        if(USBIF==1){;}//USB割込みの場合
    }
    
    // CCP割込み設定関数
    void InitInterCCP (void)
    {
    	// CCPのモードをコンペアモード(CCP割込み + TMR1クリア)に設定
    	CCP1CON = 0b00001011;
    	// CCPRレジスタの設定(周期0.1秒)
    	CCPR1H = STime0 >> 8;
    	CCPR1L = STime0;
    	// CCP割込みフラグをクリア
    	CCP1IF = 0;
    	// CCP割込みの許可
    	CCP1IE = 1;
    }
    
    // タイマ1設定関数
    void InitTimer1 (void)
    {
    	// クロック源を内部クロックに設定
    	TMR1CS = 0;
    	// プリスケーラ値を1/8に設定
    	T1CKPS1 = 1;
    	T1CKPS0 = 1;
    	// TMRレジスタをクリア
    	TMR1H = 0;
    	TMR1L = 0;
    	// タイマ1起動
    	TMR1ON = 1;
    }
    
    
    
     以下はソースプログラムのテキストファイルです。 「newmain18.cのファイル」にいく。


  7. 結果の検討
    (1)床下ファン駆動用タイマーは、データ収集無しとしたため、USBを使用しない構成にしました。
    (2)USBの使用を除くと全て独自のプログラム作成が可能となります。
    (3)ソースプログラムファイルはnewmain.cのみとしました。
    (4)こうするとPIC18F4553マイコンとPICkit3 2章:秋月電子通商サンプルプログラム「MPLABを使った使用例1」の実行に行く。の方法が単純に適用できます。
    (5)表示は8個のLEDによる1バイトの2進表示としました。
    (6)読みにくいのですが、安価、省スペースでプログラムが容易です。
    (7)操作は3個のタクトスイッチと2個のDIPロータリー・スイッチ(8ステップ)のみとしました。
    (8)これで、床下ファン駆動用タイマーで必要な操作は全てカバーできました。
    (9)操作も安価、省スペースでプログラムが容易です。




5章:PWMによる高周波波形と周波数特性の測定(1)に行く。

トップページに戻る。