車速とエンジン回転数の計測回路

走行速度とエンジン回転数を計測します。そして走行速度から、加速度と走行距離を求めます。

またドアロック制御回路とも接続され、一定速度以上でドアのロック信号を、エンジン停止時にアンロック信号を送ります。

さらにLLC (Long Life Coolant) の量を計測し、残量がわずかとなったときには警告する機能も有します。

プログラム

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

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

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

#device *=16                     // 16bitポインタ指定
#use delay( Clock = 20000000 )   // クロック周波数指定

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

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

// マクロ定義 **************************************************************
#define LED_SPD    PIN_C6
#define LED_REV    PIN_C7
#define LED_LLC    PIN_C5    // LLC残量警告灯

#define LLC_FEW    PIN_A5    // LLC残量検知(残量わずか)
#define LLC_EMP    PIN_A2    //            (残量なし)

#define SIGNAL_MOVEMENT   PIN_B6    // 走行状態信号 出力
#define SIGNAL_PARKING    PIN_B7    // 駐車信号      〃

// プロトタイプ宣言 ********************************************************
void StatusSignal();
void LLC_Warning();

// グローバル変数宣言 ******************************************************
long Speed;         // 車速[mm/s]
long Revolution;    // エンジン回転数[rpm]
signed long Accel;  // 加速度[mG]
int32 Distance;     // 走行距離[mm]

int SpdUpp = 0;
int RevUpp = 0;
const long RunningState = 11111;    // 走行状態 定義定数 [mm/s]


// -------------------------------------------------
#include "i2c.h"    // I2C送受信処理


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

        I2cSlaveSend16( ( long )( Speed * 0.036 ) );    // [mm/s] -> [x0.1km/h]
        I2cSlaveSend16( Revolution );

        Work = Distance / 1000;        // [mm] -> [m] (単位変換)

        I2cSlaveSend16( ( long )( Work >> 16 ) );    // 上位16ビット
        I2cSlaveSend16( ( long )Work );              // 下位16ビット

        I2cSlaveSend16( ( long )Accel );
    }
}

// =====================================================================
// タイマ1割り込み処理 【停車&エンジン停止 検出】【距離&加速度 算出】
#int_timer1
void isr1()
{
    static long BeSpd1, BeSpd2;

    set_Timer1( 0x0BDC );    // 100msec

    // 停車か?
    if( SpdUpp >= 4 )
    {
        Speed = 0;
        SpdUpp = 0xFF;
    }
    else
    {
        SpdUpp++;
    }

    // エンジン停止か?
    if( RevUpp >= 2 )
    {
        Revolution = 0;
        RevUpp = 0xFF;
    }
    else
    {
        RevUpp++;
    }

    // ---------------------------------------------------------------
    // 距離[mm] += ((前速度 + 速度[mm/s]) / 2) x 時間[0.1sec]
    // 計測範囲 : 0 - 2^32[mm] (0 - 4295[km])
    Distance += ( BeSpd1 + Speed ) / 20;        // 数値積分(台形公式)

    // ---------------------------------------------------------------
    // 加速度[mG] = ((速度 - 前々速度[mm/s]) / 1000[mm/s -> m/s]
    //  / 2 x 時間[0.1sec]) / 9.80665[m/s^2 -> G] x 1000[G -> mG]
    Accel = ( ( signed long )Speed - BeSpd2 ) * 0.5099;        // 数値微分(中心差分商)

    BeSpd2 = BeSpd1;
    BeSpd1 = Speed;    // 速度記録
}

// =====================================================================
// CCP1割り込み処理 【車速 計測】
#int_ccp1
void ccp1_isr()
{
    static long KeepTime1;
    long KeepTime2;

    // タイマ値 保存(仮)
    KeepTime2 = CCP_1;


    // 前回は停車状態では?
    if( SpdUpp != 0xFF )
    {
        int32 Data;

        // カウント数 = (オーバーフロー数 x (0x10000-0x0BDC) + タイマ値) - 前タイマ値
        Data = ( ( int32 )SpdUpp * 0xF424 + KeepTime2 ) - KeepTime1;

        // 速度[mm/s] = 60[km/h] / (637/60[rpm -> rps] x 4[Pulse]
        //  x 0.0000016[sec] x カウント数) / 36[km/h -> mm/s]
        // (計測範囲 : 749 - 65535[mm/s] (2.7 - 235.9[km/h])
        Speed = 156250000000.0 / ( float )( Data * 637 );

    }


    // オーバーフローカウンタ リセット
    SpdUpp = 0;

    // タイマ値 保存
    KeepTime1 = KeepTime2;

    output_bit( LED_SPD, ~input( LED_SPD ) );
}

