今日、RZ250Rに乗る鎌一さんという方のお宅にお邪魔した。
OSR-CDI Version2.0.0を装着するとタコメータが動かない問題に対処に行ったんだけど、別の大きな課題が発覚したので、一旦そちらはペンディング。
その話はまた別途。

鎌一さんが特別なのは、キャブレターにTM30SS(RGV)を装着していること、そしてSDR利楽猿号にもついているエアソレノイドジェットRASCを作成して装着しているところ。
RASCについてはこの辺参照してください。
IMG_4871
自作のゲタがあるので前傾しているガンマキャブが素晴らしい角度で付いています。
なんと殆ど手やすりらしいです。
IMG_4882
結構分厚いのは、これ以上前に出すとキャブレターがフレームに接触するからとの事。
実際、スレスレの良いクリアランスでした。


さて、単気筒用に設計したRASCは二気筒では回転数算出の計算方法が違うので、RZ250Rでは上手くない部分があります。
その部分について今日鎌市さんに聞かれたので、少し解説します。
以下。

RASCではOSR-CDI等と同じようにPICマイコンのTimer1でクランクが一周する時間を測定しています。
1気筒の場合はクランク1回転につき、1回の信号が来ます。
2気筒の場合は2回の信号が来ます。
以下は1気筒のソースコードです。
void interrupt Interrupt()
{
// Interrupt from Input capture
if(CCP1IF) { // クランク信号が来た
uint16_t ccpr1;

// Reset Timer1
TMR1H=0;
TMR1L=0;
// RPM
// ccpr1という変数にタイマー値を保存する
ccpr1 = ((CCPR1H * 0x100)|CCPR1L) + 1;
// 回転数を計算する
gRPM = (600000UL/ccpr1);
CCP1IF = 0;
}

// Timer1: Timeout means engine stop
// Timer1が満了したら、それは回転数が低すぎるという意味。
// なのでエンジンがストップしたと判断する
if(TMR1IF) {
gRPM = 0;
TMR1IF = 0;
}
}
ここでなんじゃこりゃとなるのが、
gRPM = (600000UL/ccpr1);
の部分だと思います。
600000ULのULは、Unsigned Longの略で、無くても良いんですが、明示的にこれはUnsigned Longなんですよ、とコンパイラに念の為伝えているだけです。
(無くてもたぶんコンパイルは通ります)
なんでTimer1の値で600000を割ると回転数が出るのでしょうか。

例えば、6000rpmで回転するエンジンについて考えてみます。
RASCは8MHzのクロックで動作させています。
(OSR-CDIは16MHzなので数値がまた違います)

このPICマイコンはFOSC/4、つまりクロック動作数の1/4の速度で動作します。
8MHz / 4 = 2MHz
つまり1秒間に2,000,000回命令を実行する事が出来ます。
Timer1のカウンターもこのペースでカウントアップされて行きます。

RASCのソースコードの内、Timer1のセットアップコードは以下の通りです。
// Timer1 Clock Source Select bits
T1CONbits.TMR1CS=0; // 00 = Timer1 clock source is instruction clock (FOSC/4)
T1CONbits.T1CKPS=0x01; // Timer1 Input Clock Prescale Select bits 1:2 Prescale value
T1CONbits.T1OSCEN=0; // Dedicated Timer1 oscillator circuit disabled
T1CONbits.nT1SYNC=1; // 1 = Do not synchronize external clock input
T1CONbits.TMR1ON=0; // Timer1 On bit
Timer1のクロックはFOSC/4で動作し、Prescalerで2回に1回のカウントアップに分周しています。
クロック動作が8MHzで、FOSC/4なので2MHz、プリスケーラーで分周しているので、実質1MHzで動作する事になります。
つまり0.000001秒間隔でカウントアップされて行きます。

6000rpm(回転/分) = 100rps(回転/秒)
つまり
1 / 100rps = 0.01秒間隔でクランクが1回転します。
つまり、Timer1のカウンターの値が毎回
0.01(rps) / 0.000001(s) = 10,000
の時に割り込み処理が入り、ccpr1に入ってくることになります。
結果として、
600,000 / 10,000 = 60
となり、6000rpmと判別できることになります。
(RASCもOSR-CDIも100rpmを1として扱っています)

2気筒の場合、信号が2倍来ますので、Timer1の値は半分になります。
600,000 / 5,000 = 120
つまり倍の回転数と判別します。
正しいですよね。
なので、600,000を300,000に変更します。
300,000 / 5,000 = 60
正しい値が出ました。
つまり
gRPM = (600000UL/ccpr1);

gRPM = (300000UL/ccpr1);
に変更すればOKなんです。

ちなみにOSR-CDIは高速化のために、ちょっとややこしい事をして処理時間の短縮を実現しています。
Unsigned Longは、計算時間がメッチャ掛かるんです。
RASCならそんなんでもちゃんと動くんですが、CDIは動作精度を上げる為に工夫しています。