Add compile_commands.json for build configuration and update .gitignore to exclude .cache. Modify main.cpp to enhance CAN Bus Sniffer functionality with new ID definitions and optional scanning mode for improved data output.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.cache
|
||||
290
compile_commands.json
Normal file
290
compile_commands.json
Normal file
File diff suppressed because one or more lines are too long
112
src/main.cpp
112
src/main.cpp
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* CAN Bus Sniffer for Renault Clio 3 2012
|
||||
* Reads all CAN packets via OBD2 pins 6 (CAN_H) and 14 (CAN_L)
|
||||
* Target: odometer and RPM (not available via OBD2 PIDs)
|
||||
* IDs/formulas from x0r.fr reverse-engineering: https://x0r.fr/blog/39
|
||||
*/
|
||||
#define SCAN 0
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ESP32-TWAI-CAN.hpp>
|
||||
@@ -19,6 +19,10 @@ void setup() {
|
||||
delay(1000);
|
||||
Serial.println("CAN Bus Sniffer - Renault Clio 3");
|
||||
Serial.println("-------------------------------");
|
||||
#if SCAN
|
||||
Serial.println("SCAN: printing ALL frames. Run while idling, then at steady 50km/h.");
|
||||
Serial.println("Share output to find correct RPM/speed IDs and byte positions.");
|
||||
#endif
|
||||
|
||||
// Initialize TWAI with 500 kbps, RX=GPIO32, TX=GPIO33
|
||||
if (ESP32Can.begin(ESP32Can.convertSpeed(CAN_SPEED_KBPS), CAN_TX_GPIO, CAN_RX_GPIO, 10, 20)) {
|
||||
@@ -33,84 +37,84 @@ void loop() {
|
||||
|
||||
// Non-blocking read (timeout 0)
|
||||
if (ESP32Can.readFrame(rxFrame, 0)) {
|
||||
// candump-style output: ID:0xXXX LEN:X DATA:XX XX XX XX XX XX XX XX
|
||||
Serial.print("ID:0x");
|
||||
Serial.print(rxFrame.identifier, HEX);
|
||||
Serial.print(" LEN:");
|
||||
Serial.print(rxFrame.data_length_code);
|
||||
Serial.print(" DATA:");
|
||||
#if SCAN
|
||||
Serial.printf("ID:0x%03X LEN:%d ", rxFrame.identifier, rxFrame.data_length_code);
|
||||
for (int i = 0; i < rxFrame.data_length_code && i < 8; i++) {
|
||||
if (rxFrame.data[i] < 0x10) Serial.print("0");
|
||||
Serial.print(rxFrame.data[i], HEX);
|
||||
if (i < rxFrame.data_length_code - 1) Serial.print(" ");
|
||||
Serial.printf("%02X ", rxFrame.data[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Optional: decode known Renault IDs (add as reverse-engineered)
|
||||
#else
|
||||
decode_renault(rxFrame);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Known Renault CAN IDs (Megane 3 RS / Clio 3 platform)
|
||||
#define ID_WHEEL_SPEED_FRONT 0x29A // 666 - FL, FR
|
||||
#define ID_WHEEL_SPEED_REAR 0x29C // 668 - RL, RR
|
||||
#define ID_ENGINE_RPM 0x230 // Common Renault/PSA engine broadcast (verify on your car)
|
||||
#define ID_VEHICLE_SPEED 0x2D4 // Possible speed/odometer (verify on your car)
|
||||
#define ID_ODOMETER 0x5D7 // Renault Megane 3 / Clio 3 - bytes 2-5, (raw>>4)/100 = km
|
||||
// Renault Clio 3 - from x0r.fr/blog/39
|
||||
#define ID_ENGINE_RPM 0x1F9 // bytes 2-3 BE, raw/8 = RPM
|
||||
#define ID_VEHICLE_SPEED 0x354 // bytes 0-1 BE, raw*0.01 = km/h
|
||||
#define ID_SPEED_2 0x645 // bytes 3-4 BE, raw*0.01 = km/h (dashboard backlight msg)
|
||||
#define ID_ODOMETER 0x5FD // bytes 2-4 BE, raw/13.0856 = km (cal: 114513)
|
||||
|
||||
static uint16_t lastRpm = 0xFFFF;
|
||||
static uint16_t lastSpeed = 0xFFFF;
|
||||
static uint32_t lastOdo = 0xFFFFFFFF;
|
||||
static uint32_t lastPrintMs = 0;
|
||||
#define DEBOUNCE_MS 300
|
||||
|
||||
// Decoder for Renault Clio 3 - outputs human-readable values
|
||||
void decode_renault(const CanFrame& frame) {
|
||||
const uint8_t* d = frame.data;
|
||||
uint8_t len = frame.data_length_code;
|
||||
uint32_t now = millis();
|
||||
|
||||
switch (frame.identifier) {
|
||||
case ID_WHEEL_SPEED_FRONT:
|
||||
case ID_ENGINE_RPM: // 0x1F9 bytes 2-3 BE, raw/8 (x0r: "Régime moteur")
|
||||
if (len >= 4) {
|
||||
uint16_t fr = (uint16_t)(d[1] << 8) | d[0];
|
||||
uint16_t fl = (uint16_t)(d[3] << 8) | d[2];
|
||||
float fr_kmh = fr * 0.005f;
|
||||
float fl_kmh = fl * 0.005f;
|
||||
Serial.printf(" -> [WheelSpeed Front] FL:%.1f km/h FR:%.1f km/h\n", fl_kmh, fr_kmh);
|
||||
uint16_t raw = (uint16_t)(d[2] << 8) | d[3];
|
||||
uint16_t rpm = raw / 8;
|
||||
if (rpm >= 100 && rpm <= 7000 && (rpm != lastRpm || now - lastPrintMs > DEBOUNCE_MS)) {
|
||||
lastRpm = rpm;
|
||||
lastPrintMs = now;
|
||||
Serial.printf("RPM: %u\n", rpm);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_WHEEL_SPEED_REAR:
|
||||
if (len >= 4) {
|
||||
uint16_t rr = (uint16_t)(d[1] << 8) | d[0];
|
||||
uint16_t rl = (uint16_t)(d[3] << 8) | d[2];
|
||||
float rr_kmh = rr * 0.005f;
|
||||
float rl_kmh = rl * 0.005f;
|
||||
Serial.printf(" -> [WheelSpeed Rear] RL:%.1f km/h RR:%.1f km/h\n", rl_kmh, rr_kmh);
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_ENGINE_RPM:
|
||||
if (len >= 4) {
|
||||
uint16_t raw = (uint16_t)(d[3] << 8) | d[2];
|
||||
uint16_t rpm = raw / 4;
|
||||
if (rpm < 10000) Serial.printf(" -> [Engine] RPM: %u\n", rpm);
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_VEHICLE_SPEED:
|
||||
case ID_VEHICLE_SPEED: // 0x354 bytes 0-1 BE, raw*0.01 = km/h
|
||||
if (len >= 2) {
|
||||
uint16_t raw = (uint16_t)(d[1] << 8) | d[0];
|
||||
uint16_t raw = (uint16_t)(d[0] << 8) | d[1];
|
||||
float kmh = raw * 0.01f;
|
||||
if (kmh < 300) Serial.printf(" -> [Speed] %.1f km/h\n", kmh);
|
||||
if (kmh < 250 && (raw != lastSpeed || now - lastPrintMs > DEBOUNCE_MS)) {
|
||||
lastSpeed = raw;
|
||||
lastPrintMs = now;
|
||||
Serial.printf("Speed: %.1f km/h\n", kmh);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_ODOMETER:
|
||||
if (len >= 6) {
|
||||
// Renault Megane 3 / Clio 3: bytes 2-5, (raw>>4)/100 = km (from car-reminder project)
|
||||
uint32_t raw = (uint32_t)d[2] << 24 | (uint32_t)d[3] << 16 |
|
||||
(uint32_t)d[4] << 8 | d[5];
|
||||
uint32_t km = (raw >> 4) / 100;
|
||||
if (km < 999999) Serial.printf(" -> [Odometer] %lu km\n", (unsigned long)km);
|
||||
case ID_SPEED_2: // 0x645 bytes 3-4 BE, raw*0.01 = km/h (x0r)
|
||||
if (len >= 5) {
|
||||
uint16_t raw = (uint16_t)(d[3] << 8) | d[4];
|
||||
float kmh = raw * 0.01f;
|
||||
if (kmh < 250 && (raw != lastSpeed || now - lastPrintMs > DEBOUNCE_MS)) {
|
||||
lastSpeed = raw;
|
||||
lastPrintMs = now;
|
||||
Serial.printf("Speed: %.1f km/h\n", kmh);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case ID_ODOMETER: // 0x5FD x0r: bytes 0-2 = km. This car uses bytes 2-4.
|
||||
if (len >= 5) {
|
||||
uint32_t raw = (uint32_t)d[2] << 16 | (uint32_t)d[3] << 8 | d[4];
|
||||
uint32_t km = (uint32_t)(raw / 13.0834f); // cal: 114513
|
||||
if (km < 999999 && (km != lastOdo || now - lastPrintMs > DEBOUNCE_MS)) {
|
||||
lastOdo = km;
|
||||
lastPrintMs = now;
|
||||
Serial.printf("Odometer: %lu km\n", (unsigned long)km);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user