// =====================================================================
// CCP2割り込み処理  【回転数 計測】
#int_ccp2
void ccp2_isr()
{
    static long KeepTime1;
    long KeepTime2;

    KeepTime2 = CCP_2;

    if( RevUpp != 0xFF )
    {
        int32 Data;

        // カウント数 = (オーバーフロー数 x (0x10000-0x0BDC) + タイマ値) - 前タイマ値
        Data = ( ( int32 )RevUpp * 0xF424 + KeepTime2 ) - KeepTime1;

        // 回転数[rpm] = 60 / (カウント数 x (0.0000016[sec] x 2))
        // (計測範囲 : 143 - 65535[rpm])
        Revolution =  18750000 / Data;
    }
    RevUpp = 0;

    // タイマ値 保存
    KeepTime1 = KeepTime2;

    output_bit( LED_REV, ~input( LED_REV ) );
}

/* =====================================================================
    メイン関数
===================================================================== */
void main()
{
    /* ------------------------------------------------------
        A2:LLC_LowLevel
        A5:LLC_HighLevel

        B6:MovementSignal(out)
        B7:ParkingSignal(out)

        C1:'Revolution' Pulse Input(CCP2)
        C2:'Speed' Pulse Input(CCP1)

        C3:I2C_SCL(in)
        C4:I2C_SDA(in)

        C5:LED_LLC
        C6:LED_Speed
        C7:LED_Revolution
    -------------------------------------------------------*/
    set_tris_a( 0b00100100 );
    set_tris_b( 0b00000000 );
    set_tris_c( 0b00011110 );

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

    setup_adc_ports( NO_ANALOGS );    // A/D Converter - OFF
    setup_adc( ADC_OFF);
    // ------------------------------------------------------

    setup_ccp1( CCP_CAPTURE_RE );        // CCP1設定(立ち上がりでキャプチャ)
    setup_ccp2( CCP_CAPTURE_RE );        // CCP2設定()
    setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 );    // タイマ1設定(1.6usec)

    enable_interrupts( INT_CCP1 );      // CCP1
    enable_interrupts( INT_CCP2 );      // CCP2
    enable_interrupts( INT_TIMER1 );    // タイマ1
    enable_interrupts( GLOBAL );        // グローバル割り込み許可


    // 入力信号が安定するまで待つ -----
    output_low( LED_SPD );
    output_low( LED_REV );
    output_low( LED_LLC );

    delay_ms( 1000 );

    output_high( LED_SPD );
    output_high( LED_REV );
    output_high( LED_LLC );
    // --------------------------------

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

    while( 1 )
    {
        // 状態信号出力
        StatusSignal();

        // LLC残量検知
        LLC_Warning();

        delay_ms( 100 );
    }
}

// =====================================================================
// 状態信号出力
void StatusSignal()
{
    // エンジン稼動か?
    if( Revolution )
    {
        output_high( SIGNAL_PARKING );
    }

    // 停車か?
    if( Speed == 0 )
    {
        // 走行信号リセット
        output_low( SIGNAL_MOVEMENT );

        // エンジン停止か?
        if( Revolution == 0 )
        {
            // (停車していなければ認めない)
            output_low( SIGNAL_PARKING );
        }

        return;
    }

    // 規定速度以上か?
    if( Speed > RunningState )
    {
        output_high( SIGNAL_MOVEMENT );
    }
}

// =====================================================================
// LLC残量検知
void LLC_Warning()
{
    // 残量なし
    if( input( LLC_EMP ) )
    {
        // LED点灯
        output_low( LED_LLC );
        return;
    }

    // 残量わずか
    if( input( LLC_FEW ) )
    {
        static int count;

        // LED点滅(1Hz)
        if( count++ < 5 )
        {
            output_low( LED_LLC );
            return;
        }

        if( count >= 10 )
        {
            count = 0;
        }
    }

    output_high( LED_LLC );
}

speed-rev.c