*** 編輯更新:2026.07.09***
最新參考資料同步更新GitHub:
https://github.com/Jir8taiwan/ST170_ext.control_IMRC
前言,我這台FORD FOCUS MK1 ST170的IMRC模組,雖然因為跳了P1518後換了一顆新的不會再出現警報。
但是後來有明確發現,在引擎啟動時,都沒有做正常的開啟(長通道循環)的運作,造成起步和加速相對無力、以及耗油問題。
看電路圖,猜他可能線組的中繼接頭應該是有接觸不良才造成這樣,但是我也懶得拆在東拆西查修了。
乾脆直接用外掛監控和驅動的方式去控制IMRC模組何時用短通道和長通道。
基本要控制IMRC模組的地方,就是接頭的PIN1(GND)和PIN3(SIGNAL CONTRL)腳。
當訊號接地,他就會做動成長通道模式,適用6000RPM以下的低速扭力需求。
當訊號斷路,他則會恢復放鬆成短通道模式,適用6000-8500RPM的高速吸氣需求。
如果不想要做動,只是要強制ACC後固定長通道,也可以拿一個二極體直接兩腳位導通就好。
NOTE:
1. ACC紅火啟動,PCM會使PIN3導通接地,IMRC模組於1.5s內要拉鋼索,把進氣岐管轉到長通道(扭力模式)。
2. IMRC模組鋼索拉動後,裡面的銅片金屬接點結合,觸發電阻75R迴路給PIN5和PIN6,告知PCM鋼索機構沒有卡住。
(1) 方案一,外部感應轉速訊號,強制IMRC模組不經過PCM控制,導通拉動/放鬆鋼索
修改控制配線圖:
Schematic_ST170_ext.control_IMRC diagram_2026-06-26

