<<

RS485 CAN HAT

RS485 CAN HAT User Manual

OVERVIEW

The RS485 CAN HAT will enables your Pi to communicate with other devices stably in long-distance via RS485/CAN functions.

FEATURES

⚫ Raspberry Pi connectivity, compatible with Raspberry Pi Zero/Zero W/Zero

WH/2B/3B/3B+

⚫ CAN function, onboard CAN controller MCP2515 via SPI interface, with transceiver

SN65HVD230

⚫ RS485 function, controlled via UART, half-duplex communication, with transceiver

SP3485

⚫ Reserved control pins, allows to work with other control boards

⚫ Comes with development resources and manual (examples in wiringPi/python)

SPECIFICATIONS

Operating voltage : 3.3V

CAN controller : MCP2515

1 / 24 RS485 CAN HAT

CAN transceiver : SN65HVD230

485 transceiver : SP3485

Dimension : 65mm x 30mm

Mounting hole size : 3.0mm

INTERFACES

CAN:

PIN Raspberry Pi Description

3V3 3V3 3.3V Power

GND GND Ground

SCK SCK SPI Clock

MOSI MOSI SPI Data input

MISO MISO SPI Data output

CS CE0 Data/Command selection

INT PIN22 /GPIO.6/P25 Interrupt

RS485:

PIN Raspberry Pi Description

3V3 3V3 3.3V power

GND GND Ground

RXD RXD RS485 UART receive

TXD TXD RS485 UART transmit

RSE PIN7/GPIO.7/P4 RS485 RX/TX setting

RSE pin could not be used because module is set to auto receiver and transmit in hardware by default.

2 / 24 RS485 CAN HAT

CONTENT

Overview...... 1

Features ...... 1

Specifications ...... 1

Interfaces ...... 2

Hardware Description ...... 5

CAN ...... 5

RS485 BUS ...... 6

How to use ...... 9

Libraries installtion ...... 9

CAN test ...... 10

Hardware ...... 10

Preparation ...... 10

C code example...... 11

Python example ...... 12

RS485 Test ...... 13

Hardware ...... 13

3 / 24 RS485 CAN HAT

Preparation ...... 13

Python code ...... 16

Code Analysis ...... 17

CAN ...... 17

C code ...... 17

Python ...... 20

RS485 ...... 22

wiringPi code ...... 22

Python code ...... 24

4 / 24 RS485 CAN HAT

HARDWARE DESCRIPTION

CAN BUS

CAN module could process packets transmit/receive on CAN bus. Packets transmit: first store packet to related buffer and control register. Use SPI interface to set the bits on control register or enable transmit pin for transmitting. Registers could be read for detecting communication states and errors. It will first check if there are any errors of packets detected on CAN bus, then verify it with filter which is defined by user. And store packet to one of buffers if it has no errors.

Raspberry Pi cannot support SPI bus, so this module use SPI interface and on board a receiver/transmitter for CAN communication.

Microchip Technology’s

MCP2515 is a stand-alone Controller

Area Network (CAN) controller that implements the CAN specification, version 2.0B. It is capable of transmitting and receiving both standard and extended data and remote frames. The MCP2515 has two acceptance masks and six acceptance filters that are used to filter out unwanted messages, thereby reducing the host MCUs overhead. The MCP2515 interfaces with (MCUs) via an industry standard Serial Peripheral Interface (SPI), that is Raspberry Pi can

5 / 24 RS485 CAN HAT communicate with MCP2515 via SPI interface without external driver. What we need to do is to enable the kernel driver on devices tree.

For more details, please refer to datasheet.

SN65HVD230 from TEXAS INSTRUMENTS is a CAN transceiver, which is designed for high communication frequency, anti-jamming and high reliability CAN bus communication. SN65HVD230 provide three different modes of operation: high- speed, slope control and low-power modes. The operation mode can be controlled by

Rs pin. Connect the Tx of CAN controller to SN65HVD230’s data input pin D, can transmit the data of CAN node to CAN network; And connect the RX of CAN controller to SN65HVD230’s data input pin R to receive data.

RS485 BUS

The SP3485 is a low power half-duplex transceiver that meet the specifications of

RS485 serial protocols. RO is Receiver output pin and DI is Driver input pin. RE̅̅̅̅ is

Receiver Output Enable pin which is Active LOW and DE is Driver output Enable pin

Active HIGH. A is Driver Output/Receiver input non-inverting port and B is Driver

6 / 24 RS485 CAN HAT

Output/Receiver input, Inverting port. When A-B >+0.2V, RO pin will output logic 1; and when A-B<-0.2V, RO pin will output logic 0. 100Ω resistor is recommended to add between A and B ports.

According to the hardware description, RE and DE pin of SP3845 are set to enable receive and send.

