FlashProにはスマホアプリ(有料)があって、そのアプリではエンジン等の状態を確認できるようになっている。有料かつスマホを車内で使うのも面倒だという理由から手を出してない。たまたまHondataのサイトを徘徊していた際に、Bluetooth接続の解説資料を見つけたので、それを参考に手作りのOBD2メーターをベースにしてハード改造なしにFlashProとBluetooth接続できそうだし、OBD2通信よりも高速かつ多様な情報を提供してくれそうなので試してみることにした。
以下を元手に今回の企画を進めていく。
まずは、Bluetooth接続そのものができないと話が始まらない。FlashProのBluetoothが「FlashProManager」の「FlashPro」「Bluetooth」タブで有効になっていることを確認したら、下記プログラムを(Arduino-IDE)でESP32に書き込んでみよう。
※ところで、これってどうやって作ったんだ? ChatGPTに教えてもらったような気もするが、全然覚えてない。
#include "BluetoothSerial.h" // "BluetoothSerial" by Henry Abrahamsen
#include "BLEDevice.h" //
BluetoothSerial SerialBT;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
SerialBT.print("BLE Advertised Device found: ");
SerialBT.println(advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32_BT_Scanner");
Serial.println("Starting device scan...");
SerialBT.println("Starting device scan...");
BLEDevice::init("");
}
void loop() {
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
// Wait for scan to complete
delay(5000);
}
実行するとシリアルモニタに近くで見つかったBluetooth機器が表示されるはずだ。その中に「FlashPro」(デフォルト名称はこれのはず)があればBluetoothが使える状態になっているってことだ。
次は、取得可能なデータの確認だ。必要な情報を抽出しておこう。
// FlashPro_test01 Get Channel Info
#include "BluetoothSerial.h" // Bluetoothserial by Henry Abrahamsen
#define MAX_DATA_SIZE 200
uint8_t Address[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; // FlashProのBluetooth用のMACアドレス(実機に合わせて修正)
const char *PIN = "1234"; // FlashProへのBluetooth接続用PINコード(実機に合わせて修正)
String myName = "ESP32"; // my Bluetooth name
uint8_t CMD[] = {0x00, 0x31, 0x04, 0x00}; // 送信コマンド Get channel Info
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
bool connected;
SerialBT.begin(myName, true);
Serial.println("Bluetooth starting...");
SerialBT.setPin(PIN);
connected = SerialBT.connect(Address);
Serial.println("Connecting to FlashPro with PIN_code ... ");
while(!SerialBT.connected(10000)) {}
if(connected) {
Serial.println(": Connected Successfully!");
} else {
Serial.println(": Failed to connect.");
}
}
void loop() {
Serial.println("send cmd");
SerialBT.write(CMD, sizeof(CMD));
Serial.print("Recieve ");
uint8_t receivedData[MAX_DATA_SIZE];
size_t dataSize = 0;
while (SerialBT.available() && dataSize<MAX_DATA_SIZE) {
receivedData[dataSize] = SerialBT.read();
Serial.print(receivedData[dataSize], HEX);Serial.print(" ");
dataSize++;
}
Serial.println(" ");
delay(1000);
}
これを実行すると以下のレスポンスがシリアルモニタに表示された。
send cmd
Recieve 0 31 82 0 0 1 83 1 1 84 2 1 42 10 1 85 20 1 47 22 1 47 12 1 58 13 1 96 30 1 88 40 1 49 50 1 50 60 1 50 11 2 49 10 2 49 20 3 9E 22 3 9E 30 3 52 32 3 52 40 3 41 10 3 58 10 4 4B 12 4 51 70 1 46 80 1 59 0 2 41 21 4 82 22 4 82 23 4 82 24 4 82 11 4 49 61 1 50 51 1 50 14 1 85 15 2 49 14 2 49 91 1 A0 A0 1 A1 A1 1 A1 15 1 85 90 1 A0 16 1 91 3 B 51
これは以下の意味を持っている。
値 | 意味 | ||||||||
---|---|---|---|---|---|---|---|---|---|
0 | Protocol header(固定値) | ||||||||
31 | Get Channel Info(を示すコマンド。送信に対するレスポンスで同じ値が返ってくる) | ||||||||
82 0 | レスポンス全体のバイト数。 「下位 上位」の順。今回は、0x0082=130バイト | ||||||||
0 1 83 1 1 84 ... | 対応しているデータの種類(3バイトで一つのデータを示す)と、データ取得時の各データの順番。今回はこのデータ部分が126バイトなので取得できるデータは42種類だ。
|
上記レスポンスを「Hondata Bluetooth Protocol」の「3.1 Channel Contents」「3.2 Channel Sizes」「3.3 Channel Data Types」のあたりを参照して整理しよう。
アドレス | 名称 | 内容 | バイト数 | 単位系 | FL1でのデータ順 |
---|---|---|---|---|---|
0x0100 | CID_RPM | エンジン回転数 | 2 | 0x03 | 1 |
0x0101 | CID_Speed | 車速 | 2 | 0x04 | 2 |
0x0102 | CID_Gear | ギヤ | 1 | 0x02 | 3 |
0x0110 | CID_MAP | インマニ圧(絶対値) | 2 | 4 | |
0x0111 | CID_MAPVoltage | MAP voltage | |||
0x0112 | CID_AFMVoltage | AFM voltage | 1 | 0x18 | 7 |
0x0113 | CID_AFMFlow | エアフロ流量値 | 2 | 0x16 | 8 |
0x0114 | CID_BP | 2 | 0x05 | 33 | |
0x0115 | CID_BPCMD | 2 | 0x05 | 39 | |
0x0116 | CID_AirCharge | 2 | 0x11 | 41 | |
0x0117 | CID_AFMFreq | ||||
0x0120 | CID_TPS | スロットルポジション | 1 | 0x07 | 5 |
0x0121 | CID_TPSVoltage | TPS voltage | |||
0x0122 | CID_ThrottlePlate | スロットルバルブ開度 | 1 | 0x07 | 6 |
0x0130 | CID_Inj | Injector duration | 2 | 0x08 | 9 |
0x0131 | CID_InjPhase | Injector phase | |||
0x0132 | CID_Duty | Injector duty | |||
0x0133 | CID_Inj_2 | ||||
0x0140 | CID_Ign | Ignition advance | 1 | 0x09 | 10 |
0x0141 | CID_IgnDwell | Ignition dwell | |||
0x0150 | CID_IAT | 吸気温度 | 1 | 0x10 | 11 |
0x0151 | CID_IAT_2 | 吸気温度2 | 1 | 0x10 | 32 |
0x0160 | CID_ECT | 冷却水温 | 1 | 0x10 | 12 |
0x0161 | CID_ECT2 | 冷却水温2 | 1 | 0x10 | 31 |
0x0162 | CID_ECTCorrection | 冷却水修正値 | |||
0x0163 | CID_IATCorrection | 吸気温度修正値 | |||
0x0170 | CID_PA | Atmospheric pressure | 1 | 0x06 | 23 |
0x0180 | CID_BatteryVoltage | Battery | 1 | 0x19 | 24 |
0x0190 | CID_FuelPressureCmd | 2 | 0x20 | 40 | |
0x0191 | CID_FuelPressure | 2 | 0x20 | 36 | |
0x0192 | CID_FuelDuty | ||||
0x0198 | CID_OilPressure | ||||
0x01A0 | CID_WasteGateCMD | 2 | 0x21 | 37 | |
0x01A1 | CID_WasteGate | 2 | 0x21 | 38 | |
0x0200 | CID_VTS | VTEC spool | 1 | 0x01 | 25 |
0x0201 | CID_VTP | VTEC pressure | |||
0x0210 | CID_VTC_Cmd | VTC command | 1 | 0x09 | 14 |
0x0211 | CID_VTC_Actual | VTC actual | 1 | 0x09 | 13 |
0x0212 | CID_VTC_Duty | VTC duty | |||
0x0213 | CID_VTC_Phase | VTC phase | |||
0x0214 | CID_EXVTC_Cmd | 1 | 0x09 | 35 | |
0x0215 | CID_EXVTC_Actual | 1 | 0x09 | 34 | |
0x0300 | CID_O2A_V | O2A voltage | |||
0x0301 | CID_O2A_C | O2A current | |||
0x0302 | CID_O2A_Heat | O2A heater | |||
0x0303 | CID_O2A_Heat_R | O2A heater resistance | |||
0x0310 | CID_O2B_V | O2B voltage | 1 | 0x18 | 20 |
0x0311 | CID_O2B_Heat | O2B heater | |||
0x0320 | CID_Lambda_Lambda | 空燃比λ | 2 | 0x1E | 15 |
0x0321 | CID_Corr_Lambda | Corrected lambda | |||
0x0322 | CID_Target_Lambda | λの狙い値 | 2 | 0x1E | 16 |
0x0323 | CID_Lambda_Lambda_2 | ||||
0x0324 | CID_Target_Lambda_2 | ||||
0x0328 | CID_Wideband_V | Wideband voltage | |||
0x0329 | CID_Wideband_Lambda | Wideband lambda | |||
0x0330 | CID_ShortTermTrim | Short term trim | 1 | 0x12 | 17 |
0x0331 | CID_MedTermTrim | Medium term trim | |||
0x0332 | CID_LongTermTrim | Long term trim | 1 | 0x12 | 18 |
0x0333 | CID_ShortTermTrim_2 | ||||
0x0334 | CID_LongTermTrim_2 | ||||
0x0340 | CID_ClosedLoopStatus | Closed loop status | 1 | 0x01 | 19 |
0x0341 | CID_ClosedLoopStatus_2 | ||||
0x0400 | CID_KnockLevel | Knock level | |||
0x0401 | CID_KnockVoltage | Knock voltage | |||
0x0402 | CID_KnockThreshold | Knock threshold | |||
0x0410 | CID_KnockRetard | Knock retard | 1 | 0x0B | 21 |
0x0411 | CID_KnockLimit | Knock ignition limit | 1 | 0x09 | 30 |
0x0412 | CID_KnockControl | Knock control | 1 | 0x11 | 22 |
0x0420 | CID_KnockCount | Knock count | |||
0x0421 | CID_KnockCount1 | Knock #1 | 2 | 0x02 | 26 |
0x0422 | CID_KnockCount2 | Knock #2 | 2 | 0x02 | 27 |
0x0423 | CID_KnockCount3 | Knock #3 | 2 | 0x02 | 28 |
0x0424 | CID_KnockCount4 | Knock #4 | 2 | 0x02 | 29 |
0x0425 | CID_KnockCount5 | Knock #5 | |||
0x0426 | CID_KnockCount6 | Knock #6 | |||
0x0430 | CID_KnockRetard1 | ||||
0x0431 | CID_KnockRetard2 | ||||
0x0432 | CID_KnockRetard3 | ||||
0x0433 | CID_KnockRetard4 | ||||
0x0500 | CID_ACSwitch | AC switch | |||
0x0501 | CID_SCS | Service connector | |||
0x0502 | CID_BrakeSwitch | Brake switch | |||
0x0503 | CID_ClutchIn | Clutch in | |||
0x0504 | CID_PSP | Power steering pressure | |||
0x0505 | CID_ELD_Voltage | Electrical load voltage | |||
0x0506 | CID_ELD_Current | Electrical load current | |||
0x0600 | CID_ACClutch | AC clutch | |||
0x0601 | CID_CheckEngine | Check engine | |||
0x0602 | CID_FuelPump | Fuel pump | |||
0x0603 | CID_ReverseLock | Reverse lock | |||
0x0604 | CID_AltControl | Alternator control | |||
0x0605 | CID_IAB | Secondary runners | |||
0x0606 | CID_RadFan | Radiator fan | |||
0x0700 | CID_Datalogging | Datalogging | |||
0x0701 | CID_SecondaryTables | Secondary tables | |||
0x0702 | CID_SecondaryInjector | ||||
0x0710 | CID_RevLimiter | Rev limiter | |||
0x0711 | CID_IgnitionCut | Ignition cut | |||
0x0712 | CID_BoostCut | Boost cut | |||
0x0713 | CID_LaunchCut | Launch cut | |||
0x0714 | CID_LaunchRetard | Launch retard | |||
0x0715 | CID_ShiftCut | Shift cut | |||
0x0720 | CID_PurgeDuty | Purge duty | |||
0x0721 | CID_PurgeOpen | Purge open | |||
0x0730 | CID_BoostControl_Duty | Boost control duty | |||
0x0740 | CID_FTP | Fuel tank pressure | |||
0x0800 | CID_Nitrous1Arm | Nitrous 1 arm | |||
0x0801 | CID_Nitrous1On | Nitrous 1 on | |||
0x0810 | CID_Nitrous2Arm | Nitrous 2 arm | |||
0x0811 | CID_Nitrous2On | Nitrous 2 on | |||
0x0820 | CID_Nitrous3Arm | Nitrous 3 arm | |||
0x0821 | CID_Nitrous3On | Nitrous 3 on | |||
0x0900 | CID_AnalogInput1 | Analog 1 | |||
0x0901 | CID_AnalogInput2 | Analog 2 | |||
0x0910 | CID_AN0 | Analog input 0 | |||
0x0911 | CID_AN1 | Analog input 1 | |||
0x0912 | CID_AN2 | Analog input 2 | |||
0x0913 | CID_AN3 | Analog input 3 | |||
0x0914 | CID_AN4 | Analog input 4 | |||
0x0915 | CID_AN5 | Analog input 5 | |||
0x0916 | CID_AN6 | Analog input 6 | |||
0x0917 | CID_AN7 | Analog input 7 | |||
0x0920 | CID_DI0 | Digital input 0 | |||
0x0921 | CID_DI1 | Digital input 1 | |||
0x0922 | CID_DI2 | Digital input 2 | |||
0x0923 | CID_DI3 | Digital input 3 | |||
0x0924 | CID_DI4 | Digital input 4 | |||
0x0925 | CID_DI5 | Digital input 5 | |||
0x0926 | CID_DI6 | Digital input 6 | |||
0x0927 | CID_DI7 | Digital input 7 | |||
0x0A00 | CID_TC_Speed_LF | Traction control speed LF | |||
0x0A01 | CID_TC_Speed_RF | Traction control speed RF | |||
0x0A02 | CID_TC_Speed_LR | Traction control speed LR | |||
0x0A03 | CID_TC_Speed_RR | Traction control speed RR | |||
0x0A10 | CID_TC_Slip | Traction control slip | |||
0x0A11 | CID_TC_Turn | Traction control turn | |||
0x0A12 | CID_TC_OverSlip | Traction control over slip | |||
0x0A20 | CID_TC_Output | Traction control output | |||
0x0A21 | CID_TC_Volts | Traction control voltage | |||
0x0A30 | CID_TC_Retard | Traction control retard | |||
0x0A31 | CID_TC_RevLimiter | Traction control rev limiter | |||
0x0B00 | CID_FuelLevel | Fuel level | |||
0x0B01 | CID_FuelEconomy | Fuel economy | |||
0x0B02 | CID_FuelUsed | Fuel used | |||
0x0B03 | CID_EthanolContent | 1 | 0x11 | 42 | |
0x0B04 | CID_FuelTemp | ||||
0x0B05 | CID_ABS_Speed_LF | ||||
0x0B06 | CID_ABS_Speed_RF | ||||
0x0B07 | CID_ABS_Speed_LR | ||||
0x0B08 | CID_ABS_Speed_RR | ||||
0x0B10 | CID_SteeringAngle | ||||
0x0B11 | CID_SteeringTorque | ||||
0x0B12 | CID_BrakePressure | ||||
0x0B13 | CID_ClutchPosition | ||||
0x0B20 | CID_GLat | ||||
0x0B21 | CID_GLong | ||||
0x0B22 | CID_YawRate |
数値 | 名称 | データ長 | 換算 | 単位 |
---|---|---|---|---|
0x00 | CT_UNKNOWN | 未定義 | 未定義 | |
0x01 | CT_BIT | byte | 1:ON,0:OFF | |
0x02 | CT_NUMBER | byteまたはword | ||
0x03 | CT_RPM | word | 値/4 | rpm |
0x04 | CT_SPEED | word | 値 | km/hr |
0x05 | CT_MBAR | word | 値 | mbar |
0x06 | CT_KPA | byte | 値/2 | kPa[abs] |
0x07 | CT_TPS | byte | 0.5*値-20 | % |
0x08 | CT_INJ | word | 値/1000 | msec |
0x09 | CT_IGN | deg(カム角度) | ||
0x0B | CT_RETRAD | byte | 値/64 | deg(遅角) |
0x10 | CT_TEMP | byte | 5*(値-32)/9 | ℃ |
0x11 | CT_PCT | byte | 100*値/256? | % |
0x12 | CT_PCT_SIGNED | byte | 100*値/128-100? | % |
0x13 | CT_PCT_CHG | word | 値/100 | % |
0x16 | CT_MASSFLOW | エアフロ流量 | 値 | mg/sec |
0x18 | CT_5V | byte | 5*値/256 | V |
0x19 | CT_19V | byte | 6+値/20 | V |
0x1E | CT_LAMBDA | 値/32768 | - | |
0x20 | CT_BAR | word | 値 | bar |
0x21 | CT_MM | 値/1000 | mm | |
0x22 | CT_GFORCE | word | ||
0x23 | CT_SOGNED | byteまたはword | ||
0x24 | CT_SIGNED100 | byteまたはword |
ここまでくれば、データ取得コマンドを発行するだけである。上の「取得可能なデータの確認」のソースコード10行めを、「Hondata Bluetooth Protocol」の「2.4 Datalogging Packets」を参考に変更するだけでデータ取得できるぞ。
// FlashPro_test01 Get Channel Info
#include "BluetoothSerial.h" // Bluetoothserial by Henry Abrahamsen
#define MAX_DATA_SIZE 200
uint8_t Address[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; // FlashProのBluetooth用のMACアドレス(実機に合わせて修正)
const char *PIN = "1234"; // FlashProへのBluetooth接続用PINコード(実機に合わせて修正)
String myName = "ESP32"; // my Bluetooth name
uint8_t CMD[] = {0x00, 0x35, 0x04, 0x00}; // 送信コマンド Datalog transmit packet
: 以下同一
send cmd
Recieve 0 35 40 0 8C 10 0 0 1 F0 0 14 1B 0 20 1 A4 3 2D 33 71 14 14 7C 80 84 81 7C 7D 1 2 0 8C CA A8 0 0 0 0 0 0 0 0 0 7A 30 30 EB 3 14 14 28 0 3D 1F 40 1F E8 3 2 0 BD 6 0
このレスポンスを整理してみよう。それぞれの値のデータ種への割り付けは、前項とリンクしているぞ。
レスポンス | データ種類 | 値 |
---|---|---|
0 | ヘッダー | |
35 | Datalog:0x35 | |
40 | 受信データバイト数(下位) | 0x40=64バイト |
0 | 受信データバイト数(下位) | |
8C 10 | 回転数 | (0x108C)/4=1509[rpm] |
0 0 | 車速 | 0x0000=0[km/hr] |
1 | ギヤ | 0x01=1[取得できてないかも] |
F0 0 | インマニ絶対圧 | 0x00F0=240[mbar] |
14 | スロットルポジション | 0.5*(0x14)-20=-10[%] |
1B | スロットルバルブ開度 | 0.5*(0x1B)-20=-6.5[%] |
0 | エアフロ電圧 | 0x00=0[V] |
20 1 | エアフロ流量 | 0x0120=288[mg/sec] |
A4 3 | 燃料噴射 | 0x03A4=932=0.932[msec] |
2D | 点火進角 | 0x2D=45[??] |
33 | インマニ温度 | 0x33=51[゚F]=10.6[℃] |
71 | 冷却水温 | 0x71=113[゚F]=45[℃] |
14 | VTC actual | 0x14=20[deg] |
14 | VTC command | 0x14=20[deg] |
7C 80 | 空燃比λ | (0x807C)/32768=1.004 |
84 81 | λの狙い値 | (0x8184)/32768=1.035 |
7C | Short term trim | 100*(0x7C)/128-100=3.13 |
7D | Long term trim | 100*(0x7D)/128=-2.34 |
1 | Closed loop status | 0x01="ON" |
2 | O2B voltage | 5*(0x02)/256=0.039[V] |
0 | Knock retard | (0x00)/64=0[deg] |
8C | Knock control | 100*(0x8C)/256=54.7[%] |
CA | 大気圧 | (0xCA)/2=101[kPa] |
A8 | バッテリー電圧 | 6+(0xA8)/20=14.4[V] |
0 | VTEC spool | 0x00="OFF" |
0 0 | Knock #1 | 0x0000=0 |
0 0 | Knock #2 | 0x0000=0 |
0 0 | Knock #3 | 0x0000=0 |
0 0 | Knock #4 | 0x0000=0 |
7A | Knock ignition limit | 0x7A=122[deg]? |
30 | 冷却水温2 | 5*(0x30-32)/9=10[℃] |
30 | 吸気温度2 | 5*(0x30-32)/9=10[℃] |
EB 3 | CID_BP | 0x03EB=1003[mbar] |
14 | EXVTC_Actual | 0x14=20[deg]? |
14 | EXVTC_Cmd | 0x14=20[deg]? |
28 0 | FuelPressure | 0x0028=40[bar] |
3D 1F | WasteGateCMD | (0x1F3D)/1000=7.997[mm] |
40 1F | WasteGate | (0x1F40)/1000=8.000[mm] |
E8 3 | BPCMD | 0x03E8=1000[mbar] |
2 0 | FuelPressureCmd | 0x0002=2[bar] |
BD 6 | AirCharge | 100*(0x06BD)/256=1725[%]? |
0 | EthanolContent | 100*(0x00)/256=0[%]? |
とまぁ、こんな感じとなる。これでデータが取得できたたので、『OBD2実践編4:OBD2データロガーVer2』のプログラムをベースに、Bluetooth接続を追加・CAN通信を削除・データ取得部分を追加、すれば出来上がりだ。