Add initial project structure for CAN Bus Reader
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"platformio.platformio-ide"
|
||||||
|
],
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"ms-vscode.cpptools-extension-pack"
|
||||||
|
]
|
||||||
|
}
|
||||||
104
README.md
Normal file
104
README.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# CAN Bus Reader for Renault Clio 3
|
||||||
|
|
||||||
|
ESP32-based CAN bus sniffer that reads all packets from a Renault Clio 3 2012 via OBD2, with decoded output for wheel speed, RPM, and other vehicle data.
|
||||||
|
|
||||||
|
**Target vehicle**: Renault Clio 3 2012 1.2 16V
|
||||||
|
**Purpose**: Read odometer and RPM (not available via standard OBD2 PIDs) by sniffing the CAN bus.
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
| Component | Model |
|
||||||
|
|-----------|-------|
|
||||||
|
| MCU | ESP32 DOIT DevKit V1 |
|
||||||
|
| CAN Transceiver | SN65HVD230 VP230 (3.3V) |
|
||||||
|
| Connection | OBD2 connector pins 6, 14, GND |
|
||||||
|
|
||||||
|
## Wiring
|
||||||
|
|
||||||
|
### OBD2 to VP230
|
||||||
|
|
||||||
|
| OBD2 Pin | Signal | Connect To |
|
||||||
|
|----------|--------|------------|
|
||||||
|
| 6 | CAN High | VP230 CAN_H |
|
||||||
|
| 14 | CAN Low | VP230 CAN_L |
|
||||||
|
| 4 or 5 | GND | VP230 GND |
|
||||||
|
|
||||||
|
### VP230 to ESP32
|
||||||
|
|
||||||
|
| VP230 Pin | ESP32 Pin |
|
||||||
|
|-----------|-----------|
|
||||||
|
| TX (or D) | D33 (GPIO 33) |
|
||||||
|
| RX (or R) | D32 (GPIO 32) |
|
||||||
|
| VCC | 3.3V |
|
||||||
|
| GND | GND |
|
||||||
|
|
||||||
|
### Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
OBD2 Port VP230 Module ESP32
|
||||||
|
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||||
|
│ Pin 6 │──────────────────│ CAN_H │ │ │
|
||||||
|
│ Pin 14 │──────────────────│ CAN_L │ │ │
|
||||||
|
│ Pin 4/5 │──────┬───────────│ GND │──────────────────│ GND │
|
||||||
|
└─────────┘ │ │ TX │──────────────────│ D33 │
|
||||||
|
│ │ RX │──────────────────│ D32 │
|
||||||
|
│ │ VCC │──────────────────│ 3.3V │
|
||||||
|
└───────────│ GND │ └─────────┘
|
||||||
|
└─────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: Power the ESP32 via USB. Do not connect OBD2 pin 16 (+12V) to the ESP32.
|
||||||
|
|
||||||
|
## Build & Upload
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pio run -t upload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Connect hardware as above
|
||||||
|
2. Plug into vehicle OBD2 port (under dashboard, driver side)
|
||||||
|
3. Turn ignition ON (engine running for full data)
|
||||||
|
4. Open serial monitor at **115200 baud**
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
**Raw frames** (all received):
|
||||||
|
```
|
||||||
|
ID:0x29A LEN:7 DATA:00 00 1A 00 00 00 00
|
||||||
|
```
|
||||||
|
|
||||||
|
**Decoded values** (when ID is known):
|
||||||
|
```
|
||||||
|
ID:0x29A [WheelSpeed] FL:12.5 km/h FR:12.3 km/h
|
||||||
|
ID:0x29C [WheelSpeed] RL:12.4 km/h RR:12.6 km/h
|
||||||
|
ID:0x??? [Engine] RPM: 1850
|
||||||
|
```
|
||||||
|
|
||||||
|
## Decoded CAN IDs (Renault Clio 3 / Megane 3)
|
||||||
|
|
||||||
|
| ID | Signal | Bytes | Formula |
|
||||||
|
|----|--------|-------|---------|
|
||||||
|
| 0x29A (666) | Wheel speed front | 0-1: FR, 2-3: FL | (byte[1]<<8\|byte[0]) * 0.005 km/h |
|
||||||
|
| 0x29C (668) | Wheel speed rear | 0-1: RR, 2-3: RL | (byte[1]<<8\|byte[0]) * 0.005 km/h |
|
||||||
|
| 0x230 | Engine RPM (tentative) | 2-3 | raw/4 |
|
||||||
|
| 0x2D4 | Vehicle speed (tentative) | 0-1 | raw * 0.01 km/h |
|
||||||
|
|
||||||
|
To add odometer or fix RPM/speed: edit the `#define` IDs and `decode_renault()` switch cases in `main.cpp`.
|
||||||
|
|
||||||
|
RPM and odometer IDs may need tuning. If decoded values look wrong:
|
||||||
|
- **RPM**: Rev the engine and watch which IDs change; adjust `ID_ENGINE_RPM` and byte/factor in `decode_renault()`
|
||||||
|
- **Odometer**: Drive a known distance; find IDs that increment slowly; add a new case in `decode_renault()`
|
||||||
|
|
||||||
|
## CAN Bus Speed
|
||||||
|
|
||||||
|
- **500 kbps** – Clio 3 main CAN (pins 6/14)
|
||||||
|
- **250 kbps** – Try if no traffic at 500 kbps (motor diagnostic CAN)
|
||||||
|
|
||||||
|
Change `CAN_SPEED_KBPS` in `main.cpp` if needed.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Renault OBD2 Pinout](https://pinoutguide.com/CarElectronics/renault_obd2_diag_pinout.shtml)
|
||||||
|
- [Renault Megane 3 RS DBC](https://github.com/krsche/renault-megane-3-rs-can-dbc)
|
||||||
37
include/README
Normal file
37
include/README
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the convention is to give header files names that end with `.h'.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||||
46
lib/README
Normal file
46
lib/README
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into the executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a separate directory
|
||||||
|
("lib/your_library_name/[Code]").
|
||||||
|
|
||||||
|
For example, see the structure of the following example libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
Example contents of `src/main.c` using Foo and Bar:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries by scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
16
platformio.ini
Normal file
16
platformio.ini
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:esp32doit-devkit-v1]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32doit-devkit-v1
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
lib_deps = https://github.com/handmade0octopus/ESP32-TWAI-CAN.git
|
||||||
105
src/main.cpp
Normal file
105
src/main.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ESP32-TWAI-CAN.hpp>
|
||||||
|
|
||||||
|
// SN65HVD230 VP230: TX=D33, RX=D32 (per hardware)
|
||||||
|
#define CAN_TX_GPIO 33
|
||||||
|
#define CAN_RX_GPIO 32
|
||||||
|
#define CAN_SPEED_KBPS 500
|
||||||
|
|
||||||
|
void decode_renault(const CanFrame& frame);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(1000);
|
||||||
|
Serial.println("CAN Bus Sniffer - Renault Clio 3");
|
||||||
|
Serial.println("-------------------------------");
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
Serial.println("CAN bus started at 500 kbps");
|
||||||
|
} else {
|
||||||
|
Serial.println("CAN bus init FAILED - check wiring");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
CanFrame rxFrame;
|
||||||
|
|
||||||
|
// 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:");
|
||||||
|
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.println();
|
||||||
|
|
||||||
|
// Optional: decode known Renault IDs (add as reverse-engineered)
|
||||||
|
decode_renault(rxFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
switch (frame.identifier) {
|
||||||
|
case ID_WHEEL_SPEED_FRONT:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
if (len >= 2) {
|
||||||
|
uint16_t raw = (uint16_t)(d[1] << 8) | d[0];
|
||||||
|
float kmh = raw * 0.01f;
|
||||||
|
if (kmh < 300) Serial.printf(" -> [Speed] %.1f km/h\n", kmh);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
test/README
Normal file
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PlatformIO Test Runner and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||||
Reference in New Issue
Block a user