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:
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 <mcp_can.h>
#include <SPI.h>
// 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);
}
}
}