diff --git a/.vscode/settings.json b/.vscode/settings.json index d8b89b9..eb4dad2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,11 @@ "*.tcc": "cpp" }, "C_Cpp.codeAnalysis.clangTidy.checks.disabled": [ - "clang-diagnostic-error", "clang-diagnostic-error" + ], + "github.codespaces.defaultExtensions": [ + + "GitHub.codespaces", + "GitHub.vscode-pull-request-github" ] } \ No newline at end of file diff --git a/code/DAQ_System/DAQ_System.ino b/code/DAQ_System/DAQ_System.ino index e965695..92b692c 100644 --- a/code/DAQ_System/DAQ_System.ino +++ b/code/DAQ_System/DAQ_System.ino @@ -44,15 +44,33 @@ DHT dht(DHTPIN, DHTTYPE); // —————————————————————————————————————————————————————————————————————————————— // CAN Interface Configuration // —————————————————————————————————————————————————————————————————————————————— -#define INT32U unsigned long int DFRobot_MCP2515 CAN(17); // Set CS to pin 17 const int CAN_INT_PIN = 20; -INT32U canId = 0x000; +// Current Firmware Version +char FW_Version[] = "Alpha"; +// Incoming CAN-BUS message +long unsigned int canId = 0x000; +// This is the length of the incoming CAN-BUS message unsigned char len = 0; +// Default reply ECU ID +#define REPLY_ID 0x7E8 +// This the eight byte buffer of the incoming message data payload unsigned char buf[8]; +String canMessageRead = ""; +// MIL on and DTC Present +bool MIL = true; char str[20]; -String BuildMessage = ""; int MSGIdentifier = 0; +// Stored Vechicle VIN +unsigned char vehicle_Vin[18] = "1WK58FB1111111111"; +// Stored Calibration ID +unsigned char calibration_ID[18] = "FW00116MHZ1111111"; +// Stored ECU Name +unsigned char ecu_Name[19] = "OPENECUSIM"; +// OBD standards https://en.wikipedia.org/wiki/OBD-II_PIDs#Service_01_PID_1C +int obd_Std = 11; +// Fuel Type Coding https://en.wikipedia.org/wiki/OBD-II_PIDs#Fuel_Type_Coding +int fuel_Type = 4; // —————————————————————————————————————————————————————————————————————————————— // ADXL345 Acceleration Sensor Configuration @@ -197,6 +215,7 @@ void setup() pinMode(MOSDOWN_PIN, OUTPUT); pinMode(DiagEN, INPUT); Serial.begin(115200); + delay(100); dht.begin(); // DHT Sensor Begin RPulse.begin(8000); // CPS Pulse A/D Converter Begin if (!accel.begin()) @@ -206,9 +225,9 @@ void setup() while (1) ; } - //accel.setRange(ADXL345_RANGE_16_G); - // accel.setRange(ADXL345_RANGE_8_G); - // accel.setRange(ADXL345_RANGE_4_G); + // accel.setRange(ADXL345_RANGE_16_G); + // accel.setRange(ADXL345_RANGE_8_G); + // accel.setRange(ADXL345_RANGE_4_G); accel.setRange(ADXL345_RANGE_2_G); Serial.println("-----ADXL345 STATUS-----"); /* Display some basic information on this sensor */ @@ -217,7 +236,6 @@ void setup() displayDataRate(); displayRange(); Serial.println(""); - while (CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k Serial.println("CAN BUS Shield init fail"); @@ -226,181 +244,328 @@ void setup() delay(3000); digitalWrite(obled, LOW); } + Serial.println("——————————————————————————————————————————————————————————————————————————————"); + Serial.println("* SKIDAQ " + String(FW_Version) + " *"); + Serial.println("* By Rick Spooner https://github.com/WonITKorea *"); + Serial.println("* Based on Open-Ecu-Sim-OBD2-FW *"); + Serial.println("* By Rick Spooner https://github.com/spoonieau *"); + Serial.println("——————————————————————————————————————————————————————————————————————————————"); delay(3000); } + +// —————————————————————————————————————————————————————————————————————————————— +// Define ECU Supported PID's +// —————————————————————————————————————————————————————————————————————————————— + +/* Define the set of PIDs for MODE01 you wish you ECU to support. For more information, see: +// https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_00 +// +// PID 0x01 (1) - Monitor status since DTCs cleared. (Includes malfunction indicator lamp (MIL) status and number of DTCs.) +// | PID 0x05 (05) - Engine Coolant Temperature +// | | PID 0x0C (12) - Engine RPM +// | | |PID 0x0D (13) - Vehicle speed +// | | ||PID 0x0E (14) - Timing advance +// | | |||PID 0x0F (15) - Intake air temperature +// | | ||||PID 0x10 (16) - MAF Air Flow Rate +// | | ||||| PID 0x1C (28) - OBD standards this vehicle conforms to +// | | ||||| | PID 0x51 (58) - Fuel Type +// | | ||||| | | +// v V VVVVV V v +// 10001000000111110000:000000010000000000000:0000000000000000100 +// Converted to hex, that is the following four byte value binary to hex +// 0x881F0000 0x00 PID 01 -20 +// 0x02000000 0x20 PID 21 - 40 +// 0x04000000 0x40 PID 41 - 60 + +// Next, we'll create the bytearray that will be the Supported PID query response data payload using the four bye supported pi hex value +// we determined above (0x081F0000): + +// 0x06 - additional meaningful bytes after this one (1 byte Service Mode, 1 byte PID we are sending, and the four by Supported PID value) +// | 0x41 - This is a response (0x40) to a service mode 1 (0x01) query. 0x40 + 0x01 = 0x41 +// | | 0x00 - The response is for PID 0x00 (Supported PIDS 1-20) +// | | | 0x88 - The first of four bytes of the Supported PIDS value +// | | | | 0x1F - The second of four bytes of the Supported PIDS value +// | | | | | 0x00 - The third of four bytes of the Supported PIDS value +// | | | | | | 0x00 - The fourth of four bytes of the Supported PIDS value +// | | | | | | | 0x00 - OPTIONAL - Just extra zeros to fill up the 8 byte CAN message data payload) +// | | | | | | | | +// V V V V V V V V*/ +byte mode1Supported0x00PID[8] = {0x06, 0x41, 0x00, 0x88, 0x1F, 0x00, 0x00, 0x00}; +byte mode1Supported0x20PID[8] = {0x06, 0x41, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00}; +byte mode1Supported0x40PID[8] = {0x06, 0x41, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00}; + +/* Define the set of PIDs for MODE09 you wish you ECU to support. +// As per the information on bitwise encoded PIDs (https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_00) +// Our supported PID value is: +// +// PID 0x02 - Vehicle Identification Number (VIN) +// | PID 0x04 (04) - Calibration ID +// | | PID 0x0C (12) - ECU NAME +// | | | +// V V V +// 01010000010 // Converted to hex, that is the following four byte value binary to hex +// 0x28200000 0x00 PID 01-11 + +// Next, we'll create the bytearray that will be the Supported PID query response data payload using the four bye supported pi hex value +// we determined above (0x28200000): + +// 0x06 - additional meaningful bytes after this one (1 byte Service Mode, 1 byte PID we are sending, and the four by Supported PID value) +// | 0x41 - This is a response (0x40) to a service mode 1 (0x01) query. 0x40 + 0x01 = 0x41 +// | | 0x00 - The response is for PID 0x00 (Supported PIDS 1-20) +// | | | 0x28 - The first of four bytes of the Supported PIDS value +// | | | | 0x20 - The second of four bytes of the Supported PIDS value +// | | | | | 0x00 - The third of four bytes of the Supported PIDS value +// | | | | | | 0x00 - The fourth of four bytes of the Supported PIDS value +// | | | | | | | 0x00 - OPTIONAL - Just extra zeros to fill up the 8 byte CAN message data payload) +// | | | | | | | | +// V V V V V V V V*/ +byte mode9Supported0x00PID[8] = {0x06, 0x49, 0x00, 0x28, 0x28, 0x00, 0x00, 0x00}; + // —————————————————————————————————————————————————————————————————————————————— // Main(Loop) Area // —————————————————————————————————————————————————————————————————————————————— void loop() { - // DHT Area - // —————————————————————————————————————————————————————————————————————————————— - int h = dht.readHumidity(); // Gets Humidity value - int t = dht.readTemperature(); // Gets Temperature value - // Check if any reads failed and exit early (to try again). - if (isnan(h) || isnan(t)) - { - Serial.println("DHT Error: Failed to read from DHT sensor!"); - return; - } - // Printing Values for Monitoring - // Serial.print("Humidity: "); - // Serial.print(h); - // Serial.print("% Temperature: "); - // Serial.print(t); - // —————————————————————————————————————————————————————————————————————————————— - - // —————————————————————————————————————————————————————————————————————————————— - // ADXL345 Acceleration Sensor - // —————————————————————————————————————————————————————————————————————————————— + ////Build setting return msg + byte obd_Std_Msg[8] = {4, 65, 0x1C, (byte)(obd_Std)}; + byte fuel_Type_Msg[8] = {4, 65, 0x51, (byte)(fuel_Type)}; + sensors_event_t event; accel.getEvent(&event); - // Display the results (acceleration is measured in m/s^2) - // Serial.print("X: "); - // Serial.print(event.acceleration.x); - // Serial.print(" "); - // Serial.print("Y: "); - // Serial.print(event.acceleration.y); - // Serial.print(" "); - // Serial.print("Z: "); - // Serial.print(event.acceleration.z); - // Serial.print(" "); - // Serial.println("m/s^2 "); + unsigned int engine_Coolant_Temperature = random(1, 200); // Set to random until measuring Actual value + int rpm = random(1, 55); + int vehicle_Speed = random(0, 255); + unsigned int intake_Temp = random(0, 255); + int maf_Air_Flow_Rate = random(0, 255); + int acelx = event.acceleration.x; + int acely = event.acceleration.y; + int acelz = event.acceleration.z; + int ControlAirTemp = dht.readTemperature(); + int OBTemp = picoTemp; + int ControlHumidity = dht.readHumidity(); + int timing_Advance = 10; + + // Work out eng RPM + float rpm_Val = rpm * 4; + unsigned int rpm_A = (long)rpm_Val / 256; + unsigned int rpm_B = (long)rpm_Val % 256; + // Work out MAF values + float maf_Val = maf_Air_Flow_Rate * 100; + unsigned int maf_A = (long)maf_Air_Flow_Rate / 256; + unsigned int maf_B = (long)maf_Air_Flow_Rate; + + // Build sensor return msg + byte engine_Coolant_Temperature_Msg[8] = {3, 65, 0x05, (byte)(engine_Coolant_Temperature + 40)}; + byte engine_Rpm_Msg[8] = {4, 65, 0x0C, (byte)rpm_A, (byte)rpm_B}; + byte vehicle_Speed_Msg[8] = {3, 65, 0x0D, (byte)(vehicle_Speed)}; + byte timing_Advance_Msg[8] = {3, 65, 0x0E, (byte)((timing_Advance + 64) * 2)}; + byte intake_Temp_Msg[8] = {3, 65, 0x0F, (byte)(intake_Temp + 40)}; + byte maf_Air_Flow_Rate_Msg[8] = {4, 65, 0x10, (byte)maf_A, (byte)maf_B}; + + // Serial return message + String reply; // CAN Area - // Sensor Value conversion - char rndCoolantTemp = random(1, 200); // Set to random until measuring Actual value - char rndRPM = random(1, 55); - char rndSpeed = random(0, 255); - char rndIAT = random(0, 255); - char rndMAF = random(0, 255); - char acelx = event.acceleration.x; - char acely = event.acceleration.y; - char acelz = event.acceleration.z; - char ControlAirTemp = t; - char OBTemp = picoTemp; - char ControlHumidity = h; - - // Normal CAN Message Configuration - unsigned char normal1MSG[8] = {rndCoolantTemp, rndRPM, rndSpeed, rndIAT, rndMAF, ControlAirTemp, ControlHumidity, 0}; - unsigned char normal2MSG[4] = {acelx, acely, acelz, 1}; - CAN.sendMsgBuf(0x0, 0, 8, normal1MSG); - delay(200); - CAN.sendMsgBuf(0x1, 0, 4, normal2MSG); - delay(200); - - // GENERAL Sensor ROUTINE - unsigned char SupportedPID[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - unsigned char MilCleared[7] = {4, 65, 63, 34, 224, 185, 147}; - - // OBD2 Mode Configuration - // SENSOR CAN Message Setup - unsigned char dCoolantTemp[7] = {4, 65, 5, rndCoolantTemp, 0, 185, 147}; - unsigned char drpm[7] = {4, 65, 12, rndRPM, 224, 185, 147}; - unsigned char dvspeed[7] = {4, 65, 13, rndSpeed, 224, 185, 147}; - unsigned char dIATSensor[7] = {4, 65, 15, rndIAT, 0, 185, 147}; - unsigned char dMAFSensor[7] = {4, 65, 16, rndMAF, 0, 185, 147}; - unsigned char dBoardAirTemp[7] = {4, 65, 70, ControlAirTemp, 0, 185, 147}; - unsigned char dControlHum[7] = {4, 65, 71, ControlHumidity, 0, 185, 147}; - unsigned char dAcelxdir[7] = {4, 65, 77, acelx, 224, 185, 147}; - unsigned char dAcelydir[7] = {4, 65, 78, acely, 224, 185, 147}; - unsigned char dAcelzdir[7] = {4, 65, 79, acelz, 224, 185, 147}; - unsigned char dAcelall[7] = {4, 65, 80, acelx, acely, acelz, 147}; - - DIAGENB = digitalRead(DiagEN); // When Diag Pin toggled to on - - if (DIAGENB == 1) + if (CAN_MSGAVAIL == CAN.checkReceive()) { - Serial.println("OBD-2 Diag Mode Enabled"); - } - while (DIAGENB == 1) - { - - if (CAN_MSGAVAIL == CAN.checkReceive()) { - CAN.readMsgBuf(&len, buf); - canId = CAN.getCanId(); - Serial.print("<"); - Serial.print(canId); + + CAN.readMsgBufID(&canId, &len, buf); + // https://en.wikipedia.org/wiki/OBD-II_PIDs#CAN_(11-bit)_bus_format + + Serial.print("Received: "); + Serial.print(canId, HEX); Serial.print(","); - for (int i = 0; i < len; i++) + for (int i = 0; i < 3; i++) + { + canMessageRead = canMessageRead + buf[i] + ","; + } + Serial.println(canMessageRead); + //================================================================= + // Return CAN-BUS Messages - SUPPORTED PID's + //================================================================= + + if (canMessageRead == "2,1,0,") { - BuildMessage = BuildMessage + buf[i] + ","; + CAN.sendMsgBuf(REPLY_ID, 0, 8, mode1Supported0x00PID); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)mode1Supported0x00PID)); + Serial.println("Reply: " + reply); + reply = ""; } - Serial.println(BuildMessage); - // Check wich message was received. - if (BuildMessage == "2,1,0,0,0,0,0,0,") + if (canMessageRead == "2,1,32,") { - CAN.sendMsgBuf(0x7E8, 0, 8, SupportedPID); + CAN.sendMsgBuf(REPLY_ID, 0, 8, mode1Supported0x20PID); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)mode1Supported0x20PID)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,1,0,0,0,0,0,") + + if (canMessageRead == "2,1,64,") { - CAN.sendMsgBuf(0x7E8, 0, 7, MilCleared); - Serial.println("OBD-2 Diag Mode Cleared"); - delay(100); - BuildMessage = ""; - break; + CAN.sendMsgBuf(REPLY_ID, 0, 8, mode1Supported0x40PID); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)mode1Supported0x40PID)); + Serial.println("Reply: " + reply); + reply = ""; } - // SEND SENSOR STATUSES - if (BuildMessage == "2,1,5,0,0,0,0,0,") + if (canMessageRead == "2,9,0,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dCoolantTemp); + CAN.sendMsgBuf(REPLY_ID, 0, 8, mode9Supported0x00PID); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)mode9Supported0x00PID)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,12,0,0,0,0,0,") + + //================================================================= + // Return CAN-BUS Messages - RETURN PID VALUES - SENSORS + //================================================================= + + // Engine Coolant + if (canMessageRead == "2,1,5,") { - Serial.println(rndRPM); - CAN.sendMsgBuf(0x7E8, 0, 7, drpm); + CAN.sendMsgBuf(REPLY_ID, 0, 8, engine_Coolant_Temperature_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)engine_Coolant_Temperature_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,13,0,0,0,0,0,") + + // Rpm + if (canMessageRead == "2,1,12,") { - Serial.println(rndSpeed); - CAN.sendMsgBuf(0x7E8, 0, 7, dvspeed); + CAN.sendMsgBuf(REPLY_ID, 0, 8, engine_Rpm_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)engine_Rpm_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,15,0,0,0,0,0,") + + // Speed + if (canMessageRead == "2,1,13,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dIATSensor); + CAN.sendMsgBuf(REPLY_ID, 0, 8, vehicle_Speed_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)vehicle_Speed_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,16,0,0,0,0,0,") + + // Timing Adv + if (canMessageRead == "2,1,14,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dMAFSensor); + CAN.sendMsgBuf(REPLY_ID, 0, 8, timing_Advance_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)timing_Advance_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,70,0,0,0,0,0,") + + // Intake Tempture + if (canMessageRead == "2,1,15,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dBoardAirTemp); - Serial.println(t); + CAN.sendMsgBuf(REPLY_ID, 0, 8, intake_Temp_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)intake_Temp_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,71,0,0,0,0,0,") + + // MAF + if (canMessageRead == "2,1,16,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dControlHum); + CAN.sendMsgBuf(REPLY_ID, 0, 8, maf_Air_Flow_Rate_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)maf_Air_Flow_Rate_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,77,0,0,0,0,0,") + + // OBD standard + if (canMessageRead == "2,1,28,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dAcelxdir); + CAN.sendMsgBuf(REPLY_ID, 0, 8, obd_Std_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)obd_Std_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,78,0,0,0,0,0,") + + // Fuel Type Coding + if (canMessageRead == "2,1,58,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dAcelydir); + CAN.sendMsgBuf(REPLY_ID, 0, 8, fuel_Type_Msg); + reply = String(String(REPLY_ID, HEX) + ",0,8," + String((char *)fuel_Type_Msg)); + Serial.println("Reply: " + reply); + reply = ""; } - if (BuildMessage == "2,1,79,0,0,0,0,0,") + // VIN + if (canMessageRead == "2,9,2,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dAcelzdir); + + unsigned char frame1[8] = {16, 20, 73, 2, 1, vehicle_Vin[0], vehicle_Vin[1], vehicle_Vin[2]}; + unsigned char frame2[8] = {33, vehicle_Vin[3], vehicle_Vin[4], vehicle_Vin[5], vehicle_Vin[6], vehicle_Vin[7], vehicle_Vin[8], vehicle_Vin[9]}; + unsigned char frame3[8] = {34, vehicle_Vin[10], vehicle_Vin[11], vehicle_Vin[12], vehicle_Vin[13], vehicle_Vin[14], vehicle_Vin[15], vehicle_Vin[16]}; + + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame1); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame2); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame3); } - if (BuildMessage == "2,1,80,0,0,0,0,0,") + + // CAL ID + if (canMessageRead == "2,9,4,") { - CAN.sendMsgBuf(0x7E8, 0, 7, dAcelzdir); + unsigned char frame1[8] = {16, 20, 73, 4, 1, calibration_ID[0], calibration_ID[1], calibration_ID[2]}; + unsigned char frame2[8] = {33, calibration_ID[3], calibration_ID[4], calibration_ID[5], calibration_ID[6], calibration_ID[7], calibration_ID[8], calibration_ID[9]}; + unsigned char frame3[8] = {34, calibration_ID[10], calibration_ID[11], calibration_ID[12], calibration_ID[13], calibration_ID[14], calibration_ID[15], calibration_ID[16]}; + + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame1); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame2); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame3); } - BuildMessage = ""; + + // ECU NAME + if (canMessageRead == "2,9,10,") + { + + unsigned char frame1[8] = {10, 14, 49, 10, 01, ecu_Name[0], ecu_Name[1], ecu_Name[2]}; + unsigned char frame2[8] = {21, ecu_Name[3], ecu_Name[4], ecu_Name[5], ecu_Name[6], ecu_Name[7], ecu_Name[8], ecu_Name[9]}; + unsigned char frame3[8] = {22, ecu_Name[10], ecu_Name[11], ecu_Name[12], ecu_Name[13], ecu_Name[14], ecu_Name[15], ecu_Name[16]}; + unsigned char frame4[8] = {23, ecu_Name[17], ecu_Name[18]}; + + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame1); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame2); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame3); + CAN.sendMsgBuf(REPLY_ID, 0, 8, frame4); + } + // DTC + if (canMessageRead == "1,3,0,") + { + if (MIL) + { + unsigned char DTC[] = {6, 67, 1, 2, 23, 0, 0, 0}; // P0217 + CAN.sendMsgBuf(REPLY_ID, 0, 8, DTC); + reply = String(String(REPLY_ID, HEX) + ",0,8, " + String((char *)DTC)); + Serial.println("Reply: " + reply); + reply = ""; + } + else + { + unsigned char DTC[] = {6, 67, 0, 0, 0, 0, 0, 0}; // No Stored DTC + CAN.sendMsgBuf(REPLY_ID, 0, 8, DTC); + reply = String(String(REPLY_ID, HEX) + ",0,8, " + String((char *)DTC)); + Serial.println("Reply: " + reply); + reply = ""; + } + } + + // DTC Clear + if (canMessageRead == "1,4,0,") + { + MIL = false; + } + + canMessageRead = ""; } delay(100); } - DIAGENB = 0; - delay(100); } // ——————————————————————————————————————————————————————————————————————————————