OBDII Reader and display for hibrid cars

In this project i want to have a display to show the information that the car doesnt show me HV battery charge in % and Cº water temp oil temp

Im open for any feedback

#include <mcp2515.h>
#include <SPI.h>
#include <Wire.h>

// Definição dos pinos para o MCP2515
#define CAN_CS_PIN  5    // Chip Select pin
#define CAN_INT_PIN 4    // Interrupt pin

// PIDs Standard OBD-II
#define PID_SPEED          0x0D
#define PID_RPM            0x0C
#define PID_COOLANT        0x05
#define PID_OIL_TEMP       0x5C
#define PID_VOLTAGE        0x42

// PIDs Toyota Hybrid
#define PID_HV_BAT_LEVEL   0x5B
#define PID_HV_BAT_TEMP    0x5C
#define PID_HV_BAT_CURRENT 0x5D

// Inicialização do objeto MCP2515
MCP2515 mcp2515(CAN_CS_PIN);
struct can_frame canMsg;

// Estrutura para armazenar dados do veículo
struct HybridCarData {
    int speed;              // km/h
    int rpm;               // RPM
    float coolantTemp;     // °C
    float oilTemp;         // °C
    float voltage12V;      // V
    float hvBatteryLevel;  // %
    float hvBatteryTemp;   // °C
    float hvBatteryCurrent;// A
} carData;

void setup() {
    Serial.begin(115200);
    while (!Serial) delay(100);
    
    SPI.begin();
    
    // Inicializa o MCP2515
    if (mcp2515.reset() != MCP2515::ERROR_OK) {
        Serial.println("Erro ao inicializar MCP2515!");
        while (1);
    }
    
    mcp2515.setBitrate(CAN_500KBPS);
    mcp2515.setNormalMode();
    
    Serial.println("Sistema iniciado com sucesso!");
    
    // Inicializa a estrutura de dados
    memset(&carData, 0, sizeof(carData));
}

void requestPID(uint8_t pid) {
    struct can_frame frame;
    frame.can_id = 0x7DF;
    frame.can_dlc = 8;
    frame.data[0] = 0x02;
    frame.data[1] = 0x01;  // Modo 01 standard OBD-II
    frame.data[2] = pid;
    frame.data[3] = 0x00;
    frame.data[4] = 0x00;
    frame.data[5] = 0x00;
    frame.data[6] = 0x00;
    frame.data[7] = 0x00;
    
    mcp2515.sendMessage(&frame);
    delay(50); // Pequeno delay para não sobrecarregar o barramento
}

void requestToyotaHybridData() {
    struct can_frame frame;
    frame.can_id = 0x7DF;
    frame.can_dlc = 8;
    frame.data[0] = 0x02;
    frame.data[1] = 0x21;  // Modo 21 Toyota
    frame.data[2] = 0x01;  // PID específico Toyota
    frame.data[3] = 0x00;
    frame.data[4] = 0x00;
    frame.data[5] = 0x00;
    frame.data[6] = 0x00;
    frame.data[7] = 0x00;
    
    mcp2515.sendMessage(&frame);
    delay(50);
}

void processCANMessage(struct can_frame *frame) {
    if(frame->can_id == 0x7E8) {  // ID típico de resposta OBD-II
        uint8_t pid = frame->data[2];
        
        switch(pid) {
            case PID_SPEED:
                carData.speed = frame->data[3];
                Serial.print("Velocidade: ");
                Serial.println(carData.speed);
                break;
                
            case PID_RPM:
                carData.rpm = ((frame->data[3] * 256) + frame->data[4]) / 4;
                Serial.print("RPM: ");
                Serial.println(carData.rpm);
                break;
                
            case PID_COOLANT:
                carData.coolantTemp = frame->data[3] - 40;
                Serial.print("Temp. Líquido: ");
                Serial.println(carData.coolantTemp);
                break;
                
            case PID_OIL_TEMP:
                carData.oilTemp = frame->data[3] - 40;
                Serial.print("Temp. Óleo: ");
                Serial.println(carData.oilTemp);
                break;
                
            case PID_VOLTAGE:
                carData.voltage12V = ((frame->data[3] * 256) + frame->data[4]) / 1000.0;
                Serial.print("Tensão 12V: ");
                Serial.println(carData.voltage12V);
                break;
        }
    }
}

void requestAllData() {
    requestPID(PID_SPEED);
    requestPID(PID_RPM);
    requestPID(PID_COOLANT);
    requestPID(PID_OIL_TEMP);
    requestPID(PID_VOLTAGE);
    requestToyotaHybridData();
}

void loop() {
    static unsigned long lastRequest = 0;
    const unsigned long REQUEST_INTERVAL = 1000; // 1 segundo entre requisições
    
    // Faz nova requisição a cada segundo
    if (millis() - lastRequest >= REQUEST_INTERVAL) {
        requestAllData();
        lastRequest = millis();
    }
    
    // Verifica se há mensagens disponíveis
    if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
        processCANMessage(&canMsg);
    }
}

What is your question?

There's no question, @m0rxira9 just wants feedback.

You're good to go @m0rxira9 :+1:

You might want to look at this How to get the best out of this forum before you proceed any further.
We only know what you tell us, and without knowing what you have, we don't stand a chance.

So what makes you think that this information is available through the CAN bus?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.