We have two sketches that use interrupts to read CAN messages. The first sends messages that don't request responses, but it does read the two unsolicited repetitive messages that come every 1/2 second. It runs for a minute then stops recognizing interrupts. The other sketch (attached) sends messages that request specific information from the CAN bus (e.g. RPM, temp, load). This sketch is a modified version of a sketch that looped looking for a message. It now uses interrupts to recognize a response has been sent. With the attached sketch that uses the attachInterrupt command, the first request receives 2 replies, then there are no further interrupts detected. Is it possible there is something in the *.h, *.dfs or *.cpp files, or with the attachInterrupt function that fails when sending CAN messages as well as reading CAN messages? Or are we misusing the CAN or interrupt commands?
The attached sketch that now uses interrupts to detect incoming messages, is a modified version of the "looping" version found at: Seeed_Arduino_CAN/OBDII_PIDs.ino at master · Seeed-Studio/Seeed_Arduino_CAN · GitHub We have used the associated .h and .cpp and .dfs files.
We have specified the interrupt number 0 (Digital Pin 2 - INT4) in the attachInterrupt command because "digitalPinToInterrupt(x)" does not compile correctly in IDE 1.8.5.
The program output looks like this, indicating that the first sent message (PID 5) got a response, but not the following messages (C, D and 5):
</>
Enter setting mode success
set rate success!!
Enter Normal Mode Success!!
CAN BUS Shield init ok!
Begin to set Mask!!
set Mask success!!
....
Interrupt set MCP2515 Falling
SEND PID: 0x5
PID_INPUT=5
Interrupt Counter = 1
Get Data From id: 0x7E8
0x3 0x41 0x5 0x41 0x0 0x0 0x0 0x0
Interrupt Counter = 2
Get Data From id: 0x7EA
0x3 0x41 0x5 0x41 0x0 0x0 0x0 0x0
SEND PID: 0xC
PID_INPUT=C
SEND PID: 0xD
PID_INPUT=D
SEND PID: 0x5
PID_INPUT=5
/*************************************************************************************************
CAN-OBD-II_PIDs_TEST_CODE
LOOVEE @ JUN24, 2017
Query
send id: 0x7df
dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0
Response
From id: 0x7E9 or 0x7EA or 0x7EB
dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option)
https://en.wikipedia.org/wiki/OBD-II_PIDs
Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
***************************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"
unsigned char Flag_Recv = 0;
unsigned long Flag_Recv_Ctr = 0; // debugging only
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9; // Normally D9, but D11 for DFPCI
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
#define PID_ENGIN_PRM 0x0C
#define PID_VEHICLE_SPEED 0x0D
#define PID_COOLANT_TEMP 0x05
#define PID_ENGINE_LOAD 0x04
#define CAN_ID_PID 0x7DF
unsigned char PID_INPUT;
unsigned char getPid = 0;
void set_mask_filt()
{
/*
* set mask, set both the mask to 0x3ff
*/
CAN.init_Mask(0, 0, 0x7FC);
CAN.init_Mask(1, 0, 0x7FC);
/*
* set filter, we can receive id from 0x04 ~ 0x09
*/
CAN.init_Filt(0, 0, 0x7E8);
CAN.init_Filt(1, 0, 0x7E8);
CAN.init_Filt(2, 0, 0x7E8);
CAN.init_Filt(3, 0, 0x7E8);
CAN.init_Filt(4, 0, 0x7E8);
CAN.init_Filt(5, 0, 0x7E8);
}
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
set_mask_filt();
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt on digital pin 2 (INT4)
Serial.println("Interrupt set MCP2515 Falling");
}
void MCP2515_ISR()
{ Flag_Recv = 1;
Flag_Recv_Ctr = Flag_Recv_Ctr + 1; // debugging only
}
void loop()
{ if(Flag_Recv) // check if an interrupt was received if reading messages only after an interrupt
{
Flag_Recv = 0;
taskCanRecv(); // if msg available, get and print it
}
taskDbg(); // go see if any request entered on the keyboard
if(getPid == 1) // GET A PID and send a message to the CAN bus
{
Serial.print("getPid="); // debugging only
Serial.println(getPid, DEC); // debugging only
getPid = 0;
sendPid(PID_INPUT); // send a message because of request from keyboard
Serial.print("PID_INPUT="); // debugging only
Serial.println(PID_INPUT, HEX); // debugging only
PID_INPUT = 0;
}
}
void taskCanRecv()
{
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if get data
{
Serial.print("Interrupt Counter = "); // debugging only
Serial.println(Flag_Recv_Ctr, DEC); // debugging only
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
Serial.println("\r\n------------------------------------------------------------------");
Serial.print("Get Data From id: 0x");
Serial.println(CAN.getCanId(), HEX);
for(int i = 0; i<len; i++) // print the data
{
Serial.print("0x");
Serial.print(buf[i], HEX);
Serial.print("\t");
}
Serial.println();
}
else Serial.println("Interrupt received but no message"); // debugging only
}
void taskDbg() // Read PID from Serial Monitor
{
while(Serial.available())
{ // calculate the HEX code for the appropriate PID
char c = Serial.read();
if(c>='0' && c<='9') // examine entry from serial monitor
{
PID_INPUT *= 0x10;
PID_INPUT += c-'0'; // leave only the HEX value from 00 to 09
}
else if(c>='A' && c<='F')
{
PID_INPUT *= 0x10;
PID_INPUT += 10+c-'A'; // leave only the HEX value from 0A to 0F
}
else if(c>='a' && c<='f')
{
PID_INPUT *= 0x10;
PID_INPUT += 10+c-'a'; // leave only the HEX value from 0A to 0F
}
else if(c == '\n') // END
{
getPid = 1;
}
}
}
void sendPid(unsigned char __pid)
{
unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0};
Serial.print("SEND PID: 0x");
Serial.println(__pid, HEX);
CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);
}
</>
CAN-Final_Example_TEST.ino (4.75 KB)
keywords.txt (1.21 KB)
mcp_can.cpp (42.2 KB)
mcp_can.h (7.41 KB)
mcp_can_dfs.h (12.2 KB)