Connecting Serial Devices

The RevPi Flat has two RS485 interfaces. This allows you to use serial protocols such as Modbus and to integrate devices such as smart meters or solar inverters into your system at low cost.

 

The connections are marked “RS485-0” and “RS485-1”. The RS485-0 connection is to a 3-pin terminal, while the RS485-1 connection is to an RJ11 socket. Both connections are isolated galvanically from each other and from the RevPi Flat system.

The data lines of the RS485 terminal are marked P (positive) and N (negative). For other devices, these lines are often referred to as D+ and D- or A and B.

 

Only the lines N and P are required for the actual data transmission. We recommend to use a twisted pair for longer line lengths or larger baud rates.

Wiring the RS485-0 connection

GND

Ground

N

Negative

P

Positive

 

Wiring the RS485-1 connection

1: NC

Not connected

2: GND

Ground

3: N

Negative

4: P

Positive

5: GND

Ground

6: NC

Not connected

 

Reference Potential

Should a reference potential be necessary, you can use the “GND” electrical circuit ground of the respective RS485 bus for this purpose. Since the two RS485 systems have complete galvanic isolation from each other and from the rest of the RevPi Flat circuitry, these “GND” connections are also isolated galvanically from each other and from the RevPi Flat GND connection.

Shielding

Cables having a length over 30 meters and cables leaving the building should be shielded. To further improve the EMC properties of the shield, you can connect the shield to the equipotential bonding rail of the distribution box if necessary. Such a connection can easily be made with a contact force spring.

Bit Rates

Linux addresses the interfaces via the character devices “/dev/ttyAMA0” and “/dev/ttyS0”. You can configure bit rates from 50 to 3,000,000 for “/dev/ttyAMA0” and from 1,200 to 4,000,000 for “/dev/ttyS0”. However, occasional reception errors may occur at more than 230,400 bits. The reason is that the UART of the Raspberry Pi, to which the interface is connected, has only a 16 byte FIFO and does not support DMA. The higher the bit rate, the more often the FIFO is not read out fast enough and received data is lost. For example, there are 1 – 2 errors per 50 MByte received at 460,800 bits and there are about 10 errors at 921,600 bits. If your RevPi Flat mainly sends data and only rarely receives it, you can also use higher bit rates. Otherwise we recommend to not set more than 230,400 baud.

Termination

The interface has an integrated 120 ohm terminating resistor. This termination is switched off after booting. This is safest, as no communication is possible if several devices on the RS485 bus switch on their termination. Short cables allow for communication also without termination. For longer distances you should switch the termination on if your RevPi Flat is at the end of the bus line.

Switch the termination on and off as follows:

  • Open the character device “/dev/ttyAMA0” or “/dev/ttyS0” with “open()”.
  • Read out the current RS485 configuration with a “TIOCGRS485 ioctl()”.
  • Set or delete the SER_RS485_TERMINATE_BUS flag in the “struct serial_rs485”.
  • Activate the changed RS485 configuration with a “TIOCSRS485 ioctl()”.
  • If necessary, send or receive the data with “read()” or “write()”.
  • Close the character device with “close()”.

Attention: You have to repeat these steps after each boot if you want to enable termination.

We have prepared a C listing including these steps that you just need to compile:

/*

* Copyright (c) 2020, KUNBUS GmbH

*

* Permission is hereby granted, free of charge, to any person obtaining a

* copy of this software and associated documentation files (the “Software”),

* to deal in the Software without restriction, including without limitation

* the rights to use, copy, modify, merge, publish, distribute, sublicense,

* and/or sell copies of the Software, and to permit persons to whom the

* Software is furnished to do so.

*

* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL

* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR

* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,

* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR

* OTHER DEALINGS IN THE SOFTWARE.

*/

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <linux/serial.h>

#include <sys/ioctl.h>

#define RCV_LEN 3

int main(int argc, char **argv)

{

struct serial_rs485 rs485conf;

int fd, ret;

char buf[RCV_LEN];

if (argc != 2) {

printf(“Usage: %s <device>\n”, argv[0]);

return 0;

}

fd = open(argv[1], O_RDWR);

if (fd < 0) {

printf(“Cannot open: %s\n”, strerror(errno));

return errno;

}

ret = ioctl(fd, TIOCGRS485, &rs485conf);

if (ret < 0) {

printf(“Cannot get rs485 config: %s\n”, strerror(errno));

return errno;

}

rs485conf.flags ^= SER_RS485_TERMINATE_BUS;

ret = ioctl(fd, TIOCSRS485, &rs485conf);

if (ret < 0) {

printf(“Cannot set rs485 config: %s\n”, strerror(errno));

return errno;

}

ret = write(fd, “abc”, 3);

ret |= read(fd, buf, RCV_LEN);

if (ret < 0) {

printf(“send or receive error: %s\n”, strerror(errno));

return errno;

}

ret = close(fd);

if (ret < 0) {

printf(“Cannot close: %s\n”, strerror(errno));

return errno;

}

}

By default, after booting “/dev/ttyAMA0” is used as the console terminal with the following configurations:

pi@RevPi0000:~ $ sudo stty -F /dev/ttyAMA0

speed 115200 baud; line = 0;

lnext = <undef>; min = 1; time = 0;

-brkint -icrnl ixoff -imaxbel iutf8

-icanon -iexten -echo