16章:高温用温度レコーダの製作

    作成2015.02.06

     7セグメントLED表示器とK型熱電対プローブを使用して、高温用温度レコーダを製作します。

  1. 高温用温度レコーダ回路図
     高温用温度レコーダ回路図を以下に示します。

     
    *7セグメントLED表示器は配線量が増大しますが、安価で低電力です。
    *高精度IC温度センサLM61BIZの出力端に33kΩの負荷抵抗をつけると出力が安定しました。
    *シリアルIスケアC EEPROM 24FC256−I/Pで動作条件の設定と測定データの記録を行います。
    *K型熱電対プローブの出力電圧を非反転増幅回路で101倍に増幅してAD変換します。


  2. 高温用温度レコーダ回路の外観
     高温用温度レコーダ回路の外観を以下に示します。



  3. 評価プログラム
     まずは下記の「41-16.zip」ファイルをダウンロードしてください。
    [41-16.zip]をダウンロードする。

    解凍するとフォルダー内にUMy-CDC-Basicフォルダーとdynamic_cdc_demo.exeがあります。USB-HID-SCDフォルダー内に

    (1)UMy-CDC-Basicフォルダー
    *My-CDC-Basic.Xがソースプログラムです。
    *「XC8」用です。

    (2)dynamic_cdc_demo.exe
    *標準のWindows用実行ファイルです。
    *Win-PingPong.exeでも同様な操作ができます。

    (3)注意事項
    *上記プログラムはPIC18F4553用です。


  4. 操作方法
    (1)PIC18F4553にプログラムを書込みます。
    (2)USBを接続し、動作条件をシリアルIスケアC EEPROM 24FC256−I/Pに書込みます。
    (3)dynamic_cdc_demo.exeを起動します。
    (4)標準動作条件(高温測定モード、測定間隔1s)を書込みます。
    *Send DataにBB#0#10#を設定して、Send Dataボタンを押します。


    (5)測定モード
    0:高温測定モード
    1:気温測定モード
    2:気温AD変換値(デバッグ用)
    3:熱電対AD変換値(デバッグ用)
    (6)測定間隔
    *0.1s刻みで設定できます。
    *設定可能最大値は0XFFFF=65535です。(6553.5s)

    (6)データレコード開始
    *SW1を押すとLEDが点灯し、データNo=0からレコードを開始します。
    (7)データレコード終了
    *SW2を押すとLEDが消灯し、レコードを終了するとともに、データ数を記録します。
    *この後電源を切ってもデータ数とデータは保持されます。

    (7)レコードデータの読取
    *Send DataにAA#を設定して、Send Dataボタンを押します。


    (8)読取データのコピー、ペースト
    *テキストボックスを右クリックしてすべて選択をえらびます。
    *テキストボックスを右クリックしてコピーを選択します。
    *EXCEL数表にペーストします。


  5. 測定例
     ガスコンロで水を入れたなべを過熱した場合の温度変化を調べました。
    (1)数値データ
     数値データは以下のようになりますが、No14以降は省略します。
    M0=0
    gN=10
    gSNo=137
    0 213
    1 329
    2 580
    3 580
    4 608
    5 618
    6 614
    7 627
    8 642
    9 644
    10 644
    11 644
    12 644
    13 646

    (2)ガスコンロで水を入れたなべを過熱した場合の温度変化グラフ
     温度変化グラフを以下に示します。

     約100℃で温度が一定になることが確認できます。


  6. My-CDC-Basic.Xプログラムコードのポイント
    *MPLAB_X_IDE_v2.25とPIC18F4553マイコンの復習、3章:サンプルプログラムのファイル構造の変更とカスタマイズをベースに修正しました。

    (1)タイマ0割込み設定関数
    *system.cとsystem.hに定義しました。
    *2930Hzの割込みを発生します。
    *MAIN_RETURN main(void)で読み出します。
    // タイマ0割込み設定関数
    void InitInterTimer0 (void)
    {
        // クロック源を内部クロックに設定
        T0CS = 0;
        // プリスケーラをタイマ0に割り当て
        PSA = 0;
        // プリスケーラ値を16に設定=割込み周波数=48MHz/(4*256*16)=2930Hz
        T0CONbits.T0PS0 = 1;//PIC18F4553
        T0CONbits.T0PS1 = 1;//PIC18F4553
        T0CONbits.T0PS2 = 0;//PIC18F4553
        // TMR0レジスタをクリア
        TMR0 = 0x0000;
        // タイマ0割込みフラグをクリア
        T0IF = 0;
        // タイマ0割込みの許可
        T0IE = 1;
    }
    

    (2)割込み処理関数
    *system.cとsystem.hに定義されています。
    *7セグメントLED表示器の制御を行います。(2930Hzで表示切替)
    *0.1s毎の割込み関数を呼び出します。
    *USB割込みに処理を行います。
    void interrupt SYS_InterruptHigh(void)
    {
    
    
        if(T0IF == 1)
        {
            switch (gCT)
            {
    	case 0:
                gCT++;
                 PORTD=~CH[gNo3];
                 PORTB=0X04;
    		break;
    	case 1:
                gCT++;
                PORTD=~CH[gNo2];
                PORTB=0X08;
    		break;
    	case 2:
                gCT++;
                PORTD=~CH[gNo1];
                PORTB=0X10;
    		break;
            case 3:
                gCT++;
                PORTD=~CH[gNo0];
                PORTB=0X20;
    		break;
    	default:
                gCT=0;
    		break;
            }
    
            gCT2++;
            if(gCT2>293)
            {
                gCT2=0;
                Int_Low();
            }
    
    
            // タイマ0割込みフラグをクリア
            T0IF = 0;
        }
    
        #if defined(USB_INTERRUPT)
        //***変更1
        if(PIR2bits.USBIF == 1){USBDeviceTasks();}
        #endif
    }
    

    (3)0.1s毎の割込み処理関数
    *system.cとsystem.hに定義しました。
    *計測とデータの保存を行います。
    void Int_Low()
    {
        //long N=10;
        long X;
        
        if(gCT3 < gN)
        {
            gCT3++;
            SX=SX+ADC0();
            SX2=SX2+ADC1();
        }
        else
        {
            switch (M0) 
            {
                case 0:
    		X=(796*SX)/(1000*gN)-600+(1880*SX2)/(1000*gN)-70;
    		break;
                case 1:
    		X=(796*SX)/(1000*gN)-600;
    		break;
                case 2:
    		X=ADC0();
    		break;
                case 3:
    		X=ADC1();
    		break;
                default:
    		break;
            }
            gCT3=0;
            gNo=X;SetgNo();
            SX=0;SX2=0;
            if(fStart==1)
            {
                Write_EPROM(2*gSNo+6,(unsigned char)(X/256));
                __delay_ms( 10 );
                Write_EPROM(2*gSNo+7,(unsigned char)(X));
                BfStart=1;
                gSNo++;
                if(gSNo>15000){gSNo=15000;}//領域制限
            }
            else
            {
                if(BfStart==1)
                {
                    Write_EPROM(4,(unsigned char)(gSNo/256));
                    __delay_ms( 10 );
                    Write_EPROM(5,(unsigned char)(gSNo));
                }
                BfStart=0;
            }
        }
    }
    

    (4)AD変換処理関数
    *app_device_cdc_basic.cとapp_device_cdc_basic.hに定義しました。
    *AD変換を行います。
    unsigned short ADC0()
    {
        unsigned short result;
        long X;
    
        ADCON0bits.GO = 0;              // Stop AD conversion
        __delay_us( 100 );
        ADCON0bits.CHS = 0b0000; //Analog Channel Select bits=Channel 0 (AN0)
        __delay_us( 100 );
        ADCON0bits.GO = 1;              // Start AD conversion
        while(ADCON0bits.NOT_DONE);     // Wait for conversion
        result=ADRESH*256+ADRESL;
        return result;
    }
    
    unsigned short ADC1()
    {
        unsigned short result;
        long X;
    
        ADCON0bits.GO = 0;              // Stop AD conversion
        __delay_us( 100 );
        ADCON0bits.CHS = 0b0001; //Analog Channel Select bits=Channel 0 (AN0)
        __delay_us( 100 );
        ADCON0bits.GO = 1;              // Start AD conversion
        while(ADCON0bits.NOT_DONE);     // Wait for conversion
        result=ADRESH*256+ADRESL;
        return result;
    }
    

    (5)USB受信処理関数
    *app_device_cdc_basic.cとapp_device_cdc_basic.hに定義しました。
    *USB受信処理を行います。
    void MyCDCBasicTasks()
    {
         unsigned short X1,X2;
         uint16_t i,j,k;
         uint8_t numBytesRead;
         unsigned char FIN[5][20];
         numBytesRead = getsUSBUSART(readBuffer, sizeof(readBuffer));
    
        if( USBUSARTIsTxTrfReady() == true)
        {
    
            if(numBytesRead > 0)
            {
                j=0;k=0;
                for(i=0;i5){j=4;}
                        k=0;
                    }
                    else
                    {
                        FIN[j][k]=readBuffer[i];
                        k++;if(k>20){k=19;}
                    }
                }
                int TEST=1;
                if(FIN[0][0]=='A' && FIN[0][1]=='A' && FIN[0][2]==0)
                {
                    //X1=atof((const char *)FIN[1]);
                    //X2=atof((const char *)FIN[2]);
                    //X3=X1+X2;
                    //RA0=ADC0();
                    X1=Read_EPROM(0);
                    X2=256*Read_EPROM(2)+Read_EPROM(3);
                    gSNo=256*Read_EPROM(4)+Read_EPROM(5);
    
                    sprintf(writeBuffer,"M0=%d\r\ngN=%d\r\ngSNo=%d\r\n",X1,X2,gSNo);
                    numBytesRead = strlen(writeBuffer);
                    putUSBUSART(writeBuffer,numBytesRead);
                    TEST=2;
                    fOut=1;gi=0;
                }
                if(FIN[0][0]=='B' && FIN[0][1]=='B' && FIN[0][2]==0)
                {
                    X1=atoi((const char *)FIN[1]);
                    X2=atoi((const char *)FIN[2]);
    
                    Write_EPROM(0,(unsigned char)X1);
                    __delay_ms( 10 );
                    Write_EPROM(2,(unsigned char)(X2/256));
                    __delay_ms( 10 );
                    Write_EPROM(3,(unsigned char)(X2));
                    __delay_ms( 10 );
                    M0=X1;gN=X2;
    
                }
            }
            else
            {
                 if(fOut==1)
                 {
                     if(gi < gSNo)
                     {
                         X1=256*Read_EPROM(2*gi+6)+Read_EPROM(2*gi+7);
                         sprintf(writeBuffer,"%d\t%d\r\n",gi,X1);
                         numBytesRead = strlen(writeBuffer);
                         putUSBUSART(writeBuffer,numBytesRead);
                         gi++;
                     }
                     else
                     {
                         fOut=0;
                     }
                 }
            }
        }
         
        CDCTxService();
    }
    

    (6)グローバル変数
    system.hに定義しました。
    #define _XTAL_FREQ  48000000             //__delay_ms
    
    unsigned char CH[10] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//7セグLED
    unsigned char gCT=0;//カウンタ
    unsigned long gCT2=0,gCT3=0;//カウンタ
    unsigned short gNo=1234;//7セグLED表示
    unsigned char gNo3,gNo2,gNo1,gNo0;//7セグLED表示
    long SX=0,SX2=0;//総和用
    unsigned char M0;//動作モード
    unsigned short gN;//計測間隔
    unsigned short gSNo;//計測データ数
    unsigned char fStart=0;//記録開始、停止
    unsigned char BfStart;//ひとつ前の状態
    unsigned char fOut=0;//USB送信フラグ
    unsigned short gi;//USB送信No
    




  7. 高温用温度レコーダ纏め
    (1)7セグメントLED表示器を使用することにより、実用的な高温度レコーダを製作することができました。
    (2)動作条件のモード設定はシリアルIスケアC EEPROM 24FC256−I/Pの0番アドレスを使用しました。
    (3)動作条件の測定間隔設定は2番と3番を使用しました。
    (4)測定したデータ数は4番と5番に記録されます。
    (5)測定データは6番以降に記録され、最大記録データ数は15000に設定しました。
    (6)高精度IC温度センサLM61BIZの出力端に33kΩの負荷抵抗をつけると出力が安定しました。
    (7)熱電対の出力電圧は小さいため、非反転増幅回路で101倍に増幅しました。
    (8)非反転増幅回路の出力電圧は、USB接続時と切断時で僅かですが値が変化します。高精度IC温度センサ出力は変化しません。
    (9)非反転増幅回路の出力電圧のUSB接続時と切断時の変化は、なんらかのハード的な要因によって生じると思われますが明確な原因はわかりませんでした。




17章:7セグメントLED表示器(カソードコモン)に行く。

トップページに戻る。