|
| 1 | +--- |
| 2 | +title: 'Arduino UNO R4 Minima CAN Bus' |
| 3 | +description: 'Learn how to send messages using the CAN bus on the UNO R4 Minima.' |
| 4 | +tags: |
| 5 | + - CAN |
| 6 | +author: 'Karl Söderby' |
| 7 | +--- |
| 8 | + |
| 9 | +In this tutorial you will learn how to use the CAN controller on the **Arduino UNO R4 Minima** board. The CAN controller is embedded in the UNO R4 Minima's microcontroller (RA4M1). CAN is a serial protocol that is mainly used in the automotive industry. |
| 10 | + |
| 11 | +***Please note that CAN controller requires an external transceiver to function. Instructions and hardware examples are provided in this tutorial.*** |
| 12 | + |
| 13 | +## Goals |
| 14 | + |
| 15 | +The goals of this tutorial are: |
| 16 | +- Get an overview of the built-in CAN library |
| 17 | +- Learn how to connect a board to a CAN transceiver module |
| 18 | +- Send a CAN message between two Arduinos |
| 19 | + |
| 20 | +## Hardware & Software Needed |
| 21 | + |
| 22 | +- Arduino IDE ([online](https://create.arduino.cc/) or [offline](https://www.arduino.cc/en/main/software)). |
| 23 | +- [Arduino R4 Minima](/hardware/uno-r4-minima). |
| 24 | +- [Arduino Renesas Core](https://github.com/bcmi-labs/ArduinoCore-renesas) |
| 25 | +- CAN transceiver module\* |
| 26 | +- Jumper wires |
| 27 | + |
| 28 | +In this tutorial, we are using a SN65HVD230 breakout module. |
| 29 | + |
| 30 | +## Controller Area Network (CAN) |
| 31 | + |
| 32 | +The CAN bus uses two wires: **CAN high** and **CAN low**. On the Arduino UNO R4 Minima, these pins are: |
| 33 | +- D5/CANRX0 (receive) |
| 34 | +- D4/CANTX0 (transmit) |
| 35 | + |
| 36 | +To communicate with other CAN devices however, you need a transceiver module. In this tutorial, we will be using a SN65HVD230 breakout. To connect this, you can follow the circuit diagram available in the section below. |
| 37 | + |
| 38 | +For this tutorial, we will use a simple example that sends a CAN message between two UNO R4 Minima devices. If you wish, you can also connect an existing CAN device to the UNO R4 Minima. |
| 39 | + |
| 40 | +## Circuit |
| 41 | + |
| 42 | +To connect the CAN transceiver, follow the table and circuit diagram below: |
| 43 | + |
| 44 | +| UNO R4 Minima | CAN Transceiver | |
| 45 | +| ------------- | --------------- | |
| 46 | +| D5 (CANRX0) | CANRX | |
| 47 | +| D4 (CANTX0) | CANTX | |
| 48 | +| 5V | VIN/VCC/5V | |
| 49 | +| GND | GND | |
| 50 | + |
| 51 | +Then, between the CAN transceivers, connect the following: |
| 52 | + |
| 53 | +| CAN Transceiver 1 | CAN Transceiver 2 | |
| 54 | +| ----------------- | ----------------- | |
| 55 | +| CANH (HIGH) | CANH (HIGH) | |
| 56 | +| CANL (LOW) | CANL (LOW) | |
| 57 | + |
| 58 | +## Code Examples |
| 59 | + |
| 60 | +The following code examples needs to be uploaded to each of the UNO R4 Minima boards, one will send a message, one will receive it. These examples are available in the Renesas core, and using the Arduino IDE, you can access them by navigating to **File > Examples > Arduino_CAN > CANWrite/CANRead** |
| 61 | + |
| 62 | +The library used is built in to the core, so no need to install the library if you have the core installed. |
| 63 | + |
| 64 | +To initialize the library, use `CAN.begin(CanBitRate::BR_250k)`, where a CAN bit rate is specified. Choose between: |
| 65 | +- BR_125k (125000) |
| 66 | +- BR_250k (250000) |
| 67 | +- BR_500k (500000) |
| 68 | +- BR_1000k (1000000) |
| 69 | + |
| 70 | +### CAN Write |
| 71 | + |
| 72 | +To send a CAN message, you can create a `CanMsg` object, which should contain the `CAN_ID`, size and message data. Below is an example on how to create such object. |
| 73 | + |
| 74 | +```arduino |
| 75 | +uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0}; |
| 76 | +memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt)); |
| 77 | +CanMsg msg(CAN_ID, sizeof(msg_data), msg_data); |
| 78 | +``` |
| 79 | + |
| 80 | +After you have crafted a CAN message, we can send it off, by using the `CAN.write()` method. The following example creates a CAN message that increases each time `void loop()` is executed. |
| 81 | + |
| 82 | +```arduino |
| 83 | +#include <Arduino_CAN.h> |
| 84 | +
|
| 85 | +static uint32_t const CAN_ID = 0x20; |
| 86 | +
|
| 87 | +void setup() |
| 88 | +{ |
| 89 | + Serial.begin(115200); |
| 90 | + while (!Serial) { } |
| 91 | +
|
| 92 | + if (!CAN.begin(CanBitRate::BR_250k)) |
| 93 | + { |
| 94 | + Serial.println("CAN.begin(...) failed."); |
| 95 | + for (;;) {} |
| 96 | + } |
| 97 | +} |
| 98 | +
|
| 99 | +static uint32_t msg_cnt = 0; |
| 100 | +
|
| 101 | +void loop() |
| 102 | +{ |
| 103 | + /* Assemble a CAN message with the format of |
| 104 | + * 0xCA 0xFE 0x00 0x00 [4 byte message counter] |
| 105 | + */ |
| 106 | + uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0}; |
| 107 | + memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt)); |
| 108 | + CanMsg msg(CAN_ID, sizeof(msg_data), msg_data); |
| 109 | +
|
| 110 | + /* Transmit the CAN message, capture and display an |
| 111 | + * error core in case of failure. |
| 112 | + */ |
| 113 | + if (int const rc = CAN.write(msg); rc < 0) |
| 114 | + { |
| 115 | + Serial.print ("CAN.write(...) failed with error code "); |
| 116 | + Serial.println(rc); |
| 117 | + for (;;) { } |
| 118 | + } |
| 119 | +
|
| 120 | + /* Increase the message counter. */ |
| 121 | + msg_cnt++; |
| 122 | +
|
| 123 | + /* Only send one message per second. */ |
| 124 | + delay(1000); |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +### CAN Read |
| 129 | + |
| 130 | +To read an incoming CAN message, first use `CAN.available()` to check if data is available, before using `CAN.read()` to read the message. |
| 131 | + |
| 132 | +```arduino |
| 133 | +#include <Arduino_CAN.h> |
| 134 | +
|
| 135 | +void setup() |
| 136 | +{ |
| 137 | + Serial.begin(115200); |
| 138 | + while (!Serial) { } |
| 139 | +
|
| 140 | + if (!CAN.begin(CanBitRate::BR_250k)) |
| 141 | + { |
| 142 | + Serial.println("CAN.begin(...) failed."); |
| 143 | + for (;;) {} |
| 144 | + } |
| 145 | +} |
| 146 | +
|
| 147 | +void loop() |
| 148 | +{ |
| 149 | + if (CAN.available()) |
| 150 | + { |
| 151 | + CanMsg const msg = CAN.read(); |
| 152 | + Serial.println(msg); |
| 153 | + } |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | +## Summary |
| 158 | + |
| 159 | +This tutorial shows how to use the CAN bus available on the UNO R4 Minima, and how to send and receive data using the Arduino_CAN library. |
| 160 | + |
| 161 | +Read more about this board in the [Arduino UNO R4 Minima documentation](/hardware/uno-r4-minima). |
0 commit comments