Site Information

 Loading... Please wait...

CAN Bus Prototyping With Arduino Uno - Extended CAN Bus Shield Test

Posted by Wilfried Voss on

This post is part of a series about Controller Area Network (CAN Bus) Prototyping With the Arduino Uno.

In this next, extended example, we use the same program as shown in the previous chapter but add a CAN receiving routine to it. The result, i.e. the received messages, will be displayed through the Arduino serial monitor.

// Simple CAN Shield Test
#include <stdlib.h>
#include "mcp_can.h"
#include <SPI.h>

MCP_CAN CAN0(10); // Set CS to pin 10

// Test message
unsigned char stmp[8] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};

// SYSTEM: Setup routine runs on power-up or reset
void setup() {

// Set the serial interface baud rate
Serial.begin(9600);

// Initialize the CAN controller
// Baud rates defined in mcp_can_dfs.h
if (CAN0.begin(CAN_250KBPS) == CAN_OK)
    
Serial.print("CAN Init OK.\n\r\n\r");
else
    Serial.print("CAN Init Failed.\n\r");

}// end setup

// Main Loop - Arduino Entry Point
void loop()
{

// Declarations
byte nMsgLen = 0;
byte nMsgBuffer[8];
char sString[4];

// Send out a test message
// Send data: id = 0x1FF, extended frame, data len = 8, stmp: data buf
// ID mode (11/29 bit) defined in mcp_can_dfs.h
CAN0.sendMsgBuf(0x1FF, CAN_EXTID, 8, stmp);

// Check for a message
if(CAN0.checkReceive() == CAN_MSGAVAIL)
{

// Read the message buffer
CAN0.readMsgBuf(&nMsgLen, &nMsgBuffer[0]);
INT32U nMsgID = CAN0.getCanId();

// Print message ID to serial monitor
Serial.print("Message ID: 0x");

if(nMsgID < 16) Serial.print("0");
    Serial.print(itoa(nMsgID, sString, 16));

Serial.print("\n\r");

// Print data to serial monitor
Serial.print("Data: ");

for(int nIndex = 0; nIndex < nMsgLen; nIndex++)
{

Serial.print("0x");

if(nMsgBuffer[nIndex] < 16) Serial.print("0");
    
Serial.print(itoa(nMsgBuffer[nIndex], sString, 16));

Serial.print(" ");

}// end for

Serial.print("\n\r\n\r");

}// end if

// Run in 1 sec interval
delay(1000);

}// end loop

Note: To download this sample code, see the section behind the Table of Contents

Obviously, the program has grown compared to the previous one, but most of the added code is used for the data display on the Arduino serial monitor.

First, note on top the line #include <stdlib.h>. The stdlib.h file allows us to convert integer data into ASCII, which is necessary for the data display.

The setup() routine remains the same as it was in the previous example.

In the loop() routine, we first declare some variables for the message reception and code conversion. We still send out the same message as before by calling the CAN0.sendMsgBuf() function.

Next, we check for the reception of a CAN message, and if that is the case, we read the message into the assigned buffer and retrieve the message ID. The following code is all about converting the received data into a human-readable format (ASCII) and display it on the Arduino serial monitor.

Last, but not least, we halt the system for one second (1000 milliseconds). Naturally, under real-life conditions, this delay is not reasonable, since there can occur literally thousands of messages per one second. However, this code is meant merely as a demo sample that proves that the actual CAN communication can be accomplished with very little code.

If you load this program onto two separate Arduinos with CAN shield, you have not only accomplished a full CAN network, you can also see the CAN messages as they are exchanged between the two nodes.

Note: It may sound obvious, but please make sure, in case you use more than one CAN node, that all nodes are initialized with the same baud rate. Using different baud rates is the most common cause when data communication fails.