Skip to content

Commit

Permalink
MegaMetaCheckIn!
Browse files Browse the repository at this point in the history
Revised header for all source files
Removed need to instantiate variable within user code
Standardized on instance named "CAN" (I know, right?)
Revised examples to use standard bitrate of 500kbps (CAN_BPS_500K)
Tested with Uno, Due & Teensy
  • Loading branch information
McNeight committed Jun 19, 2014
1 parent 063fd18 commit 8f9a4db
Show file tree
Hide file tree
Showing 19 changed files with 882 additions and 379 deletions.
73 changes: 41 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
CAN-Library
===========

Yet another CAN library for Arduino using MCP2515 controller.

I have tried most of the MCP2515 libraries out there and found that some were either: shield specific, purpose specific or protocol specific. These libraries were also very complicated and brought too many features out to the sketch that could be performed within the library. These libraries did have some good features and I have tried to take the best features out there and put them here. I have also made it more “Arduino” user friendly by using known functions like read(), send(), begin().

Since I have taken features from so many libraries I can’t tell what came from where, so in order not to violate any GPL, LGPL or any other license out there I am trying to give credit where credit is due. I am only a contributor to this library and some of the work here might not be mine. I can take credit in putting it together and releasing back to the public to make any variation as needed.

I will add more Arduino examples using CAN messages either CAN, J1939 or OBD2 (CAN) in the future.

Features:

CAN V2.0B
8 byte length in the data field
Standard and extended data frames
Two receive buffers
Three Transmit Buffers
SPI Interface with selectable CS via Arduino Sketch

Supported Bit rates (Confirmed and tested with Vector CANalyzer and Peak pCAN usb)

10 kpbs; 20 kpbs; 50 kbps; 100 kbps; 125 kbps; 250 kbps; 500 kbps; 1000 kbps

Intended to be used with ATMEL ATMega328P with Arduino bootlader, MCP2515 Stand-Alone CAN Controller and MCP2561/62 High-Speed CAN Transceivers. Have not tested with other Arduino ATMEL chips but it will more likely work.

Message structure allows to read messages for CAN (standard, extended), J1939 and CANopen with the correct message format.

Selectable SPI CS pin allows to use library with most of the MCP2515 CANshield variations out there (Sparkfun shield, Seeedstudio, breadboard CAN, etc)



This library allows you to communicate with multiple types of CAN controllers
using a consistent API, making CAN communications easier through Arduino.

