个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Arduino UNO R4(RA4M1)/ 互換環境上で動作するエコラン車両用ECUプログラム
Routine
AGTimer.init による24usec毎処理)WH_PULSE_ISRReadNe_ISR(パルスでクランク角更新)G_PULSE_ISRfastestdigitalWrite / fastestdigitalReadstatusTask : Serial1 出力 100ms 周期 (10Hz) / SerialUSB 出力 500ms 周期 (2Hz)mapConsoleTask : MAP 書き換えコンソールtools/strategy/)tools/send_map.py でそのまま転送できる)PlatformIO 環境: platformio.ini
| Env | ボード | 備考 |
|---|---|---|
uno_r4_minima | Arduino UNO R4 Minima | デフォルト |
rmc_ra4m1_20 | カスタム RA4M1 (-D rmc_ra4m1_20) | SD動作分岐あり |
ビルド例:
pio run -e uno_r4_minima
pio run -t upload
pio device monitor -b 115200
| 項目 | 定義 | 説明 |
|---|---|---|
| ROUTINE_CYCLE_US | 24 | メイン周期 (µs) |
| PERIMETER_MM | 1548 | タイヤ周長(mm) |
| TACHO_RPM_MAX | 6000 | レブリミット (回転数上限保護) |
| Dwell_Time_US | 5000 | ドゥエル時間(us) IGコイルへの充電時間 |
| Dwell_Time_CRANK_US | 6500 | クランキング中(スタータON中)のドゥエル時間(us) スタータ負荷による電圧低下の補償 |
| start_RPM | 1500 | スタータ自動停止の判定回転数(RPM) MAP切替用の専用定数ではない |
始動時・通常時で切り替わる専用定数(start_INJ_time 等)は無い。
燃料噴射量・点火進角・燃料噴射終了タイミングは全て単一の MAP テーブルから rpm に応じて読み出され、ビルドし直さずに USB シリアルから調整できる。
(MAP 節参照)
74HC14 によるシュミットトリガ回路でチャタリング防止・反転入力Nch MOSFET による LOW アクティブ。| 信号 | 物理ピン | 説明 |
|---|---|---|
| NE_A_IN | 2 | クランク角 A (1deg/パルス) |
| NE_B_IN | 8 | クランク角 B (位相判定) |
| NE_Z_IN | 9 | クランク角0deg基準 |
| WH_IN | 3 | 車軸パルス入力 1回転で1パルスIN |
| G_IN | 5 | カムパルス入力 クランク角720°毎に1パルス入力 |
| STR_IN | 6 | エンジンスタートスイッチ(LOW=ON) |
| ENGOFF_IN | 7 | キルスイッチ(LOW=ON=運転状態, HIGH=OFF=停止状態) |
| INJ_OUT | A0 | 燃料噴射(LOW=ON) |
| IGN_OUT | A1 | 点火(LOW=ON) |
| STR_OUT | A2 | スタータリレー(LOW=ON) |
| DISRESET_OUT | A3 | リセットランプ(LOW=点灯, HIGH=消灯) |
| MA735_CS | 10 | MA735 SPI CS |
LOW アクティブ出力注意 (INJ/IGN/STR/DISRESET)。
割り込みで角度/速度更新
ReadNe_ISR: NE_A パルスで Ne_deg ±1 更新(NE_Bの位相参照)
G_PULSE_ISR: カムパルス同期フラグ設定
角度モデルと usecperdig
usecperdig は非エンコーダ・非MA735モード時にのみ補間に使用。Ne_deg += ROUTINE_CYCLE_US / usecperdig (エンコーダ無効かつ MA735無効時)。EncoderEnabled = true のため使用されない(初期値 1.0、無信号タイムアウト時にリセット)。周期関数 Routine:
スタート/キル状態評価
スタータステートマシン (StarterState): キルスイッチON時にスタートボタン押下(エッジ)でクランキング開始。
start_RPM 以上を 0.1秒 維持で始動成功(スタータ自動停止)、1.5秒(STARTER_TIMEOUT_MS)タイムアウトで始動失敗(再押しで再試行可)。
低rpm帯のMAP行(400/800/1200rpm、inj_end_ca=20)が始動用パラメータとして自動的に採用される
(始動専用のMAP切替フラグは無い。MAP 節参照)。
STR_IDLE → [ボタン押下(エッジ)+キルスイッチON] → STR_CRANKING
STR_CRANKING → [start_RPM以上を0.1秒維持] → STR_STARTED(スタータOFF)
STR_CRANKING → [1.5秒タイムアウト] → STR_FAILED(スタータOFF・ENG_ON OFF)
STR_FAILED → [ボタン再押し(エッジ)] → STR_CRANKING
キルスイッチOFF → 常に STR_IDLE へ強制リセット(`Launch` はリセットしない)
カム同期タイムアウト→cycleReset
マップ更新: updateEngineMap
噴射開始条件 (角度 >= INJ_STR_CA、MAP行の inj_end_ca と噴射時間から逆算、0CA跨ぎ対応)
360CA通過時に噴射継続中なら強制OFF(安全リセット)
噴射時間経過で OFF & 燃料量積算
点火進角計算 & 保持時間後 OFF
タスク statusTask:
snprintf + 一括 write)噴射終了角度: calculatedINJ_END_CA(MAPの該当行の inj_end_ca 列をそのまま採用。
始動時・通常時で切り替える専用ロジックは無く、rpmに応じたMAP行選択(MAP 節)に一本化されている)
噴射開始角度: INJ_STR_CA(毎サイクルリセット時に逆算)
INJ_STR_CA = calculatedINJ_END_CA - (calculatedINJ_time * 100[µs] * 360[deg]) / tachoWidth[µs]
// INJ_STR_CA < 0 の場合(0CA跨ぎ): INJ_STR_CA += 720
0CA跨ぎ対応: 噴射開始が720CA付近・終了が次サイクル序盤(例: 716CA→20CA)の場合、
INJ_STR_CA が負値になるため +720 で正規化(0〜720CAの範囲に収める)。
cycleReset() 呼び出し時に噴射継続中(INJ_Status == 2)であれば INJ状態をリセットせず、
タイマーで正常終了させる。
360CA安全リセット: 1サイクル内で360CAを通過した時点でも噴射中の場合は強制OFFし、
意図しない噴射継続を防止(inj360Reset フラグで1サイクルに1回限り実行)。
噴射時間: calculatedINJ_time (0.1ms単位) → 実際 µs: injDuration = calculatedINJ_time * 100
燃料量近似:
gasml += ( (Δt * 0.0000007) + 0.0015 ) / 1.5073
係数は実測燃費から逆算したインジェクタ流量補正。
calculatedIGN_CADwell_Time_US(クランキング中は Dwell_Time_CRANK_US)。適用中の値は Dwell_Time_Act_US
Dwell_Time_CA = Dwell_Time_Act_US * 360 / tachoWidthNe_deg >= (360 - calculatedIGN_CA - Dwell_Time_CA) で点火 LOW360 - calculatedIGN_CA に達する or Dwell_Time_Act_US 経過で HIGH 戻しMAP は RAM 上のダブルバンク(src/map_store.cpp)で保持し、ビルドし直さずに USB シリアル経由で書き換えられる。
参照ロジック: RPM 昇順テーブルの、最初に tachoRpm < rpm となるエントリを採用(階段状)。
行数は可変(最大 24 行)。
列順(CSV / SD 読込も同一。4列必須):
rpm,inj_time(x0.1msec),ign_ca(deg),inj_end_ca(deg)
inj_end_ca(噴射終了タイミング角度、0〜720CA)は、スタートボタン押下直後を含む全rpm帯で共通のMAP行から読み出される。tools/send_map.py --legacy-inj-end-ca <値> で噴射終了角度を明示的に補って送ること(無断補完はしない)。内蔵 defaultMap(src/map_store.cpp)は、400/800/1200/1600rpm をブレークポイントに以下のように構成されている:
| RPM未満 | inj_time | ign_ca | inj_end_ca | 意味 |
|---|---|---|---|---|
| 400 | 0 | 0 | 0 | 400rpm以下はアイドリング不能なのでエンジン停止相当 |
| 800 | 80 | 0 | 20 | 800rpm以下は始動状態 |
| 1200 | 80 | 0 | 20 | 1200rpm以下は始動状態 |
| 1600〜 | 可変 | 可変 | 680 | 通常走行域 |
起動時の優先順位: EEPROM に有効な MAP があればそれを採用、無ければ内蔵 defaultMap へフォールバック。
起動時に MAP SOURCE: EEPROM (15 rows) のようにどちらを使ったか出力する。
書き換えは AGTimer 割り込みから参照されるバンクを非アクティブ側で組み立ててから 1 バイトのストアで切り替えるため、エンジン稼働中でも安全に反映できる。
回転数を見ながら GUI で MAP を詰めるためのWebアプリ(webgui/)。
Windows / macOS / Ubuntu 共通。
接続方法は 2 通りあり、どちらも同じフロントエンドが動く。
| 方法 | 必要なもの | 使えるブラウザ |
|---|---|---|
| GitHub Pages(Web Serial) | なし(ブラウザだけ) | Chrome / Edge |
| ローカルサーバ | Python 3 + pyserial | すべて |
# ローカルサーバ(追加の依存なし。標準ライブラリ + pyserial だけ)
python3 tools/map_gui.py # ポート自動検出、ブラウザを開く
python3 tools/map_gui.py --port /dev/cu.usbmodem1101
python3 tools/map_gui.py --fake # 実機なしでGUIを試す(モックECU)
GitHub Pages 版は https://todateman.github.io/UNOR4_Chibi-T_EFI/ で、
Chrome / Edge の「Web Serial で接続」から直接 USB に繋がる。
外部 CDN を一切使っておらず Service Worker を積んであるので、一度開けばピットでオフラインでも動く。
Pages 版にはローカルサーバが居ないため、「ローカルサーバ経由」「モック ECU」のボタンは
自動的に無効になる(起動時に /api/status の応答を確かめている)。
公開するには初回だけ次の 2 つが必要。
GitHub Actions にするwebgui/ を含む変更を main へマージするmain への push でのみ動く。Deploy Web GUI to Pages → Run workflow)デプロイ前にテスト(node --test と test_map_protocol.py)が走り、失敗すると公開されない。
できること:
microSD/RPM_*.CSV と同じ書式)噴射終了角のグラフ にチェックで 3 枚目が出る)20 → 680 の境界で補間が逆回りしてしまう)MAP SET で送る。安全のために GUI 側で次を強制している。
MAP SAVE は eng=OFF かつ rpm=0 のときだけ押せる。ERR ENGINE_RUNNING が返ることがあるので最大 5 回リトライするMAP SET は該当 RPM が無いと行を挿入する仕様なので、走行中に意図せずテーブル構造が変わるのを防ぐTACHO_RPM_MAX = 6000)より手前だと警告する。mapOutOfRange)ためNe_deg >= 360 で噴射中なら強制 OFF する(360CA 安全リセット)ので、その行は MAP の指示より噴射が短くなる。inj_time × 100[us] × 360 / tachoWidth で角度に直し、その行が受け持つ最大 rpm で最悪値を見る。inj と rpm を合わせて初めて実害が見えるので、列単体の範囲検査では拾えないテストは実機なしで走る。
node --test "webgui/test/*.test.mjs" # 検証規則・CRC・編集操作・行分類
python3 tools/test_map_protocol.py # プロトコル往復(モックECU)
microSD/RPM_*.CSV と同じ書式の CSV をそのまま送れる。pyserial が必要。
プロトコルの実装は tools/map_protocol.py にあり、Web GUI と共有している。
pip install pyserial
# 転送のみ(RAM へ反映。電源を切ると元に戻る)
python tools/send_map.py microSD/RPM_2026SUZUKA.CSV
# 転送 + EEPROM へ保存(エンジン停止時のみ)
python tools/send_map.py microSD/RPM_2026SUZUKA.CSV --save
# 現在の MAP を吸い出す
python tools/send_map.py --dump > current_map.csv
# 状態確認 / ポート明示
python tools/send_map.py --info
python tools/send_map.py map.csv --port /dev/cu.usbmodem1101
# 実機なしで動作確認(モックECU)
python tools/send_map.py microSD/RPM_2026SUZUKA.CSV --fake
# 3列(旧書式)CSVを送る場合は噴射終了角度を明示的に補う
python tools/send_map.py microSD/RPM_2024MOTEGI.CSV --legacy-inj-end-ca 680
送信前にファームと同じ規則で検証し、通らない CSV は実機に触れる前に弾く。
転送後は MAP INFO の CRC と自前の計算値を突き合わせて検証し、不一致なら非ゼロ終了する。
シリアルモニタから手打ちでも操作できる(src/map_console.cpp)。
応答は必ず 1 行の OK ... / ERR ...。
| コマンド | 動作 | 稼働中 |
|---|---|---|
MAP? | 現在の MAP を CSV で出力(4列) | 可 |
MAP INFO | 出所 / 行数 / CRC / EEPROM 状態 / RPM / ENG を表示 | 可 |
MAP BEGIN | 転送セッション開始(USB テレメトリを一時停止) | 可 |
<rpm>,<inj>,<ign>,<inj_end_ca> | セッション中の 1 行(RPM で始まるヘッダ行は自動スキップ。4列必須) | 可 |
MAP END | 検証して原子的に反映。失敗時は破棄され現在の MAP は無傷 | 可 |
MAP ABORT | セッション破棄 | 可 |
MAP SET <rpm> <inj> <ign> <inj_end_ca> | 1 行だけライブ変更(該当 RPM が無ければ昇順を保って挿入) | 可 |
MAP SAVE | EEPROM へ保存(既存内容と同一なら書き込まず OK UNCHANGED) | 不可 |
MAP LOAD | EEPROM から読み直して RAM へ反映 | 可 |
MAP DEFAULT | 内蔵 defaultMap へ戻す(EEPROM は変更しない) | 可 |
TELEM ON [ms] | 機械可読テレメトリを開始(既定 OFF、100〜2000ms、100ms 単位) | 可 |
TELEM OFF | 停止して従来の 2Hz 人間向け出力へ戻す | 可 |
TELEM? | on= / ms= / drop=(取りこぼし数)を表示 | 可 |
VER | OK VER <fw> proto=<n>(現行 1.4.0 / proto=5。v3 で MAP を 4 列化、v4 でテレメトリに inj_end を追加、v5 で inj_end を ign の直後へ移動) | 可 |
PING | OK PONG(副作用のない疎通確認・レイテンシ計測) | 可 |
DIAG | 直前のリセット原因(rst=POR/PIN/WDT/SW/LVD/UPLOAD)、自動リセットの累計(count=)、記録した異常(fault=HARD/STACK、pc= / lr= / cfsr= / hfsr= / exc= / task=)、積算値を引き継いだか(carry=)を表示 | 可 |
src/health.cpp が WDT(約 1.4 秒)を回す。Routine(AGT 割込み)と statusTask の両方が動いているときだけ更新するので、どちらが止まってもリセットして、スタータ操作を受け付ける状態に戻る。
HardFault とスタックあふれ(configCHECK_FOR_STACK_OVERFLOW=2)は、PC・例外番号(exc=0 はタスク、16+n は IRQn)・タスク名を VBATT バックアップレジスタに記録してからリセットする。
落ちた箇所は arm-none-eabi-addr2line -e .pio/build/uno_r4_minima/firmware.elf <pc> で引ける。
自動リセット(WDT / SW)のときだけ、走行時間・距離・燃料を引き継ぐ。ロガーの周回数を 0 に戻さないためで、リセットボタン(PIN)・電源投入(POR)・書き込み(UPLOAD)では従来どおり 0 から始める。
セッションを開いたままホストが消えた場合に備え、最終受信から 5 秒で ERR SESSION_TIMEOUT を返してセッションを破棄する。
(テレメトリがミュートされたまま復帰しなくなるのを防ぐ)
TELEM)GUI のライブトレース用に、statusTask の高速パス(100ms 周期)から出力する。
既定は OFF なので、tools/send_map.py やシリアルモニタの見え方は従来どおり変わらない。
TELEM ON の間は 2Hz の人間向けタブ行を止め、2 つの書式が混ざらないようにする。
T\t<seq>\t<ms>\t<rpm>\t<inj01>\t<ign>\t<inj_end>\t<spd01>\t<ne>\t<row>\t<flags>
| 欄 | 内容 | 単位 |
|---|---|---|
seq | 連番(uint16 wrap)。取りこぼし検出に使う | — |
ms | millis() | ms |
rpm | tachoRpm | RPM |
inj01 | calculatedINJ_time | ×0.1ms |
ign | calculatedIGN_CA | CA |
inj_end | calculatedINJ_END_CA(MAP 範囲外では前回値が残る) | CA |
spd01 | speed | ×0.1km/h |
ne | Ne_deg | CA |
row | 採用中の MAP 行 index(255 = MAP 未使用。始動時・範囲外) | — |
flags | bit0 ENG_ON / bit1 Launch / bit2 クランキング / bit3 mapOutOfRange | — |
send_map.py が「タブを含む行=テレメトリ」として
読み飛ばす実装だから。inj / ign / inj_end)を隣り合わせに並べた(proto=5 で inj_end を末尾から移動)。spd 以降が黙って 1 列ずれる)。map_gui.py は VER の proto を見て、5 未満のファームには TELEM ON を送らず、2Hz の旧形式表示にフォールバックする。ign の隣に差し込むと row と flags が黙ってずれるので、順序は変えない。calculatedINJ_END_CA は MAP 範囲外でもゼロクリアされない。updateEngineMap() は inj/ign だけ 0 にする)mapOutOfRange で止まるので実害は無いが、値としては前回値が残るため GUI は row=255 のとき表示しない。snprintf が %.1f 非対応なのに合わせてある。row をファームから出しているのは、GUI が「実機が実際に採用した行」を推測せずに
表示できるようにするため。startState == LOW)も rpm に応じた同じ MAP テーブルを参照するが、始動直後は rpm の変動が大きく PC 側の推測は容易にズレるため、ファーム自身が報告する row を信用する設計にしてある。write() はホストが接続したまま読まないと FIFO が空くまで無限にスピンする。usbLock を握ったままそうなるとコンソールが応答しなくなるため、 Serial.availableForWrite() で空きを確認してから書き、足りなければそのサンプルを捨てる。seq の飛びで GUI が検出できる)MAP END / MAP SAVE 時に以下を検査し、1 つでも違反したら全体を破棄する(部分適用しない)。
inj_time 0〜255(x0.1ms → 最大 25.5ms)ign_ca 0〜90(CA)inj_end_ca 0〜720(CA。クランク角のフルサイクル、0CA跨ぎ対応と整合)EEPROM ライブラリ経由で使用。defaultMap へ自動フォールバックする。MAP SAVE は書き込み前に EEPROM 上の内容と行数 / CRC / エントリ本体を突き合わせ、同一なら書き込みを行わず OK UNCHANGED を返す(データフラッシュの摩耗対策)。EEPROM.put を使うこと。EEPROM.update はバイト単位 API で、差分 1 バイトごとに 1KB ページの消去+書き込みが走るため摩耗対策として逆効果になる。MAP SAVE はエンジン停止時(ENG_ON == false かつ tachoRpm == 0)のみ受理し、それ以外は ERR ENGINE_RUNNING を返す。SDMapEnabled / parseCSV() のスタブは残してあり、実装時は mapParseCsvLine() / mapStagingAppend() / mapStagingApply() をそのまま再利用できる。Increase_Fuel 分岐位置あり(未実装)CSV パース・検証ルール・バンク切替・send_map.py のプロトコルはホスト側のテストで確認済み。
以下は実機でしか確認できない項目なので、車両に載せる前に順に潰すこと。
1 → 8 の順(無負荷 → クランキング → 実走)で進めると手戻りが少ない。
検証結果(Ardu-Stim + オシロによる代替検証、発見した不具合と修正内容を含む):
pio run -t upload
pio device monitor -b 115200
MAP SOURCE: DEFAULT (15 rows) が出るMAP SAVE 済みなら MAP SOURCE: EEPROM (n rows) が正しいMAP INFO で src= / eeprom= を確認できるMAP? の出力が src/map_store.cpp の defaultMap[] と一致するHELP でコマンド一覧が出るpython tools/send_map.py microSD/RPM.CSV
RAMへ反映しました(読み戻し検証OK) が出て終了コード 0MAP? が RPM.CSV の内容(INJ=110 系)になっているSerial1(メーター・ロガー)側の CSV 出力は途切れないpython tools/send_map.py microSD/RPM_2026SUZUKA.CSV --save
EEPROMへ保存しました が出るMAP SOURCE: EEPROM (15 rows)MAP? が 2026SUZUKA の内容MAP DEFAULT → MAP? が既定値 → MAP LOAD → MAP? が EEPROM の内容に戻るArdu-Stim で回転信号を与えるか、実際にクランキングした状態で:
MAP SAVE → ERR ENGINE_RUNNING が返るMAP SET 3200 45 26 680 → OK SET が返り、MAP? に即反映されるMAP BEGIN 〜 MAP END の一括転送が稼働中でも通り、反映されるMAP SET / MAP END の実行前後でエンジンが失火・ストールしない ← 最重要printf 'RPM,INJ,IGN\n3000,40,20\n1000,40,20\n' > /tmp/bad_order.csv
python tools/send_map.py /tmp/bad_order.csv # ERR RPM_NOT_ASCENDING で非ゼロ終了
ign_ca 91 以上 のいずれでも MAP END が ERR を返すMAP? の内容が転送前から変化していない「デバッグ」節の Ardu-Stim + DHO804 の構成で、変更前のファームと比較する:
INJ_OUT(A0) / IGN_OUT(A1) のタイミングが変更前と一致MAP SET 実行の瞬間に噴射パルスが1サイクル内で分断・二重化しないMAP SAVE(停止時)中に Ne_deg のカウント抜けが無い(未検証、理由は検証結果ドキュメント参照)--save で EEPROM に焼き、再起動して MAP INFO の crc= を記録python tools/send_map.py --dump の出力が意図した CSV と一致TACHO_RPM_MAX = 6000)付近で MAP 最終行を超えたとき、
calculatedINJ_time / calculatedIGN_CA が 0 になり燃料噴射・点火が止まるWH_IN・実負荷・実燃料噴射量)は Ardu-Stim では代替不可のため未検証。実車で確認すること。Ardu-Stim で回転信号を与えつつ、STR_IN/ENGOFF_IN 相当を操作する:
start_RPM(1500) 以上へスイープしながら STR_IN を ON → STR_OUT が LOW になり、
start_RPM 到達から約100ms 後に STR_OUT が HIGH に戻る(STR_STARTED)start_RPM 未満に維持したまま STR_IN を ON → STR_OUT が LOW になってから
2000ms 後に STR_OUT が HIGH に戻る(STR_FAILED)STR_FAILED 状態で STR_IN を離さず維持 → 再クランキングしない(エッジ検出のみで再始動する設計の確認)74HC14 シュミットトリガを経由せず
MCUへ直結されるため、ボタン押下中に生ピンが数千回/秒オーダーでチャタリングし、
OFF→ONエッジが繰り返し検出されて STR_FAILED から STR_CRANKING へ誤って再突入し続ける
(実測: 1秒保持で生値が約1万回反転)。シュミットトリガ回路を通す実車配線での再検証が必要。STR_FAILED 後に STR_IN を一度離してから再度 ON → STR_CRANKING へ再遷移し STR_OUT が再度 LOW になるSTR_IDLE に戻るLaunch 連動の積算)が途切れない
(キルスイッチOFFで Launch はリセットされない仕様の確認)EEPROM を完全な未書き込み状態へ戻すコマンドは用意していない。
既定値へ戻したい場合はMAP DEFAULT→MAP SAVE(出所はEEPROMのままになる)。
sbi/cbi 直接制御R_PORTx->PODR_bdigitalWrite/digitalReadクリティカル区間 (割り込み内) の遅延最小化に寄与。
AGTimer: AGTimer.init(period_us, callback)
本プロジェクトでは 24µs 周期で Routine 呼び出し。
周波数変更は ROUTINE_CYCLE_US を調整。
statusTask (Serial1: 100ms(10Hz) / SerialUSB: 500ms(2Hz), 優先度 2, スタック 256 words)mapConsoleTask (5ms, 優先度 1, スタック 256 words)Serial) 出力は両タスクで共有するため、mapConsoleUsbLock() / mapConsoleUsbUnlock() で排他する。statusTask の USB テレメトリを停止する(Serial1 側は常時出力)。statusTask のスタック 256 words は snprintf 浮動小数点フォーマット分を含む。追加タスクは xTaskCreate で拡張可能。スタック追加時は増量推奨。| ポート | 形式 | 周期 | フィールド | 出力先 |
|---|---|---|---|---|
Serial1 (HW UART) | CSV + XORチェックサム | 10Hz (100ms) | RPM, INJ(ms), IGN_CA, INJ_END(CA), speed, distance, fuel(ml), km/L, worktime(s, 0.1s分解能) | ロガー (ESP32) https://github.com/todateman/Chibi-T_Furoshiki_Logger |
Serial (USB CDC) | タブ区切り | 2Hz (500ms) | 上記 + Ne_deg | PC (USB) |
Serial1 の行末は *XX(XX = 先頭から * 直前までの全バイトのXOR、16進2桁)。
ロガーは不一致の行を捨てる。INJ_END(CA) は MAP 範囲外では前回値が残る。
エンジン停止中(ENG_ON=false: キルスイッチOFF・スタータ待機・始動失敗)は、INJ(ms) / IGN_CA / INJ_END(CA) を 0 で出力する。
ロガー側でエンジン停止状態を判別できる(USBテレメトリは MAP 参照値のままで、flags の bit0 が ENG_ON)。
INJ_END を IGN_CA の直後に挿入したため、EFI とロガーは必ず同時に更新する(旧形式とは非互換)。
speed は 0.1km/h 分解能。停止時は最終パルス経過時間で減衰し、約8秒後に 0.0 へ。
document/Arduino_ECU_Workflow.pumljebbs.plantuml)を使用して開く。java -jar "$env:USERPROFILE\.vscode\extensions\jebbs.plantuml-2.18.1\plantuml.jar" -tsvg document/Arduino_ECU_Workflow.puml
start_RPM×0.1秒維持で自動停止、1.5秒タイムアウトで失敗検出・再試行可。始動専用MAPフラグは廃止しMAP方式に一本化)parseCSV) ※ SD が使えるようになったら mapParseCsvLine() を再利用updateAFR)| フラグ | 影響 |
|---|---|
uno_r4_minima | 自動 (PlatformIO env) |
rmc_ra4m1_20 | SD 初期化ブロック有効 |
Ardu-Stimのdevelop/furoshikiブランチにあるfuroshiki_2025のパターンと、visa-mcpによるオシロスコープの制御を組み合わせて、ECUプログラムのデバッグを行う。
USB0::6833::1101::DHO8A253701207::0::INSTRMAP? で吸い出せる。EEPROMに保存済みなら defaultMap ではなくそちらが使われている点に注意)INJ_OUTとIGN_OUTの信号出力を開始しないので、手動で実行する。評価結果:
phases に周ごとのパターンを書いてある)python3 tools/strategy_sim.py optimize # 加速位置・停止速度・感度を出す
python3 tools/strategy_sim.py --params tools/strategy/practice_motegi_2026.json plan # 練習走行のプランを確かめる
python3 tools/test_strategy_sim.py # テスト(走行ログ不要)
実車/燃焼系制御へ適用する際は下記を検討:
DIAG CLEAR |
| 記録と自動リセットの累計を消す |
| 可 |
DIAG HANG / DIAG FAULT | 自動復旧の確認用に、わざとハング/HardFault を起こす | 不可 |
HELP | コマンド一覧 | 可 |