走行速度とエンジン回転数を計測します。そして走行速度から、加速度と走行距離を求めます。
またドアロック制御回路とも接続され、一定速度以上でドアのロック信号を、エンジン停止時にアンロック信号を送ります。
さらに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 ); }