The idea behind this CAN library is to use a similar approach to Adafruit's
Unified Sensor library (https://github.com/adafruit/Adafruit_Sensor) by
standardizing CAN frame message structures, filters, masks, buffers, etc
to be used with a wide variety of CAN controllers. This library currently
supports the following controllers:

* Microchip MCP2515 through the SPI interface
* Tested using various Arduino and Arduino-compatible controllers
* Atmel SAM3X family of MCU
* Tested using the SAM3X8E on the Arduino Due
* Freescale Kinetis K2x family of MCU
* Tested using the MK20DX256VLH7 on the PJRC Teensy 3.1

Since I have taken features from so many libraries I can’t tell what came
from where, so in order not to violate any GPL, LGPL or any other license
out there I am trying to give credit where credit is due. I am only a
contributor to this library and some of the work here might not be mine.
I can take credit in putting it together and releasing back to the public
to make any variation as needed. This is a work in progress library with
no current release.

For the MCP2515 library release see CAN_MCP2515 branch on this repo

```Arduino
#include <Arduino.h>
#include <CAN.h>
#if defined(ARDUINO_ARCH_AVR) // Arduino with SPI interface to MCP2515 chip
#include <SPI.h>
#include <CAN_MCP2515.h>
#elif defined(ARDUINO_ARCH_SAM) // Arduino Due
#include <CAN_SAM3X8E.h>
#elif defined(__MK20DX256__) // Teensy 3.1
#include <CAN_K2X.h>
#else
#error “Your CAN controller is currently unsupported.”
#endif
```
108 changes: 0 additions & 108 deletions examples/CAN_ExtendedPingPong/CAN_ExtendedPingPong.ino

This file was deleted.

180 changes: 180 additions & 0 deletions examples/ExtendedPingPong/ExtendedPingPong.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/* CAN extended Frames with Ping/Pong sending
This example sets up a receive and transmit mailbox on both CAN devices.
First NODE0 sends to NODE1. When NODE1 receives it sends to NODE0. PING/PONGs forever
and as quickly as possible - This will saturate the bus so don't have anything important connected.
Authors: Thibaut Viard, Wilfredo Molina, Collin Kidder, Pedro Cevallos & Neil McNeight
Created: 06/01/14
Updated: 06/18/14
As per wiki information:
"CAN bus is a message-based protocol, designed specifically for automotive
applications but now also used in other areas such as aerospace, maritime,
industrial automation and medical equipment."
For more info http://en.wikipedia.org/wiki/Controller_area_network
*/

#include <Arduino.h>
#include <CAN.h>

#if defined(ARDUINO_ARCH_AVR) // Arduino with SPI interface to MCP2515 chip
#include <SPI.h>
#include <CAN_MCP2515.h>
#elif defined(ARDUINO_ARCH_SAM) // Arduino Due
#include <CAN_SAM3X8E.h>
#elif defined(__MK20DX256__) // Teensy 3.1
#include <CAN_K2X.h>
#else
#error “Your CAN controller is currently unsupported.”
#endif

// Define our CAN speed (bitrate).
#define bitrate CAN_BPS_500K

//Comment out for one node, and leave uncommented for the other node
#define NODE1
#ifdef NODE1
#define NODETX_CAN_ID 0x15555555
#define NODERX_CAN_ID 0x0AAAAAAA
#else
#define NODETX_CAN_ID 0x0AAAAAAA
#define NODERX_CAN_ID 0x15555555
#endif

// CAN frame max data length
#define MAX_CAN_FRAME_DATA_LEN 8

uint32_t sentFrames, receivedFrames;

CAN_Frame frameTX, frameRX, incoming;

void setup()
{
Serial.begin(115200); // Initialize Serial communications with computer to use serial monitor

//Set CAN speed. Note: Speed is now 500kbit/s so adjust your CAN monitor

CAN.begin(bitrate);

delay(4000); // Delay added just so we can have time to open up Serial Monitor and CAN bus monitor. It can be removed later...

// Output will be formatted as a CSV file, for capture and analysis
Serial.println(F("millis(),ID,RTR,EID,Length,Data0,Data1,Data2,Data3,Data4,Data5,Data6,Data7"));

// Initialize frame counters
sentFrames = 0;
receivedFrames = 0;

//Initialize the definitions for the frames we'll be sending.
//This can be done here because the frame never changes
frameTX.id = NODETX_CAN_ID;
frameTX.length = MAX_CAN_FRAME_DATA_LEN;
//We are using extended frames so mark that here. Otherwise it will just use
//the first 11 bits of the ID set
frameTX.extended = 1;

// Process
processTXFrame();
// Send out the first frame
CAN.write(frameTX);
}

// Test rapid fire ping/pong of extended frames
void loop()
{
if (CAN.available())
{
frameRX = CAN.read();
receivedFrames++;
// Process
processRXFrame();

// Only send frames after receiving one, otherwise bus is flooded
processTXFrame();
CAN.write(frameTX);
}
}

void processTXFrame()
{
sentFrames++;
frameTX.data[3] = sentFrames;
frameTX.data[2] = sentFrames >> 8;
frameTX.data[1] = sentFrames >> 16;
frameTX.data[0] = sentFrames >> 24;

frameTX.data[7] = receivedFrames;
frameTX.data[6] = receivedFrames >> 8;
frameTX.data[5] = receivedFrames >> 16;
frameTX.data[4] = receivedFrames >> 24;
}

void processRXFrame()
{
if (frameRX.id == NODERX_CAN_ID)
{
uint32_t otherNodeSent = (uint32_t)frameRX.data[3];
otherNodeSent |= ((uint32_t)frameRX.data[2] << 8);
otherNodeSent |= ((uint32_t)frameRX.data[1] << 16);
otherNodeSent |= ((uint32_t)frameRX.data[0] << 24);

uint32_t otherNodeReceived = (uint32_t)frameRX.data[7];
otherNodeReceived |= ((uint32_t)frameRX.data[6] << 8);
otherNodeReceived |= ((uint32_t)frameRX.data[5] << 16);
otherNodeReceived |= ((uint32_t)frameRX.data[4] << 24);

// Serial.print("I am node 0x");
// Serial.println(NODETX_CAN_ID, HEX);
if ((sentFrames % 5000) == 0)
{
Serial.print("IS:");
Serial.print(sentFrames);
Serial.print(" OR:");
Serial.println(otherNodeReceived);
Serial.print("IR:");
Serial.print(receivedFrames);
Serial.print(" OS:");
Serial.println(otherNodeSent);
}

int16_t txDropped = sentFrames - otherNodeReceived;
if (txDropped < 0)
{
Serial.print("Node 0x");
Serial.print(NODERX_CAN_ID, HEX);
Serial.print(" received ");
Serial.print(abs(txDropped));
Serial.println(" more frames than I transmitted.");
}
else if (txDropped > 0)
{
Serial.print(txDropped);
Serial.print(" frames dropped from here to node 0x");
Serial.println(NODERX_CAN_ID, HEX);
}

int16_t rxDropped = receivedFrames - otherNodeSent;
if (rxDropped < 0)
{
Serial.print("I received ");
Serial.print(abs(rxDropped));
Serial.print(" more frames than node 0x");
Serial.print(NODERX_CAN_ID, HEX);
Serial.println(" transmitted.");
}
else if (rxDropped > 0)
{
Serial.print(rxDropped);
Serial.print(" frames dropped from node 0x");
Serial.print(NODERX_CAN_ID, HEX);
Serial.println(" to here.");
}

// Synchronize the counters
sentFrames = otherNodeReceived;
receivedFrames = otherNodeSent;
}
}
Loading

0 comments on commit 8f9a4db

Please sign in to comment.