・もしかして、AIを使えば難しいプログラミングも不要なのでは…?
バイクの主流がインジェクション車になって20年近く経ちます。一部の人気車種ならサブコンがメーカーから出ていますが、そうでない車種が多いのも事実。それじゃあ自分でECUを自作して進角制御や燃料噴射量の制御、はたまたリミッター解除をしよう!となるのですが、20年が経過した今でもネット上で検索してもきちんとまとまった情報は出てきません。(やっている人は何人かいるようですが)
自分も昔挑戦して、結局諦めていました。
これの失敗の原因は後程触れますが、何せ当時は手に入れられる情報量が少なすぎた。
しかし今は最先端のツールがあります。それがAI!!
これに相談しながらトライ&エラーを繰り返し、制作していきます。CHATGPTとGeminiを使いましたがGeminiがおすすめです(チャッピーはすぐ口答えする)。
・今回使用したもの
・ArduinoR4minima
・スズキ アドレスV50(CA44A)
・フォトカプラ(PIC817)
・抵抗器10kΩ,100Ω
・ショットキーバリアダイオード(11EQS03L)
・12V-5Vレギュレータ(BP2593-50)
・ほか配線やテスターなど
・まずエンジンの回転数を検出しよう
これができないと点火も燃料噴射も始まりません。
「ただのタコメーターでしょ?」と思う方も多いかもしれませんが、最近インジェクション車のフライホイールは歯が複数個付いています。(初期のインジェクション車は歯が
一つでした)クランク角度を正確に認識するためなのですが、これが厄介です。
先ほどのアドレスV125の記事も、ピックアップコイル(VRセンサー)の数を一つだけだと勘違いして設計したためクランク1回転でとんでもない量の火花を飛ばす点火回路になっていました。(それじゃあ動くわけない)
単純に1回転1パルスならピックアップからのノイズの除去だけで制御が済むのですが、今回10個の信号と欠歯(歯と歯の感覚が広い部分)を検出してクランク角がどこにあるのか正確に判断しなければいけません。

そこのところをGeminiと対話して作ったコードがこちら
const int INPUT_PIN = 2;
volatile unsigned long lastPulseTime = 0;volatile unsigned long firstPulseTime = 0;volatile unsigned long rotationPeriod = 0;volatile bool newRotation = false;volatile int pulseCount = 0;
const int PULSES_PER_ROTATION = 9; // レッツ4仕様(10-1欠歯)const unsigned long DEADBAND_TIME = 1000;
void onPulse() {unsigned long currentTime = micros();unsigned long interval = currentTime - lastPulseTime;if (interval > DEADBAND_TIME) {if (pulseCount == 0) {firstPulseTime = currentTime;}pulseCount++;if (pulseCount >= PULSES_PER_ROTATION) {rotationPeriod = currentTime - firstPulseTime;newRotation = true;pulseCount = 0;}lastPulseTime = currentTime;}}
void setup() {Serial.begin(9600);pinMode(INPUT_PIN, INPUT_PULLUP);attachInterrupt(digitalPinToInterrupt(INPUT_PIN), onPulse, FALLING);Serial.println("=================================");Serial.println(" レッツ4 RPMメーター (バグ修正版)");Serial.println("=================================");}
void loop() {unsigned long safeLastPulseTime;
// 1. 変数データの安全なコピー(データの衝突を防ぐ)noInterrupts();safeLastPulseTime = lastPulseTime;interrupts();
// 2. 停止判定(判定時間を2.5秒に延長し、安全にコピーした時間で比較)if (micros() - safeLastPulseTime > 2500000) {static unsigned long lastZeroPrint = 0;if (millis() - lastZeroPrint > 1000) {Serial.println("RPM: 0 (Engine Stopped)");lastZeroPrint = millis();}return;}
// 3. クランク1回転の計算if (newRotation) {unsigned long currentPeriod;
// ここでも安全にデータをコピーnoInterrupts();newRotation = false;currentPeriod = rotationPeriod;interrupts();if (currentPeriod > 0) {float rpm = 60000000.0 / currentPeriod;static unsigned long lastPrintTime = 0;if (millis() - lastPrintTime > 200) {Serial.print("クランク1回転の時間: ");Serial.print(currentPeriod);Serial.print(" us | ");Serial.print("RPM: ");digitalWrite(IGNITION_PIN, LOW);isDwelling = false;}}
こうなります。

こんな具合です。
現時点では点火回路が完成していないので、仮で13番のLEDをチカチカさせているだけ。実際に点火するかまでは確認していません。
この辺り自分もあまり詳しくはないので、AIの言いなりです。何か実際の走行でトラブルが起こる可能性も十分あり得ます。
・おわりに
久しぶりにarduinoを使いましたが、やっぱり自分で(AIの力を借りながらですが)何かを作るのって面白い!
仕事そっちのけで何時間もパソコンとバイクの前で試行錯誤するのは大変ですが、うまく動いてくれた時の達成感はたまらないものがあります。
次は実際に点火させてエンジンを始動させる事、そしてインジェクターの制御まで進みたいと思っています。詳しい人がいましたら改善案やコメントお待ちしております!

つづく
*1:int)rpm);





























