I'm trying to use a Beaglebone Black running Angstrom (3.8 kernel) to communicate with devices on a half-duplex RS-485 network at 9600-N-8-1.
I'm trying to use an RS-485 Breakout board similar to this one: https://www.sparkfun.com/products/10124, except the chip is a MAX3485 http://www.maximintegrated.com/datasheet/index.mvp/id/1079. I bought the board pre-assembled with pins and a terminal strip. A friend of mine tested it with an oscilloscope and declared that the RS-485 board does work. The board has five pins that connect to the BBB. 3-5V (Power), RX-I, TX-O, RTS, and GND.
I've disabled HDMI support on the BBB so that the UART4_RTSn
and UART4_CTSn
pins will be available.
mkdir /mnt/boot
mount /dev/mmcblk0p1 /mnt/boot
nano /mnt/boot/uEnv.txt
#change contents of uEnv.txt to the following:
optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
Then I've found an overlay to enable UART-4 with RTS/CTS control:
/*
* Modified version of /lib/firmware/BB-UART4-00A0.dtbo to add RTS so we can reset Arduinos
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
part-number = "BB-UART4-RTS";
version = "00A0";
exclusive-use = "P9.13", "P9.11", "P9.15", "P8.33", "P8.35", "uart4";
fragment@0 {
target = <0xdeadbeef>;
__overlay__ {
pinmux_bb_uart4_pins {
pinctrl-single,pins = <
0x070 0x26 /* P9_11 = UART4_RXD = GPIO0_30, MODE6 */
0x074 0x06 /* P9_13 = UART4_TXD = GPIO0_31, MODE6 */
/* need to enable both RTS and CTS, if we only turn on RTS then driver gets confused */
0x0D0 0x26 /* P8_35 = UART4_CTSN = lcd_data12, MODE6 */
0x0D4 0x06 /* P8_33 = UART4_RTSN = lcd_data13, MODE6 */
/* 0x040 0x0F /* P9_15 = GPIO1_16 = GPIO48, MODE7 failed attempt to put DTR on gpio */
>;
linux,phandle = <0x1>;
phandle = <0x1>;
};
};
};
fragment@1 {
target = <0xdeadbeef>;
__overlay__ {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <0x1>;
};
};
__symbols__ {
bb_uart4_pins = "/fragment@0/__overlay__/pinmux_bb_uart4_pins";
};
__fixups__ {
am33xx_pinmux = "/fragment@0:target:0";
uart5 = "/fragment@1:target:0"; /* Not a mistake: UART4 is named uart5 */
};
__local_fixups__ {
fixup = "/fragment@1/__overlay__:pinctrl-0:0";
};
};
Compiled and Enabled the overlay:
cd /lib/firmware
dtc -O dtb -o BB-UART4-RTS-00A0.dtbo -b 0 -@ BB-UART4-RTS-00A0.dts
echo BB-UART4-RTS:00A0 > /sys/devices/bone_capemgr.*/slots
Hooked up the 485 board to the BB like this
3-5V to P9_05 (VDD_5V)
RX-I to P9_13 (UART4_TXD)
TX-O to P9_11 (UART4_RXD)
RTS to P8_33 (UART4_RTSn)
GND to P9_01 (DGND)
In python I'm trying to use the serial port like this:
import serial
ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
ser.write(list_of_byte_dat)
I know the program works because when I use a USB to RS-485 converter on /dev/ttyUSB0
and set rtscts=False
the communication works in both directions just fine. But I can't get communication to work correctly using the RS-485 board.
I have two issues with the RS-485 board, both deal with RTS.
The RTS on the board works backwards from the way I expect it to. When I apply voltage on the RTS pin of the rs485 board the RTS led on the board goes off and the board will not transmit. When I remove voltage from the RTS pin the RTS led turns on and the board will transmit. How do I reverse the polarity of the UART_RTSn pin on the BBB?
Temporary solution: I've made a small bone script program that uses UART4_RTSn pin as input. It turns on a different GPIO when the UART4_RTSn pin is off and turns off that same GPIO pin when the UART4_RTSn pin is on. Then hooked up the RTS pin on the rs485 board to the GPIO pin instead of the UART4_RTSn pin.
This seems to be a poor solution, but it does make the RTS on the RS485 board come on at the correct time when echoing to the
/dev/ttyO4
from the command line.How can I change the polarity of the
UART4_RTSn
pin either by adjusting the hardware configuration or by changing the configuration in pyserial?This brings me to the second issue
As I stated in problem 1 the
UART4_RTSn
pin will work automatically (but backwards) for me when echoing a value to the tty port like this:echo -en '\x02\xFD\xCD......' > /dev/ttyO4
This will make the
UART4_RTSn
led blink while the data is being transmitted. If I have it setup without the bonescript mentioned above, then it will be on normally and blink off while transmitting. If I use my bonescript hack then it will be off normally and blink on while transmitting (which is what I want). However this only works when using echo from the command line. When I use python and setup the serial port theUART4_RTSn
pin becomes inactive. It will not blink while transmitting. As soon as I make the statement in python:ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
The
UART4_RTSn
pin shuts off and stays off. It does not blink when sending information usingser.write(stuff)
. As a result the rs485 board is not enabled for transmission. How do I get theUART4_RTSn
pin to work automatically in pyserial? I've tried settingrtscts=False
and it did not work.I am able to use
ser.setRTS(True)
orser.setRTS(False)
to manually toggle the pin value so I know I'm using the correct pin and that it is being recognized. But I don't want to toggle the UART4_RTSn pin directly. I want it to work automatically when the serial port is transmitting data and it does when using echo, but not in Python.
Any help would be greatly appreciated.