利用高壓線圈處理RPM訊號擷取模擬電路圖:
https://is.gd/YLMHyL
需求材料:
Arduino NANO板
HALL感應器模組
1路5V RELAY模組
12V轉5V電源轉換模組
PVC絞線0.5或0.3mm^2,四心線
腳位纜線
配線:
IMRC模組的PIN1(GND)、PIN2(VCC)、PIN3(CONTROL);12V正電和接地接到12V轉5V模組;控制線和接地則分別接到RELAY模組的NC和COM。
HALL感應器模組的正極接3.3V、負極接GND、數位訊號接7號腳。
RELAY模組的正極接12號腳,負極接GND。
12V轉5V模組的USB輸出線,接Arduino NANO板的USB電源線
工作判斷設計原理:
霍爾感應器回饋訊號給7號腳,計算比對當下的引擎轉速值。
判斷當3900RPM於0.5秒後,又超過4000RPM時,則12號腳輸出給RELAY,讓本來PIN1和PIN3短路狀態變斷路。
過程中,發現RELAY會亂做動。
用Serial埠見控數值後,怠速下回饋的RPM轉速訊號計算值會破9000~12000RPM左右的誤差值~XD
看起來我安裝SENSOR的位置,有極大的雜訊會造成干擾誤算。
所以先下一個除以12倍的方式做初步的濾波計算,看起來就能相對正常計算繼電器的啟閉時機了。
等有空一點,改成監控點火電晶體的12V訊號好了。
這個應該不會有周遭電場的雜訊干擾,只是要怎麼監控訊號,又不干擾點火系統的高阻抗電路,我要再想想。
利用EasyEDA軟體製作成品,PDF原始檔連結:
Schematic_ST170_ext.control_IMRC diagram_251113
**此文件已有更新調整接線、公母接頭腳位判讀、BYPASS的繼電器接法。
最新程式碼同步更新在GitHub那裏:https://github.com/Jir8taiwan/ST170_ext.control_IMRC
程式碼:
// ======================================================================
// Ford Focus MK1 ST170 — IMRC 外部主動訊號控制器
// Version 4.0 2026.06.26
// 硬體腳位定義:
// D7 → Hall sensor / 點火訊號輸入(PCM 初級線圈下拉訊號)
// D12 → 繼電器 IN 致能輸出(HIGH = 繼電器動作,LOW = 繼電器關閉)
// OLED(SPI 7-pin SH1106):
// D0=13, D1=11, CS=10, DC=9, Reset=8
// ======================================================================
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9, 8);
// 版本:
IMRCversion = "2026.06.26";
// -----------------------------------------------------------------------
// 腳位定義
// -----------------------------------------------------------------------
const int SIGNAL_PIN = 7; // 點火脈衝訊號輸入腳位
const int RELAY_PIN = 12; // 繼電器 IN 致能輸出腳位
// -----------------------------------------------------------------------
// 脈衝計數設定
// 說明:等到累積 hall_thresh 個脈衝後才計算一次 RPM
// 數值越大,計算越精確,但更新越慢
// -----------------------------------------------------------------------
const float HALL_THRESH = 400.0;
// -----------------------------------------------------------------------
// 脈衝係數設定(依實際接線調整)
// 四缸四行程,抓一個點火訊號:
// 若曲軸每轉 1 圈 D7 收到 1 個脈衝 → PULSE_PER_REV = 1.0
// 若曲軸每轉 1 圈 D7 收到 2 個脈衝 → PULSE_PER_REV = 2.0
// 實車測試時對比儀表板轉速表確認
// -----------------------------------------------------------------------
const float PULSE_PER_REV = 1.0;
// -----------------------------------------------------------------------
// IMRC 作動轉速門檻
// -----------------------------------------------------------------------
const int RPM_THRESHOLD = 6000;
const int RPM_ON_THRESHOLD = RPM_THRESHOLD; // 超過此值 → 繼電器 ON
const int RPM_OFF_THRESHOLD = RPM_THRESHOLD - 200; // 低於此值 → 繼電器 OFF
// 5800 ~ 6000 之間保持上一次狀態
// -----------------------------------------------------------------------
// 全域狀態變數
// -----------------------------------------------------------------------
int current_rpm = 0; // 當前計算 RPM(給 OLED 顯示用)
bool relay_active = false; // 繼電器目前狀態(true = ON)
// ======================================================================
// setup():開機初始化,只執行一次
// ======================================================================
void setup() {
Serial.begin(115200);
// 設定腳位方向
pinMode(SIGNAL_PIN, INPUT); // D7 點火訊號輸入
pinMode(RELAY_PIN, OUTPUT); // D12 繼電器輸出
digitalWrite(RELAY_PIN, LOW); // 開機預設繼電器關閉
delay(100);
// OLED 開機畫面
u8g.firstPage();
do {
u8g.setFont(u8g_font_helvB08);
u8g.drawStr(3, 12, "GitHub: Jir8taiwan");
u8g.drawStr(3, 32, "ST170 IMRC Controller");
u8g.drawStr(3, 52, IMRCversion);
} while (u8g.nextPage());
delay(400);
}
// ======================================================================
// loop():主迴圈,持續執行
// ======================================================================
void loop() {
// --------------------------------------------------------------------
// 第一步:量測 RPM
// 原理:等待 HALL_THRESH 個脈衝,計算這段時間,換算轉速
// PCM 下拉訊號:點火時為 LOW,待機時為 HIGH
// --------------------------------------------------------------------
float hall_count = 0.0;
float start_time = micros();
bool in_pulse = false; // 防止同一個脈衝重複計數
while (true) {
if (digitalRead(SIGNAL_PIN) == LOW) {
// 訊號為 LOW = 點火觸發中
if (!in_pulse) {
in_pulse = true; // 標記:目前在脈衝內
hall_count += 1.0; // 計數加一
}
} else {
// 訊號回到 HIGH = 脈衝結束,重置旗標準備下一次
in_pulse = false;
}
// 累積夠了就跳出,開始計算
if (hall_count >= HALL_THRESH) {
break;
}
}
// --------------------------------------------------------------------
// 第二步:計算 RPM
// 公式:RPM = (脈衝數 / 每轉脈衝數) / 經過秒數 × 60
// --------------------------------------------------------------------
float end_time = micros();
float time_passed = (end_time - start_time) / 1000000.0; // 轉換成秒
current_rpm = (int)((hall_count / PULSE_PER_REV) / time_passed * 60.0);
// 序列埠輸出供除錯監控
Serial.print("Time Passed: ");
Serial.print(time_passed, 3);
Serial.print("s | RPM: ");
Serial.println(current_rpm);
// --------------------------------------------------------------------
// 第三步:依 RPM 控制繼電器輸出
// 邏輯:
// RPM >= RPM_THRESHOLD → 繼電器 ON(IMRC 開啟)
// RPM < RPM_THRESHOLD → 繼電器 OFF(IMRC 關閉)
// 注意:不使用 delay() 做二次確認,因為 delay() 期間
// RPM 不會更新,確認沒有實際意義。
// RPM 本身已是 HALL_THRESH 個脈衝的平均值,穩定性足夠。
// --------------------------------------------------------------------
if (current_rpm >= RPM_ON_THRESHOLD) {
// 轉速超過 6000 RPM → 繼電器 ON
digitalWrite(RELAY_PIN, HIGH);
relay_active = true;
} else {
digitalWrite(RELAY_PIN, LOW);
// 轉速低於 5800 RPM → 繼電器 OFF
relay_active = false;
}
// ---- 序列埠輸出繼電器狀態 ----------------------------
Serial.print("Relay: ");
Serial.println(relay_active ? "ON" : "OFF");
Serial.println("--------------------");
// --------------------------------------------------------------------
// 第四步:更新 OLED 顯示
// 顯示:目前 RPM、繼電器狀態、設定門檻
// --------------------------------------------------------------------
u8g.firstPage();
do {
u8g.setFont(u8g_font_helvR12);
// 第一行:RPM 數值
u8g.drawStr(0, 15, "RPM:");
u8g.setPrintPos(50, 15);
u8g.print(current_rpm);
// 第二行:繼電器狀態
u8g.drawStr(0, 35, "IMRC:");
u8g.setPrintPos(50, 35);
u8g.print(relay_active ? "ON " : "OFF");
// 第三行:設定門檻(確認目前設定值)
u8g.drawStr(0, 55, "SET:");
u8g.setPrintPos(50, 55);
u8g.print(RPM_THRESHOLD);
u8g.print("rpm");
} while (u8g.nextPage());
// 短暫延遲避免 OLED 更新過快造成閃爍
delay(100);
} // loop() 結束
(2) 方案二,保持PCM控制訊號,IMRC模組內部迴路修改,由外掛DC馬達驅動器,導通拉動/放鬆鋼索
看起來IMRC應該是福特早期有設計不良的通病,模組的TIP121更換一陣子後(一年左右),仍然會過熱損壞,造成馬達鋼索無法正常拉動。
也歸咎於近期強大的AI運算能力,和現在ARDUINO/ESP微型控制板的周邊應用模組套件,有類似功能且可靠度也還算不錯的選擇產品變多了。
無意間發現神人Mark Olson的分享資料和電路,分析後看懂這內部的電路結構和早期IC控制的方案。
裡面的馬達控制參數是達到阻轉後,會拉低供應電流,保持恆流約1.2~1.5A。
利用這個物理特性,使用現成的自動升降壓CC CV電源模組(或降壓模組),來直接驅動內部馬達。
修改控制配線圖:
Schematic_IMRCmod_DirectDrive_Motor_2026-07-09

