limiter121 / esp32-obd2-emulator

Open-source OBD-II emulator based on an ESP32 + CAN transceiver IC, controllable via WiFi through a simple web UI (or via API)
Mozilla Public License 2.0
404 stars 105 forks source link

Problem to read transmitted data #6

Closed clfregis closed 5 years ago

clfregis commented 5 years ago

Hi guys!! I've followed your instructions to deploy the program at ESP32 microcontroller. Everything worked fine, I was able to connect to it using my phone and also was able to track the log of TX using terminal. However, I was not able to read the transmitted data using a CAN Module MCP2515 Module with arduino UNO. The receiver end is working fine as well, since I tested it in a car using the code at the end of this post (some comments are in portuguese, sorry for that) and was able to get RPM data. Thus, I think that maybe the problem is in the connection that I did, which is the following: Instead of using the WROOM32 alone I used the ESP32 DEVKIT V1. Also, I was not able to find SN65HVD230, so I used MCP2551 Module. The voltage supply of this module is 5V, so it was necessary to interface the communication using this logic level converter. So, the connections are as follows:

D4 (GPIO4 from ESP32 module) -> LV4 (logic level converter) D5 (GPIO5 from ESP32 module) -> LV3 (logic level converter)

HV4 (logic level converter) -> CRX (MCP2551 Module) HV3 (logic level converter) -> CTX (MCP2551 Module)

CANH (MCP2551 Module) -> CANH (MCP2515 Module) CANL (MCP2551 Module) -> CANL (MCP2515 Module)

POWER SUPPLY: -Logic Level Converter

VIN (ESP32 Module) -> HV (Logic Level Converter) GND (ESP32 Module) -> Both GND (Logic Level Converter) 3V3 (ESP32 Module) -> LV (Logic Level Converter)

-MCP2551 Module

VIN (ESP32 Module) -> VCC (MCP2551 Module) GND (ESP32 Module) -> GND (MCP2551 Module)

Am I missing something? I do not have oscilloscope here to see if the data is arriving at the logic converter or at the MCP2551 module. Do you have any suggestion? I thing that maybe the VIN voltage (which comes directly from USB VDD) is not sufficient to run the MCP2551.

P.S.: I've checked dozen times the above connections using a multimeter (continuity test) to avoid any faulty wiring.

P.P.S.: I've maintained the default values in menuconfig (pins, etc). I only needed to change the flash memory to a higher value.

/ CAN OBD & UDS Simple PID Request

  • Currently requests PID 0x00 at a 1 second interval and
  • displays all received CAN traffic to the terminal at 115200.
  • Written By: Cory J. Fowler April 5th, 2017
  • (Disclaimer: Standard IDs are currently UNTESTED against a vehicle)
  • Hiya, Claudio here. I made some modifications in this code to make
  • it work on a Renault Sandero in Brazil. So, I tested the Standard IDs
  • and they are working pretty fine. I also changed the txData in order
  • to request the RPM of the vechicle. Changed the frequency of the
  • oscillator as well, since the MCP2515 module that I'm using is a chinese
  • version with 8MHz crystal. And finally, I've added a function to convert
  • the data received from the car to a readable RPM value on serial screen.
  • */

// Codigos retirados de: //http://forum.arduino.cc/index.php?topic=402018.0 //https://forum.arduino.cc/index.php?topic=476862.0

include

include

// Standard igual a 1 pois trabalhando com 11 bits, n eh extended (29 bits)

define standard 1

// 7E0/8 = Engine ECM // 7E1/9 = Transmission ECM

if standard == 1

define LISTEN_ID 0x7EA

define REPLY_ID 0x7E0

define FUNCTIONAL_ID 0x7DF

else

define LISTEN_ID 0x98DAF101

define REPLY_ID 0x98DA01F1

define FUNCTIONAL_ID 0x98DB33F1

endif

// Variaveis TX do CAN unsigned long prevTx = 0; unsigned int invlTx = 1000; //byte txData[] = {0x02,0x01,0x00,0x55,0x55,0x55,0x55,0x55}; // Requisita quais os PIDs suportados byte txData[] = {0x02,0x01,0x0C,0x55,0x55,0x55,0x55,0x55}; // Requisita o RPM do veiculo //byte txData[] = {0x02,0x01,0x0C}; // Requisita o RPM do veiculo //byte txData[] = {0x02,0x01,0x0D,0x55,0x55,0x55,0x55,0x55}; // Requisita a velocidade do veiculo //byte txData[] = {0x02,0x01,0x11,0x55,0x55,0x55,0x55,0x55}; // Requisita o Throttle do veiculo

// Variaveis RX do CAN unsigned long rxID; byte dlc; byte rxBuf[8]; char msgString[128]; // Vetor para armazenar a string serial float DisplayValue = 0.0;

// Pinos Interrupt e Chip Select

define CAN0_INT 2 / INT no Pino 2 /

MCP_CAN CAN0(10); / CS no Pino 10 /

