This post is a part of a series about the TouchBerry ModbusRTU autoflow issue and how have I resolved it. Other posts of the series can be found under the touchberry tag. Note that newer posts might contain more recent information.

With the access to the TouchBerry 10" model including RS485, I set to start controlling some ModbusRTU devices with it. It has the M8, 3-pin connector. The center pin is connected to supply voltage ground, so I assumed the remaining two are A and B for RS485. As it turned out, there is absolutely no documentation on the topic publicly available.

RS485 pinout

Fortunately, I was able to receive the email from the support quite promptly. The email confirmed the pinout.

#M8 positionRS485
1rightB-
2leftA+
3topGND

But with the GND sorted out, getting to A and B is not a problem. If not working, just swap them and try again. With everything else correct, this is sufficient procedure.

The UPS shield pinout

Subsequently, the email contained information about the UPS shield pinout which hosts the RS-485 chip. The chip is Unisonic Technologies UTRS485G, but I have never heard about them before. The UPS shield also hosts uninterrupted power supply electronics (hence the name) and the timekeeping chip DS3231 for the RTC capabilities.

The shield makes use of the full 40 pin header for the Raspberry Pi 4 being the core of the TouchBerry 10", the details from the email are following:

FnDescr.##Descr.Fn
NC12Vin
SDAGPIO234Vin
SCLGPIO356GND
NC78GPIO14TXD
NC910GPIO15RXD
REGPIO171112NC
DEGPIO271314GND
NC1516GPIO23UPS IN
NC1718GPIO24UPS OUT
NC1920GND
NC2122NC
NC2324NC
GND2526NC
NC2728NC
NC2930GND
NC3132NC
NC3334GND
NC3536NC
NC3738NC
GND3940NC

This was quite helpful, as the chip responsible for the RS485 communication has to know which direction the data is flowing. It is an advanced feature to design the overall system such that the user has this responsibility abstracted away - so called autoflow or automatic flow control.

Using RS485 interface on TouchBerry 10

The importance for the autoflow can be apparent from the python script provided as the third part of the email from the IndustrialShields support:

#!/usr/bin/env python3

# IMPORTANT: remember to add "enable_uart=1" line to /boot/config.txt

from gpiozero import OutputDevice
from time import sleep
from serial import Serial

# RO  <-> GPIO15/RXD
# RE  <-> GPIO17
# DE  <-> GPIO27
# DI  <-> GPIO14/TXD
#
# VCC <-> 3.3V
# B   <-> RS-485 B
# A   <-> RS-485 A
# GND <-> GND

# enable reception mode
re = OutputDevice(17)
de = OutputDevice(27)

de.off()
re.off()

with Serial('/dev/ttyS0', 19200) as s:
  while True:
    # waits for a single character
    rx = s.read(1)

    # print the received character
    print("RX: {0}".format(rx))

    # wait some time before echoing
    sleep(0.1)

    # enable transmission mode
    de.on()
    re.on()

    # echo the received character
    s.write(rx)
    s.flush()

    # disable transmission mode
    de.off()
    re.off()

To send the data over the RS485 interface, the RE and DE pins of the chip has to be pulled HIGH, the data should be transmitted, and then both RE and DE pins should be pulled LOW immediately to receive the response. This is very unfortunate as most Modbus implementations assume the autoflow, as is also the case when using mbpoll.

Missing autoflow?

It is basically a lot of hassle to not have the autoflow functionality rendering most standard Modbus implementations unusable. I have searched quite hard for the way how to do this in some nice automated way on the RPi software on some application or kernel level, visiting search term results like alternative GPIO functions, dtoverlay, RTS0, uart-ctsrts and serial sniffers but could not find the solution yet. Some of the most promising are referenced below among other relevant links.

The GPIO17 has the alternative function of RTS0 at ALT3, which is connected to the RE pin - this is hopefully done by design. There is however no such function available for the GPIO27 connected to the RE pin. In reality, both DE and RE should be tied together, controlled by the single RTS0 pin, that is in turn driven by GPIO14 being TXD0. I have no idea why the RE pin is separate. I have to hook it up to the oscilloscope to learn more. Before touching the soldering iron, I also have to wait for another support email response - maybe they provide some nice information. In the end, their RPi based PLC has /dev/ttySC0 and /dev/ttySC1 for both RS485 channels.

This is a 92th post of #100daystooffload.