We have already tried using the MKR CAN shield from Arduino, which is helpful for quick and small applications or simply to get started using CAN.
However, we know that MKR-family boards are not the only CAN capable. Arduino UNO R4 (Wi-Fi and Minima) and, Arduino Giga R1 Wi-Fi also have this feature, but they need a transceiver to deploy the CAN communication completely.
Sometimes we need to run tests or want to create small projects with our Arduino boards. Still, if using CAN-capable boards (other than MKR-family along with MKR CAN Shield) we could not complete the communication due to a transceiver lack, so we decided to design a shield compatible with UNO and MEGA board format (we refer to as "MEGA" format due to the physical design, remember that Arduino Mega and Arduino Giga R1 have the same count and distribution of pins). In this article, we will show you the creation process of the Electronic Cats CAN Shield and how we tested this board in an application.
But first, let’s remember the essentials of CAN.
CAN Protocol
Designed in 1986 for the Robert Bosch GmbH company and specified in the ISO 11898 standard, the Controlled Area Network protocol is used for real-time and high-integrity applications. This communication protocol is most used in the automotive and aeronautics industry due to its reliability.
The CAN Bus can transmit as slow as 50 Kbit/s and as fast as 1 MB/s, and its reliability is not affected by these speed rates.
Two elements compose a CAN module:
- Controller: for managing the mounting of the CAN frames, error checking (during transmission or in any node inside the network), and collision detection.
- Transmitter/Receiver or Transceiver: for coding and decoding all the messages in the bus; synchronization, controlling the electric levels carrying the signal to be transmitted and media access control.
This is a bus topology, which uses a twisted pair of cables with a 120-ohm impedance. Two signals work to carry the information: CAN_H and CAN_L; these signals differ in their voltage magnitude (at least 1.5V). The voltage difference helps with the electromagnetic fields that can surround the bus: if the wires have a voltage variation, the voltage difference between CAN_H and CAN_L will remain the same.
A CAN data frame is composed of:
- Identifier: 11 bits (standard) or 29 bits (extended) long.
- Control field: 12 bits long. 4 bits inform about the frame length (in bytes) and the remaining 8 bits have the data transmitted (up to 8 bytes can be sent in a simple CAN message if using CAN FD).
- CRC field: ensures the data sent integrity.
CAN FD: CAN Flexible Data-rate. This is a CAN protocol extension that allows for a higher data transfer rate.
The Transceiver we choseWe chose the Texas Instruments TCAN1051HGV transceiver for our shields. It is CAN FD capable; then it is suitable for our needs to transfer big amounts of data, so we will be able to send messages up to 8 bytes long. In addition, is a fault-protected device.
Design ProcessTwo shields were designed due to the different dimensions of each board (UNO and MEGA formats).
The MEGA format can be used with the Arduino Giga R1 WiFi board. And the UNO format with UNO R4 family boards:
The design of the board was relatively easy since the latest version of KiCAD allows us to start a new project from a template. In this case, the templates for UNO boards and MEGA boards are already available in KiCAD.
Now that we had the template selected and selected our transceiver, we consulted the transceiver’s datasheet to see which pins we needed to connect and where. We found a typical application section on the datasheet that was really useful since it was very similar to our application.
We followed the design instructions/suggestions found in that section of the datasheet and ended up with a very similar design for our shields.
The design of the shield for the UNO format can be used with Arduino UNO R4 (Wi-Fi and Minima). However, the CAN TX and CAN RX pins are different for each board, so we implemented a jumper to change the RX/TX paths to select the UNO board.
After that, we made the typical connections to CANH and CANL using 260 Ohm resistors in series.
We supplied the transceiver with 5 V for its operation, connected it to the ground, and then used the VIO pin to set the 3.3V level shift for compatibility with our 3.3V MCUs.
Both boards have the CS pin, which helps to set the transceiver to Normal mode or Silent Mode. In Normal mode, the driver and receiver are fully operational and CAN communication is bidirectional. On the other hand, in Silent mode, the CAN driver is disabled, preventing communication from the TXD pin to the CAN bus. This pin in both shields is connected to GPIO 2 so we can set the mode via code.
Assembling the shieldsOnce we received the PCB and their components, we assembled and soldered our shields at the office.
Not all the Arduino boards are CAN bus capable. Here is the list of the boards compatible with each shield:
We tested the shields with the three different boards. We decided to create a small demo where we could read three sensors and control two actuators. Also, we added a fifth device: a Portenta Machine Control, as the main device in this CAN network.
Nodes
- Arduino Giga R1 Wi-Fi and BME280. This node reads the environmental temperature and atmospheric pressure to send the data to the CAN Bus. This is identified as node number one.
- Arduino UNO R4 Minima and HC-020K encoder module. This node works as a tachometer. The encoder counts the pulses from a DC motor shaft. The pulses are converted to velocity (Km/h) and then shared with the CAN Bus. This is identified as node number three.
- Arduino UNO R4 Wi-Fi and DC Motor. This node receives messages from the CAN Bus but only processes the instructions from the Main Device to modify the speed of the DC Motor. The DC Motor is related to the Node 3, which reads the motor’s speed. This is identified as node number five.
- Arduino Giga R1 Wi-Fi, relay, and DC Lamp. This node receives messages from the CAN Bus but only processes the instructions from the Main Device to modify the status of a DC Lamp. We used a relay to energize the lamp because the last one works using 12V, but Giga’s board digital outputs are only 3.3V capable. This is identified as node number seven.
Main Device
Our central controller, the brain for the application is an Arduino Portenta Machine Control.
This is an industrial solution offering different communication protocols, including CAN Bus.
Portenta Machine Control receives data from nodes 1 and 3. Node’s 1 data is just informative, whereas node’s 3 data is used to modify the speed for a DC Motor connected to node 5. The Main device sends the right commands to node 5 to control the speed.
In addition, Portenta Machine Control enables a digital input to read an inductive sensor. The status of this sensor is shared with the CAN Bus and the designated node (node 7) turns a lamp on to complete the tester action.
Assemblingthe demo
Huge quantity of wires! We used a small register box to connect the main buses: positive voltage and ground.
Outside the box are all the boards with their respective shields (if needed), and their sensors/actuators. The CAN bus was also placed outside the box so you can look at it.
Ready to go?
Here are the outcomes for this project.
Final notesThe project was not perfect from the start, we made a mistake in the V1.0 for the UNO format shield. We got confused during the schematic creation and the TX and RX wires were exchanged for both Wi-Fi and Minima boards. Of course, this led to a non-working shield, and the communication was never completed. We noticed this error after several tests (including, connecting with separate wires a UNO Wi-Fi/UNO Minima board with the MEGA format shield). The development board always worked with the MEGA format shield, so then we discovered our silent but important mistake. Yikes!
Currently, the firmware for every board works properly, except for the sync between the reading and writing process of the main device that sends the command to turn on or turn off the lamp. Seems that when the main device is not in the “writing process”, it will always send a “turn off” command. This is a feature that can be fixed in a future case. How would you solve it?
Hope you have enjoyed this tutorial!
If you are interested in the complete content to deploy your demo, visit our repository on GitHub.
See you next time! 😼
Comments
Please log in or sign up to comment.