void setup(){

Serial.begin(115200); while(!Serial);

// Inicializa o MCP2515 rodando a 8MHz com baudrate de 500kb/s e com as mascaras e filtros desativados. if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Iniciado com Sucesso!"); else{ Serial.println("Erro ao inicializar o MCP2515... Falha permanente! Por favor checar o código e conexoes"); while(1); }

// // // Allow all Standard IDs // CAN0.init_Mask(0,0x00000000); // Init first mask... // CAN0.init_Filt(0,0x00000000); // Init first filter... // CAN0.init_Filt(1,0x00000000); // Init second filter... // // Allow all Extended IDs // CAN0.init_Mask(1,0x80000000); // Init second mask... // CAN0.init_Filt(2,0x80000000); // Init third filter... // CAN0.init_Filt(3,0x80000000); // Init fouth filter... // CAN0.init_Filt(4,0x80000000); // Init fifth filter... // CAN0.init_Filt(5,0x80000000); // Init sixth filter...

if standard == 1

// Filtros de ID standard CAN0.init_Mask(0,0x7F00000); // Init first mask... CAN0.init_Filt(0,0x7DF0000); // Init first filter... CAN0.init_Filt(1,0x7E10000); // Init second filter...

CAN0.init_Mask(1,0x7F00000); // Init second mask... CAN0.init_Filt(2,0x7DF0000); // Init third filter... CAN0.init_Filt(3,0x7E10000); // Init fouth filter... CAN0.init_Filt(4,0x7DF0000); // Init fifth filter... CAN0.init_Filt(5,0x7E10000); // Init sixth filter...

else

// Filtros de ID extended CAN0.init_Mask(0,0x90FF0000); // Init first mask... CAN0.init_Filt(0,0x90DA0000); // Init first filter... CAN0.init_Filt(1,0x90DB0000); // Init second filter...

CAN0.init_Mask(1,0x90FF0000); // Init second mask... CAN0.init_Filt(2,0x90DA0000); // Init third filter... CAN0.init_Filt(3,0x90DB0000); // Init fouth filter... CAN0.init_Filt(4,0x90DA0000); // Init fifth filter... CAN0.init_Filt(5,0x90DB0000); // Init sixth filter...

endif

CAN0.setMode(MCP_NORMAL); // Configurando o modo de operacao normal, >logo o MCP2515 envia confirmacao para os dados recebidos.

// Enfrentando problemas? =================================== // Se voce nao esta recebendo nenhuma mensagem, descomente a linha setMode // abaixo para testar a conexao entre o Arduino e MCP2515. // Sendo assim, a mensagem enviada nesse programa será instantaneamente // recebida. // ======================================================= //CAN0.setMode(MCP_LOOPBACK);

pinMode(CAN0_INT, INPUT); // Configurando o pino Interrupt como entrada

Serial.println("Programa de Request de PID simples usando CAN pela OBD-II"); }

void loop(){

if(!digitalRead(CAN0_INT)){ // Se o pino CAN0_INT esta em nivel baixo, fazer leitura do buffer recebido

CAN0.readMsgBuf(&rxID, &dlc, rxBuf); // Receber dados CAN

// Mostrar os dados CAN na medida em que recebemos eles if((rxID & 0x80000000) == 0x80000000) // Determinar se o ID eh standard (11 bits) ou extended (29 bits) sprintf(msgString, "ID Extended: 0x%.8lX DLC: %1d Dados:", (rxID & 0x1FFFFFFF), dlc); else sprintf(msgString, "ID Standard: 0x%.3lX DLC: %1d Dados:", rxID, dlc);

Serial.print(msgString);

if((rxID & 0x40000000) == 0x40000000){ // Determine se a mensagem eh uma request remota. sprintf(msgString, "REQUEST REMOTA"); Serial.print(msgString); } else { for(byte i = 0; i<dlc; i++){ sprintf(msgString, " 0x%.2X", rxBuf[i]); Serial.print(msgString); } } Serial.println();

//Calculando RPM / Posteriomente eu pretendo criar funções / if (rxBuf[1]==0x41 && rxBuf[2]==0x0C) { int A = rxBuf[3]; int B = rxBuf[4];

 DisplayValue = ((A * 256)+B)/4;
 int tmpInt1 = DisplayValue;                    // Armazena o inteiro
 float tmpFrac = DisplayValue - tmpInt1;        // Armazena a fracao
 int tmpInt2 = trunc(tmpFrac * 1000);           // Transforma a fracao em inteiro
 sprintf(msgString, "RPM: %d.04%d", tmpInt1, tmpInt2);
 Serial.println(msgString);

}

Serial.println(); }

/ A cada 1000ms (Um Segundo) envia uma request para o PID 0C

  • Esse PID responde de volta com 2 bytes de dados indicando os *
  • o RPM do veiculo. */ if((millis() - prevTx) >= invlTx){ prevTx = millis(); int resposta = CAN0.sendMsgBuf(FUNCTIONAL_ID, 8, txData);

    if(CAN0.sendMsgBuf(FUNCTIONAL_ID, 8, txData) == CAN_OK){ Serial.println("Mensagem enviada com sucesso!"); } else { Serial.print("Erro ao enviar mensagem. Erro numero: "); Serial.println(resposta); } } }

clfregis commented 5 years ago

Hello guys, again another amateur mistake. All connections described above are correct. However, the Vin pin of ESP32 does not provide 5V. It is slightly less than that (4.75V, even less when loaded). I thought it was ok, because we always have a margin of operation on those chips and dismissed the possibility of an error due to the value of this voltage. Then, after trying hundreds of different approaches to solve the problem, I decided to take a look on MCP2551 datasheet, then I found that the minimum value of the VDD for this particular chip is 4.5V (so we do not have a good margin of operation here). Thus I decided to use an external 5V power supply. On top of that, since the emulator is near the receptor (aka short line) I plugged a ballast resistor of 120 Ohms between CANH and CANL (on some modules there is a jumper to this). Now is working like a charm.