Skip to content

Buna ziua, #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 2 additions & 275 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,279 +1,6 @@
Arduino MCP2515 CAN interface library
---------------------------------------------------------
[![Build Status](https://travis-ci.org/autowp/arduino-mcp2515.svg?branch=master)](https://travis-ci.org/autowp/arduino-mcp2515)

<br>
CAN-BUS is a common industrial bus because of its long travel distance, medium communication speed and high reliability. It is commonly found on modern machine tools and as an automotive diagnostic bus. This CAN-BUS Shield gives your Arduino/Seeeduino CAN-BUS capibility. With an OBD-II converter cable added on and the OBD-II library imported, you are ready to build an onboard diagnostic device or data logger.
This is a fork of [autowp's](https://github.com/autowp) [MCP2515 CAN interface library](https://github.com/autowp/arduino-mcp2515), modified to remove SPI calls from the class constructor for general safety and compatibility with Mbed-OS boards.

- Implements CAN V2.0B at up to 1 Mb/s
- SPI Interface up to 10 MHz
- Standard (11 bit) and extended (29 bit) data and remote frames
- Two receive buffers with prioritized message storage

**Contents:**
* [Hardware](#hardware)
* [CAN Shield](#can-shield)
* [Do It Yourself](#do-it-yourself)
* [Software Usage](#software-usage)
* [Library Installation](#library-installation)
* [Initialization](#initialization)
* [Frame data format](#frame-data-format)
* [Send Data](#send-data)
* [Receive Data](#receive-data)
* [Set Receive Mask and Filter](#set-receive-mask-and-filter)
* [Examples](#examples)

# Hardware:

## CAN Shield

The following code samples uses the CAN-BUS Shield, wired up as shown:

![MCP2515 CAN-Shield wiring](examples/wiring.png)

## Do It Yourself

If you want to make your own CAN board for under $10, you can achieve that with something like this:

![MCP2515 with MCP2551 wiring](examples/wiring-diy.png)

Component References:
* [MCP2515](https://www.microchip.com/wwwproducts/en/MCP2515) Stand-Alone CAN Controller with SPI Interface
* [MCP2551](https://www.microchip.com/wwwproducts/en/MCP2551) High-speed CAN Transceiver - pictured above, however "not recommended for new designs"
* [MCP2562](https://www.microchip.com/wwwproducts/en/MCP2562) High-speed CAN Transceiver with Standby Mode and VIO Pin - an updated tranceiver since the _MCP2551_ (requires different wiring, read datasheet for example, also [here](https://fragmuffin.github.io/howto-micropython/slides/index.html#/7/5))
* [TJA1055](https://www.nxp.com/docs/en/data-sheet/TJA1055.pdf) Fault-tolerant low speed CAN Transceiver. Mostly used in vehicles.


# Software Usage:

## Library Installation

1. Download the ZIP file from https://github.com/autowp/arduino-mcp2515/archive/master.zip
2. From the Arduino IDE: Sketch -> Include Library... -> Add .ZIP Library...
3. Restart the Arduino IDE to see the new "mcp2515" library with examples

## Initialization

To create connection with MCP2515 provide pin number where SPI CS is connected (10 by default), baudrate and mode

The available modes are listed as follows:
```C++
mcp2515.setNormalMode();
mcp2515.setLoopbackMode();
mcp2515.setListenOnlyMode();
```
The available baudrates are listed as follows:
```C++
enum CAN_SPEED {
CAN_5KBPS,
CAN_10KBPS,
CAN_20KBPS,
CAN_31K25BPS,
CAN_33KBPS,
CAN_40KBPS,
CAN_50KBPS,
CAN_80KBPS,
CAN_83K3BPS,
CAN_95KBPS,
CAN_100KBPS,
CAN_125KBPS,
CAN_200KBPS,
CAN_250KBPS,
CAN_500KBPS,
CAN_1000KBPS
};
```


Example of initialization

```C++
MCP2515 mcp2515(10);
mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
mcp2515.setLoopbackMode();
```

<br>

<br>
You can also set oscillator frequency for module when setting bitrate:

```C++
mcp2515.setBitrate(CAN_125KBPS, MCP_8MHZ);
```

<br>
The available clock speeds are listed as follows:

```C++
enum CAN_CLOCK {
MCP_20MHZ,
MCP_16MHZ,
MCP_8MHZ
};
```

Default value is MCP_16MHZ
<br>

Note: To transfer data on high speed of CAN interface via UART dont forget to update UART baudrate as necessary.

## Frame data format

Library uses Linux-like structure to store can frames;

```C++
struct can_frame {
uint32_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
uint8_t can_dlc;
uint8_t data[8];
};
```

For additional information see [SocketCAN](https://www.kernel.org/doc/Documentation/networking/can.txt)

## Send Data

```C++
MCP2515::ERROR sendMessage(const MCP2515::TXBn txbn, const struct can_frame *frame);
MCP2515::ERROR sendMessage(const struct can_frame *frame);
```

This is a function to send data onto the bus.

For example, In the 'send' example, we have:

```C++
struct can_frame frame;
frame.can_id = 0x000;
frame.can_dlc = 4;
frame.data[0] = 0xFF;
frame.data[1] = 0xFF;
frame.data[2] = 0xFF;
frame.data[3] = 0xFF;

/* send out the message to the bus and
tell other devices this is a standard frame from 0x00. */
mcp2515.sendMessage(&frame);
```

```C++
struct can_frame frame;
frame.can_id = 0x12345678 | CAN_EFF_FLAG;
frame.can_dlc = 2;
frame.data[0] = 0xFF;
frame.data[1] = 0xFF;

/* send out the message to the bus using second TX buffer and
tell other devices this is a extended frame from 0x12345678. */
mcp2515.sendMessage(MCP2515::TXB1, &frame);
```



## Receive Data

The following function is used to receive data on the 'receive' node:

```C++
MCP2515::ERROR readMessage(const MCP2515::RXBn rxbn, struct can_frame *frame);
MCP2515::ERROR readMessage(struct can_frame *frame);
```

In conditions that masks and filters have been set. This function can only get frames that meet the requirements of masks and filters.

You can choise one of two method to receive: interrupt-based and polling

Example of poll read

```C++
struct can_frame frame;

void loop() {
if (mcp2515.readMessage(&frame) == MCP2515::ERROR_OK) {
// frame contains received message
}
}
```

Example of interrupt based read

```C++
volatile bool interrupt = false;
struct can_frame frame;

void irqHandler() {
interrupt = true;
}

void setup() {
...
attachInterrupt(0, irqHandler, FALLING);
}

void loop() {
if (interrupt) {
interrupt = false;

uint8_t irq = mcp2515.getInterrupts();

if (irq & MCP2515::CANINTF_RX0IF) {
if (mcp2515.readMessage(MCP2515::RXB0, &frame) == MCP2515::ERROR_OK) {
// frame contains received from RXB0 message
}
}

if (irq & MCP2515::CANINTF_RX1IF) {
if (mcp2515.readMessage(MCP2515::RXB1, &frame) == MCP2515::ERROR_OK) {
// frame contains received from RXB1 message
}
}
}
}
```


## Set Receive Mask and Filter

There are 2 receive mask registers and 5 filter registers on the controller chip that guarantee you get data from the target device. They are useful especially in a large network consisting of numerous nodes.

We provide two functions for you to utilize these mask and filter registers. They are:

```C++
MCP2515::ERROR setFilterMask(const MASK mask, const bool ext, const uint32_t ulData)
MCP2515::ERROR setFilter(const RXF num, const bool ext, const uint32_t ulData)
```

**MASK mask** represents one of two mask **MCP2515::MASK0** or **MCP2515::MASK1**

**RXF num** represents one of six acceptance filters registers from **MCP2515::RXF0** to **MCP2515::RXF5**

**ext** represents the status of the frame. **false** means it's a mask or filter for a standard frame. **true** means it's for a extended frame.

**ulData** represents the content of the mask of filter.


## Examples

Example implementation of CanHacker (lawicel) protocol based device: [https://github.com/autowp/can-usb](https://github.com/autowp/can-usb)


For more information, please refer to [wiki page](http://www.seeedstudio.com/wiki/CAN-BUS_Shield) .


----

This software is written by loovee ([[email protected]]([email protected] "[email protected]")) for seeed studio,<br>
Updated by Dmitry ([https://github.com/autowp](https://github.com/autowp "https://github.com/autowp"))<br>
and is licensed under [The MIT License](http://opensource.org/licenses/mit-license.php). Check [LICENSE.md](LICENSE.md) for more information.<br>

Contributing to this software is warmly welcomed. You can do this basically by<br>
[forking](https://help.github.com/articles/fork-a-repo), committing modifications and then [pulling requests](https://help.github.com/articles/using-pull-requests) (follow the links above<br>
for operating guide). Adding change log and your contact into file header is encouraged.<br>
Thanks for your contribution.

Seeed Studio is an open hardware facilitation company based in Shenzhen, China. <br>
Benefiting from local manufacture power and convenient global logistic system, <br>
we integrate resources to serve new era of innovation. Seeed also works with <br>
global distributors and partners to push open hardware movement.<br>
#### Except for the examples, everything else is left unchanged, ensuring compatibility with previous sketches.
23 changes: 12 additions & 11 deletions examples/CAN_SpeedTest/CAN_SpeedTest.ino
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
#include <SPI.h>
#include <mcp2515.h>

MCP2515 mcp2515(SS); //Default hardware CS pin (UNO=10, MEGA=53, ESP32=5 etc.)

struct can_frame canMsg;
MCP2515 mcp2515(10);
int cntr = 0;

unsigned long oldTime = 0;
int cntr = 0;

void setup() {
Serial.begin(115200);

mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
delay(300);

while (mcp2515.reset() != MCP2515::ERROR_OK) {
Serial.println("MCP2515 init failure!");
}

mcp2515.setBitrate(CAN_100KBPS); //set the bitrate to your requirements
mcp2515.setNormalMode();

Serial.println("------- CAN Speedtest ----------");
}

void loop() {
Expand Down
57 changes: 43 additions & 14 deletions examples/CAN_read/CAN_read.ino
Original file line number Diff line number Diff line change
@@ -1,33 +1,62 @@
#include <SPI.h>
#include <mcp2515.h>
MCP2515 mcp2515(SS); //Default hardware CS pin (UNO=10, MEGA=53, ESP32=5 etc.)

struct can_frame canMsg;
MCP2515 mcp2515(10);

unsigned long timer = 0;
char debug_time[8];

void setup() {
Serial.begin(115200);
delay(300);

while (mcp2515.reset() != MCP2515::ERROR_OK) {
Serial.println("MCP2515 init failure!");
}

mcp2515.setBitrate(CAN_100KBPS); //set the bitrate to your requirements

/*
//Set MASK0 and MASK1 to 0x7FF to close the module from all IDs.
mcp2515.setFilterMask(MCP2515::MASK0, false, 0x7FF);
mcp2515.setFilterMask(MCP2515::MASK1, false, 0x7FF);

//Set FILTER0...5 to only receive messages from what IDs you need (delete unwanted).
mcp2515.setFilter(MCP2515::RXF0, false, 0x...);
mcp2515.setFilter(MCP2515::RXF1, false, 0x...);
mcp2515.setFilter(MCP2515::RXF2, false, 0x...);
mcp2515.setFilter(MCP2515::RXF3, false, 0x...);
mcp2515.setFilter(MCP2515::RXF4, false, 0x...);
mcp2515.setFilter(MCP2515::RXF5, false, 0x...);
*/

mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
mcp2515.setNormalMode();

Serial.println("------- CAN Read ----------");
Serial.println("ID DLC DATA");
Serial.println(" Time | IDs | Data");
Serial.println("--------+-----+------------------------");

timer = millis();
}

void loop() {
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
Serial.print(canMsg.can_id, HEX); // print ID
Serial.print(" ");
Serial.print(canMsg.can_dlc, HEX); // print DLC
Serial.print(" ");
snprintf(debug_time, 8, "%7lu", millis() - timer);
timer = millis();

Serial.print(debug_time); // print the time since the last message
Serial.print(" | ");

for (int i = 0; i<canMsg.can_dlc; i++) { // print the data
Serial.print(canMsg.data[i],HEX);
Serial.print(" ");
char can_id[4];
snprintf(can_id, 4, "%03lX", canMsg.can_id);
Serial.print(can_id); // print ID
Serial.print(" | ");

for (int i = 0; i < canMsg.can_dlc; i++) { // print the data
if (canMsg.data[i] < 0x10) Serial.print(0);
Serial.print(canMsg.data[i], HEX);
Serial.print(' ');
}

Serial.println();
}
}
}
Loading