CAN-BUS with Arduino

i made some kind of a sketch and i struggle with few things.
I managed to get RPM and coolant temperature to RealDash.
With this sketch these works sometimes and sometimes not, usually coolant temperature is missing.
Anyway, i had connector for ABS unit disconnected and RPM seemed to work fine, no lag.
When i connect it RPM needle or bar indicator has a lag. Maybe that error is in the code, or can Arduino with CAN-shield be too slow?
Smoothing fucntion does not help in RealDash
With CAN-receiving code RPM CAN-messages come very rarely in serialmonitor when ABS unit is connected.
Almost all messages come from ABS then randomly and rarely something else to serial monitor.
If ABS not connected then for example RPM messages come all the time and gauge works without lags.

#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];                        // Array to store serial string


#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(9);                               // Set CS to pin 9

int rpm;
int coolant;
bool glow;
bool engineMIL;


void setup() 
{
   Serial.begin(115200);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.

  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input

}

void loop() 
{
 
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)

   sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);


   for (byte i = 0; i < len; i++) {
      sprintf(msgString, " 0x%.2X", rxBuf[i]);
//      Serial.print(msgString);
    }
    
    if (rxId == 0x280) {
      uint16_t rawRPM = (uint16_t)rxBuf[2] << 8;
      rawRPM |= rxBuf[3];
      rpm = rawRPM/4;
      
   }

    else if (rxId == 0x288) {
      uint8_t rawCOOLANT = (uint8_t)rxBuf[1];
      coolant = rawCOOLANT * 0,75-48;

    }


     else if (rxId == 0x488) {
      glow = bitRead(rxBuf[1],7);
      engineMIL = bitRead(rxBuf[1],4);

    }

  }

  SendCANFramesToSerial(); 
  
}


void SendCANFramesToSerial()
{
  byte buf[8];

  // build & send CAN frames to RealDash.
  // a CAN frame payload is always 8 bytes containing data in a manner
  // described by the RealDash custom channel description XML file

  // build 1st CAN frame, RPM, MAP, CLT, TPS
  buf[0] = (0x49);
  buf[1] = (0xff);
  buf[2] = ((rpm >> 8) & 0xff);
  buf[3] = (rpm & 0xff);
  buf[4] = (0xff);
  buf[5] = (0xff);  
  buf[6] = (0xff);
  buf[7] = (0xff);

  // write first CAN frame to serial
  SendCANFrameToSerial(3200, buf);


  // build 2nd CAN frame, coolant
  buf[0] = (0xff);
  buf[1] = (coolant & 0xff);
  buf[2] = (0xff);
  buf[3] = (0xff);
  buf[4] = (0xff);
  buf[5] = (0xff);
  buf[6] = (0xff);
  buf[7] = (0xff);

  // write 2nd CAN frame to serial
  SendCANFrameToSerial(3201, buf);


  // build 3rd CAN frame, glow and engineMIL
  buf[0] = (0xff);
  buf[1] = glow;
  buf[2] = engineMIL;
  buf[3] = (0xff);
  buf[4] = (0xff);
  buf[5] = (0xff);
  buf[6] = (0xff);
  buf[7] = (0xff);

  // write 2nd CAN frame to serial
  SendCANFrameToSerial(3202, buf);
}


void SendCANFrameToSerial(unsigned long canFrameId, const byte* frameData)
{
  // the 4 byte identifier at the beginning of each CAN frame
  // this is required for RealDash to 'catch-up' on ongoing stream of CAN frames
  const unsigned long serialBlockTag = 0x11223344;
  Serial.write((const byte*)&serialBlockTag, 4);

  // the CAN frame id number
  Serial.write((const byte*)&canFrameId, 4);

  // CAN frame payload
  Serial.write(frameData, 8);
}

what Arduino and CANshield are you using?
is the Canbus correctly terminated?
I find a USB-CAN dongle for a PC to monitor data flows useful

1 Like

Arduino Mega with Seeed CAN-BUS Shield V2.0.
I took CAN-wires from original instrument cluster and connected to shield.
I think this end does need resistors.

Changing baud-rate does not help, with 9600 it does not give much messages and if over 115200, can get messages to serialmonitor but in RealDash, gauges won't work.

You need to enable filters on the MCP 2515 to ignore the ABS messages unless you want them.... Your just getting swamped by the high priority ABS messages

Checkout This

I need that ABS data in future to get speed to gauge, so i cannot filter that out.
I tried to enable filter so that it get only 0x280 and 288, 5A0 should be for ABS. That does not show in serialmonitor now, ok.
RPM is still lagging and when i disconnect abs connector rpm has no lag.

There should not be any termination on the shield, the vehicle has supplied all the needed termination. They are at the two physical ends of the bus. Adding another can introduce weird problems.

Is that another end in instrument cluster?
If so, then shield should have termination, because Arduino will replace that?
I measured 35-44 ohms from wires, i think that should not be a big problem because relatively short distances.

I don't believe your issue is related to termination, CanBus is quite tolerant in short length systems, Especially in automotive.
You really should use the int pin on the MCP to trigger an interrupt routine on your Arduino. This way you can handle fresh can frames as soon as they arrive.

Another "simple" solution is to get your hands on a Samd21 based arduino (like Arduino Zero) You'll have access to DMA and FreeRTOS, which can make problems like this disappear like magic.

You should measure about 60 Ohms across a properly terminated bus. I would recommend not connecting the termination resistor on the shield. What is your resistance measurement without the shield resistor and it connected? It should ba about 60 OHMs.

1 Like

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