This module is set to the way that hardware automatically receive/send, you can also change to software receive/sending by changing the 0Ω resistors on board.

Hardware auto control:

7 / 24 RS485 CAN HAT

Receiving data: P_TX is in idle state, which is high level, transistor breakover, RE pin of

SP3485 is low to be active. RO pin begins to receive data from 485AB port.

Sending data: P_TX will get a pull-down level, toggle that sending data. Transistor cut off, DE pin is high to enable sending. In sending states, if the data sent is “1”, transistor will turn to breakover which looks like Receiving states, however, the chip is in high impedance sate, data “1” will still be sending instead of changing to receiving.

8 / 24 RS485 CAN HAT

HOW TO USE

LIBRARIES INSTALLTION

To use the demo codes, you should install libraries (wiringPi, bcm2835, python) first, otherwise the codes cannot work properly. About how to install libraries, you can refer to Wiki page:

https://www.waveshare.com/wiki/Libraries_Installation_for_RPi

For python, you should install two more libraries as below:

sudo apt-get install python-pip sudo pip install python-can

Visit Waveshare Wiki: https://www.waveshare.com/wiki and search with “RS485 CAN

CAPE”, download the demo code.

Decompressed and copy to Raspberry Pi.

9 / 24 RS485 CAN HAT

CAN TEST

HARDWARE

Raspberry Pi 3B x2

Waveshare RS485 CAN HAT x2

PREPARATION

1. Insert RS485 CAN HAT to Raspberry Pi, and then modify config.txt file:

sudo vi /boot/config.txt

2. Append these statements to the file:

dtparam=spi=on

dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25,spimaxfrequency=1000000

3. Save and exit, then restart your Pi.

sudo reboot

4. After restart, check if initialize successfully:

dmesg | grep -i '\(can\|spi\)'

It will print information as below:

The information will be different if RAS485 CAN HAT doesn’t be inserted:

10 / 24 RS485 CAN HAT

In this case, you need to check if the module is connected? If SPI interface and

CP2515 kernel driver is enable and restart Raspberry Pi.

5. Connect the H and L port of RS485 CAN HAT to another’s.

C CODE EXAMPLE

1. List the folder of demo code you can get as below:

2. Set one HAT as receiver: Enter the directory of receiver and run the code

cd /RS485_CAN_HAT_code/can/c/receive

make

sudo ./can_receive

3. Set another as Sender: Enter the directory of send and run the code

cd /RS485_CAN_HAT_code/can/c/send

make

sudo ./can_send

11 / 24 RS485 CAN HAT

At the same time you can find the receiver receive the packet from sender:

PYTHON EXAMPLE

1. List the folder:

2. Set the receiver first:

sudo python can_reveive.py

3. Then the sender:

sudo python can_send.py

12 / 24 RS485 CAN HAT

RS485 TEST

HARDWARE

Raspberry Pi 3B x2

RS485 CAN HAT x2

PREPARATION

The serial of Raspberry Pi is used for Linux console output by default, so we need to disable it first:

1. Run command to open raspi-config:

sudo raspi-config

2. Choose Interfaces Options ->Serial->no

13 / 24 RS485 CAN HAT

3. Open file /boot/config.txt, add the statement to the end:

enable_uart=1

4. For Raspberry Pi, the serial port is used for Bluetooth, which should be commend:

#dtoverlay=pi-minuart-bt

5. reboot Raspberry Pi

sudo reboot

6. Connect A and B port of HAT to another’s

WIRINGPI CODE

14 / 24 RS485 CAN HAT

1. List folders:

2. Set receiver:

cd /RS485_CAN_HAT_code/can/c/receive

make

sudo ./can_receive

3. Set sender:

cd /RS485_CAN_HAT_code/can/c/send

make

sudo ./can_send

The packet received at receiver is as below:

15 / 24 RS485 CAN HAT

PYTHON CODE

1. List folders:

2. First set receiver:

sudo python reveive.py

3. Set sender:

sudo python send.py

16 / 24 RS485 CAN HAT

CODE ANALYSIS

CAN

We provide two codes for CAN communication, one is C code and another is python.

C code use socket-can and python use similar libraries as well.

C CODE

This example uses socket skill similar to network coding skill of Linux. If you have studied Linux network coding, you will familiar to it: Socketcan is method for CAN protocol in Linux.

Step 1: Open socket

s = socket(PF_CAN, SOCK_RAW, CAN_RAW); if it failed it will return -1

Step 2: Target device can0

strcpy(ifr.ifr_name, "can0");

ret = ioctl(s, SIOCGIFINDEX, &ifr);

Step 3: Bind socket to CAN interface.

addr.can_family = AF_CAN;

addr.can_ifindex = ifr.ifr_ifindex;

ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));

