推定、誰も関心が無いと思われる話。

CDI内部のマイコンは8Mhzで駆動するPIC12F683です。
今回はそれでCDIの進角制御しようとしています。
pic12f683
画像は秋月電子から。
ちなみに今回のCDIは全て秋月電子と千石電商で買えます。

このマイコンはUSB接続が出来ませんので最終的にはUSB対応のPICに移行しますが、これは一個100円でして、壊しても大して痛くありません。
アナログ回路の確認をするにはとっても都合がよろしいのです。

さて、今回は備忘録含めたPICの割り算の話。

PIC12F683は内部クロック利用時に最大8Mhzで動作します。
外部クロックで20Mhz出すことができますが、まぁ色々制限も付くのでこれはやりません。

8MhzのPICは、ひとつの命令を0.5usで処理します。
ちなみに単位は1us = 0.001ms = 0.000001sで表しています。
動作速度としては結構早い気がします。

エンジン内部のピックアップから流れる電気信号がマイコンに入力されると、マイコンはタイマーを使ってしばらく待ち、その後サイリスタゲートに対して電圧を与えることによって、プラグを発火します。

SDRのバヤイ、マイナスの電圧がBTDC70度にやってきます。
つまりクランク角度としてピストンの上死点より70度程前の圧縮工程時にピックアップ信号がきます。
当然ながらBTDC70度は進角させすぎなので、これをBTDC10〜30度程度まで遅らせます。
ピストンが上死点に来る少し前にプラグで点火すると、ピストンが上死点から下降するタイミングに爆発による衝撃波がピストンのヘッドを叩くイメージです。

無題


ピックアップ信号から発火タイミングまでの間、つまりクランク角度として10〜30度遅らせる為には、PIC側でエンジン回転数を知る必要があります。
たとえば6,000rpmで回っているエンジンは、一分間に6,000回程回転しています。
一秒間に100回転。100Hzです。

2ストの場合毎回爆発しますから、一回転、つまり爆発の間隔は1/100 = 0.01s = 10msです。
ちなみに一周は360度ですから一度進む時間は10ms/360度=0.0277ms = 27usです。

こうなってくると、1サイクルを0.5usで実行するマイコンでも、時間を気にする必要が出てきます。
BTDC70からBTDC30までは40度。
6,000rpmで回っている場合、40度進む時間は約1111.1us です。
マイコンは0.5usで1命令を処理しますので、40度進む間に処理できる命令は大体2,000回になります。

2,000回も処理できるなら、まぁ何とかなるんではないか、、、と思いますが、意外と注意してないと簡単に2000回は使い切ってしまいますので、色々と工夫が必要になってきます。
(アセンブラじゃなくてC言語で書いているからとか、まぁそんな理由もありますけれども)
12,000rpm回っている時は1,000回しか命令を処理出来ませんし。

PICの開発環境であるMPLABには、この処理回数を測定するシミュレータが搭載されています。
このシミュレータを使って動作速度をチコチコと測定してますと、やっぱりというかなんというか、割り算で結構処理時間を食ってました。

当初、回転数算出に32ビット整数値を使って以下のように記述してました。
(1) gRPM = 60000000UL/((CCPR1H*0x100)+CCPR1L);
CCPR1H/CCPPR1Lは、16ビットタイマーの値です。
これは、YPVS12Fでも使っている式なのですが、8MhzのPICでgRPMに回転数が入力されます。
これの計算に必要な時間は2000rpm時に600us前後でした。
これではちょっと使えません。 

なので少し精度を落として16ビット整数値で計算してみました。
(2)gRPM = (unsigned)0xE4E1/(unsigned)CCPR1H*4;
これで300usです。
必要な処理時間はおよそ半分になりました。
16ビットに桁落ちさせたというよりは、割り算の分子を小さくしたのが大きく響いています。

しかしそれでもまだ長い。

次に精度を無視して、回転数を0~15の範囲で出力する様にしてみます。
マイコンの中で、割り算は引き算とビットシフトの組み合わせで構成されてますから、引き算の回数を減らした訳です。
式(1)(2)では、回転数を0〜15000で出してました。これの桁を1/1000にした結果は以下。
(3)gRPM = 60000/((CCPR1H*0x100)+CCPR1L);
この結果は564usです。
結構かかっている理由を調べてみると理由は符号無し(unsigned)にしなかったからの様です。

符号付き、符号無しの割り算は処理が全く違ってきます。
なので、これを符号無しにして計算してみます。
(4)gRPM = (unsigned)60000/((CCPR1H*0x100)+CCPR1L);
これで73us。符号の有り無しでおよそ8倍の速度になりました。

もっとも時間のかかる割り算の処理を73usにまで抑える事が出来ました。
ちなみに式(4)は12,000rpmの時には125.5us必要となってきます。
1,000rpmあたり10.5usですね。
あまり拘らないなら許容範囲ですが、12,000rpm時は、この時間にクランクが8~9度程回ってしまう時間です。


ほんのちょっとした事で点火時期は1度2度位簡単に変わります。
マイコン毎に割り込み処理に必要な時間も変わってきます。
これぞ組み込みワールド。
マルチタスクマルチスレッド等の便利な機能を持つOSに慣れていた自分にとっては、結構新鮮な感じですね。