気温と湿度の計測回路

2つの温度 (車内温度・車外温度) と1つの湿度を計測します。

プログラム

コンパイラはCCS Cを使用しています。

#include <16f876.h>
#include "FsID.h"

#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP

#device ADC=10, *=16            // A/D変換 10ビットモード, 16bitポインタ指定
#use delay( Clock = 20000000 )  // クロック周波数指定

#use i2c( slave, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=ADD_ENVIRON, FAST, FORCE_HW )

#use fast_io( A )
#use fast_io( B )
#use fast_io( C )

// マクロ定義 **************************************************************
#define    CH_TEMPOUT    0    // 外気温 入力チャンネル
#define    CH_TEMPIN     1    // 内気温       〃

#define    CH_HUM        4    // 湿度 入力チャンネル

// プロトタイプ宣言 ********************************************************
signed long Thermometer( int );
long Hygrometer();

void DisplayLCD();
long MinusSign( signed long Data );

// グローバル変数宣言 ******************************************************
signed long AirTemp;    // 外気温[x10℃]
signed long RoomTemp;   // 内気温[x10℃]
long Humidity;          // 湿度[x10%]


// -------------------------------------------------
#include "lcd_lib.h"    // 液晶表示ライブラリ
#include "i2c.h"        // I2C送受信処理
#include "ad.h"         // A/D


// =====================================================================
// SSP割り込み処理
#int_ssp
void ssp_interupt()
{
    if( i2c_poll() )
    {
        // 受信
        int Receive;
        Receive = i2c_read();
    }
    else
    {
        // 送信
        I2cSlaveSend16( ( long )AirTemp );
        I2cSlaveSend16( ( long )RoomTemp );

        I2cSlaveSend16( Humidity );
    }
}


// =====================================================================
// メイン関数
void main()
{
    /* ------------------------------------------------------
        A0,A1:温度測定(AN_in)
        A5:湿度測定(AN_in)

        C3:I2C_SCL(in)
        C4:I2C_SDA(in)
    -------------------------------------------------------*/
    set_tris_a( 0b00100011 );
    set_tris_b( 0b00000000 );
    set_tris_c( 0b00011000 );

    output_a( 0x00 );
    output_b( 0x00 );
    output_c( 0x00 );

    setup_adc_ports( A_ANALOG );    // Setup A/D Converter
    setup_adc( adc_clock_div_32 );  // Fosc/32 最高速度
    // ------------------------------------------------------

    enable_interrupts( GLOBAL );    // グローバル割り込み許可

    lcd_init();
    printf( lcd_data, "Fs - environment" );

    // 入力信号が安定するまで待つ -----
    delay_ms( 1000 );
    // --------------------------------

    AirTemp = RoomTemp = Humidity = 0;
    enable_interrupts( INT_SSP );    // SSP割り込み許可。外部との通信を開始する

    while( 1 )
    {
        // 外気温 測定
        AirTemp = Thermometer( CH_TEMPOUT );

        // 内気温 測定
        RoomTemp = Thermometer( CH_TEMPIN );

        // 湿度 測定
        Humidity = Hygrometer();


        DisplayLCD();
        delay_ms( 90 );
    }
}

// =====================================================================
// 温度 測定
signed long Thermometer( int Channel )
{
    const signed long minTemp = -15;    // 測定最低温度
    const long TempData[ 81 ] =         // 温度データ表(-15~64℃)
    {
        0x064F, 0x068F, 0x06D1, 0x0714, 0x0759,
        0x07A0, 0x07E9, 0x0834, 0x0880, 0x08CE,
        0x091D, 0x096D, 0x09BF, 0x0A11, 0x0A65,
        0x0ABB, 0x0B12, 0x0B6B, 0x0BC5, 0x0C1F,
        0x0C7B, 0x0CD7, 0x0D34, 0x0D92, 0x0DF0,
        0x0E4E, 0x0EAF, 0x0F0F, 0x0F72, 0x0FD3,
        0x1033, 0x1095, 0x10F7, 0x1159, 0x11BB,
        0x121C, 0x127E, 0x12DE, 0x1340, 0x13A1,
        0x1400, 0x1460, 0x14BF, 0x151D, 0x157B,
        0x15D8, 0x1634, 0x1690, 0x16EB, 0x1744,
        0x179D, 0x17F4, 0x184A, 0x189F, 0x18F3,
        0x1946, 0x1998, 0x19E9, 0x1A39, 0x1A86,
        0x1AD3, 0x1B1F, 0x1B69, 0x1BB2, 0x1BF9,
        0x1C40, 0x1C85, 0x1CC9, 0x1D0C, 0x1D4D,
        0x1D8D, 0x1DCC, 0x1E09, 0x1E45, 0x1E7F,
        0x1EB9, 0x1EF1, 0x1F28, 0x1F5F, 0x1F93,
        0xFFFF,    // 最後は番兵
    };

    int Count;
    long Data;

    Data = ADConv10( Channel ) * 10;        // アナログ入力 x10

    for( Count = 0; Data >= TempData[ count + 1 ]; Count++ )
    {
        // 温度データ表と比較
    }

    // 測定範囲オーバー
    if( Data < TempData[ 0 ] || Count >= 80 )
    {
        // エラー(コード:0x7FFF)
        return 0x7FFF;
    }

    // 小数点以下計算
    Data -=  TempData[ Count ];
    Data /= ( TempData[ Count + 1 ] - TempData[ Count ] ) / 10;

    // 温度[x10℃] = ((最低温度 + データ位置) * 10) + 少数点以下の値
    return ( minTemp + Count ) * 10 + Data;
}

// =====================================================================
// 湿度 測定
long Hygrometer()
{
    int i;
    long Data;
    long Result = 0;

    // 32回の平均値を測定値とする
    for( i = 0; i < 32; i++ )
    {
        Data = ADConv10( CH_HUM );

        // 湿度100%以上は 測定エラー
        if( Data >= 1000 )
        {
            // エラー(コード:0xFFFF)
            return 0xFFFF;
        }

        Result += Data;
    }

    // 湿度[x10%] = (A/D平均値 - 仮想GND電圧) * 10 / 5
    return ( Result / 32 - 0x0200 ) * 2;
}


// =====================================================================
// LCD表示処理
void DisplayLCD()
{
    long Work;
    lcd_cmd( 0xC0 );

    // 内気温
    printf( lcd_data, "In:" );

    Work = MinusSign( RoomTemp );
    printf( lcd_data, "%2lu.%1luC\xDF ", Work / 10, Work % 10 );

    // 湿度
    if( Humidity == 0xFFFF )
    {
        printf( lcd_data, "error" );    // エラー表示
    }
    else
    {
        printf( lcd_data, "%2lu.%1lu%%", Humidity / 10, Humidity % 10 );
    }
}

// マイナス記号処理
long MinusSign( signed long Data )
{
    if( Data >= 0x0000 )
    {
        // 表示位置を合わせるため符号表示を手動で行う
        printf( lcd_data, " " );
        return Data;
    }
    else
    {
        printf( lcd_data, "-" );

        // 2の補数により絶対値をとる
        return ~Data + 1;
    }
}

temperature-humidity.c