17 / 24 RS485 CAN HAT

Step 4: Set rule that only send

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

Step 5: Set the data

struct can_frame frame;

frame.can_id = 0x123;

frame.can_dlc = 8;

frame.data[0] = 1;

frame.data[1] = 2;

frame.data[2] = 3;

frame.data[3] = 4;

frame.data[4] = 5;

frame.data[5] = 6;

frame.data[6] = 7;

frame.data[7] = 8;

Step 6: Transmit data

nbytes = write(s, &frame, sizeof(frame));

Calling write() function to write the data to socket, it will return-1 if failed and return the number of byte if success. We could use the return value to check if it is successfully sending.

if(nbytes != sizeof(frame)) {

18 / 24 RS485 CAN HAT

printf("Send Error frame[0]!\r\n");

system("sudo ifconfig can0 down");

}

Step 7: Close socket and CAN device

close(s);

system("sudo ifconfig can0 down");

Note: if you dont close CAN device, system will prompt CAN bus is busy at next sending.

For Receiving:

1. It is different when binding socket

addr.can_family = PF_CAN;

addr.can_ifindex = ifr.ifr_ifindex;

ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));

if (ret < 0) {

perror("bind failed");

return 1;

}

2. The receive could be defined to only receive socket whose ID is 0x123

struct can_filter rfilter[1];

19 / 24 RS485 CAN HAT

rfilter[0].can_id = 0x123;

rfilter[0].can_mask = CAN_SFF_MASK;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

3. Read data read()

nbytes = read(s, &frame, sizeof(frame));

Return number of bytes it read.

For more information about socket-can coding please refer: https://www.kernel.org/doc/Documentation/networking/can.txt

PYTHON

Before use python sample, check if python-can library has been installed

Build up CAN device first:

os.system('sudo ip link set can0 type can bitrate 100000')

os.system('sudo ifconfig can0 up')

Step 1: Connect to CAN bus

can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan_ctypes')# socketcan_native

Step2: Create message

msg = can.Message(arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7], extended_id=False)

Step 3: Send message

20 / 24 RS485 CAN HAT

can0.send(msg)

Step 4: Finial close device as well

os.system('sudo ifconfig can0 down')

Receive Data:

msg = can0.recv(10.0) recv() define the timeout of receiving.

For more information please refer to: https://python-can.readthedocs.io/en/stable/interfaces/socketcan.

21 / 24 RS485 CAN HAT

RS485

For RS485 communication, we provide two sample code, one is based on wiringPi library and another is Python.

WIRINGPI CODE

Steps 1: Set Receiving and sending

The RE and DE pin of SP3485 are used for enable input and output (Chapter

Hardware description).

#define EN_485 18

if(wiringPiSetupGpio() < 0) { //use BCM2835 Pin number table

printf("set wiringPi lib failed !!! \r\n");

return -1;

} else {

printf("set wiringPi lib success !!! \r\n");

}

pinMode(EN_485, OUTPUT);

digitalWrite(EN_485,HIGH);

The example code sets module to sending states. the Pin18 is the ID based on bcm2835 libraries. For wiringPi, the pin id of bcm2835 is workable as well as wiringpi pin id. wiringPiSetupGpio() is called for using bcm2835 pin id and wiringPiSetup() called for using wiringPi pin id.

22 / 24 RS485 CAN HAT

Step 2: Create file descriptor, open serial /dev/ttyS0 and set baudrate

if((fd = serialOpen ("/dev/ttyS0",9600)) < 0) {

printf("serial err\n");

return -1;

}

Step 3: Send data

serialFlush(fd);

serialPrintf(fd,"\r");

serialPuts(fd, "12345");

serialFlush() #clean all data on serial and wait for sending

serialPrintf() #similar to printf function, bind the tansmit datato file desriptor

serialPuts() #Send string which end with nul to serial device marked by related file

descriptor

The serialGetchar(fd) function will return a character which is should used next of serial device, it will cause some wrong errors, so the sender should send a character

“\r” to avoid this phenomenon. (If you have better way, kindly to contact us)

For more information about functions, please refer to:

http://wiringpi.com/reference/serial-library/

23 / 24 RS485 CAN HAT

PYTHON CODE

Using Python to control RS485 will be much easy. Python could operate serial directly:

Open serial file and set the baud rate as well.

t = serial.Serial("/dev/ttyS0",115200)

Set the command which you want to send:

command = ["a","b","c",",","1","5",0x24,0x48]

Write the data to serial, and it will response the numbers of bytes written:

len = ser.write(command)

print("len:"),len

Reading:

Return the number of bytes in buffer:

ser.inWaiting()

Read data (length is definable):

ser.read(ser.inWaiting())

24 / 24