選配的接法,如果想要利用發光LED,去外部可視IMRC模組內部接觸開關的75R迴路,到底有沒被觸發使用的量測修改方案:

IMRC模組需內部修改直接馬達控制供電(若已故障的Q1 TIP121電晶體可以順道移除,使之斷路):



材料:
1. Mini560 Pro 固定5V電源模組
2. 5V Relay 高低電位繼電器模組
3. FP5139 (SJ4) 自動升降壓CC CV模組 (設定12V、1.5A)
或 LM2596 壓降型CC CV模組 (設定1.4V、1.5A、以及加強散熱片)
4. A1015 PNP電晶體 *1
20K 電阻 *1
2K 電阻 *1
5. 6P 車用公插頭、母插座 (拿TOYOTA車種修改) – ** 希望未來有網友能建議對應正確的公母接頭,感激不盡。**
6. 6C或4C+2C 0.75mm(1.25mm)電纜線
7. [選配 – 看75R接合回饋狀態]:
2SC1815 NPN電晶體 *1
33K 電阻 *1 (或47K)
2K 電阻 *1
LED 發光二極體 *1
8. [選配 – CC/CV電源模組加強穩壓抗干擾用]
1000uF 50V 電解電容 *2
103(0.1uF) 陶瓷電容 *2
工作判斷設計原理:
PCM在PIN1 CTRL腳位,會從5V拉低到4V要求IMRC工作,馬達要做動變成長通道模式。
透過A1015電晶體開關迴路,監控此電壓值變化,讓5V繼電器模組可以高電位工作。
5V繼電器導通電壓源給馬達工作,電壓源需要恆壓恆流模擬原始IMRC模組阻轉的工作參數。
FP5139自動升降壓,設定12V供應固定電壓源,然後最大只到1.5A電流給馬達定位後阻轉。
阻轉狀態,內部的訊號回饋電阻75R會被IMRC內部的轉盤機械結構接合處發PIN5 MON和PIN6 RTN迴路,使PCM知道目前已經是長通道狀態。
(3) 方案三,保持PCM控制訊號,IMRC模組整組改成客製全模組直流驅動馬達轉動鋼索機構
(專案計畫建構中)
(4) DELETE RELAY – IMRC模組不使用,要騙PCM電腦訊號的方式
因為PCM拉低電位不是拉到0V的基準,只有ON=4.0V、OFF=5.0V的方式給IMRC模組判斷做動。
所以如果是用4P或5P的DC12V繼電器,會因為負極腳不夠低電位,所以會不吸合。
又因為PCM系統是5V環境、IMRC供電是12V環境,所以要利用一顆PNP和一顆NPN電晶體搭配,做ON/OFF開關電路,這個設計的下拉迴路稍微複雜一點。
但是能透過一顆PNP做PCM控制訊號判斷,狀態投遞給一顆NPN做12V導通,給控制75R電阻接點時機的DC12V型繼電器,回傳訊號給PCM判讀。
這個配線元件修改裝上後,就可以把進氣歧管常態改成固定長通道、或者裝廠外修改套件來使用,讓PCM能抓到岐管位置訊號自動判讀。
BYPASS設計元件模擬運作:
https://is.gd/wWr3L9
PDF檔案下載連結:
Schematic_IMRC_RelayModule_trigger_2026-06-24

其他參考文章:
http://stm32-learning.blogspot.com/2014/05/arduino.html
http://59.126.75.42/blog/blog.php?uid=shadow&id=1862
https://makersportal.com/blog/2018/10/3/arduino-tachometer-using-a-hall-effect-sensor-to-measure-rotations-from-a-fan
https://kokoraskostas.blogspot.com/2013/12/arduino-inductive-spark-plug-sensor.html
https://www.scribd.com/document/758299998/Manual-IMRC
https://img1.wsimg.com/blobby/go/1975f84f-4935-4131-8404-5a914da1afb7/downloads/IMRCAnatomyR1-2.pdf?ver=1677295757783






請問如果用騙的讓p1518不會出現?
就是讓它有一個正確的導通歐姆值和工作時訊號切斷狀態的變化,ECU就會誤以為IMRC是正常的。