Python PySerial使用Beaglebone Black Angstrom通过半双工RS-485转接板实现自动RTS

2024-05-13 13:34:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我试着用一个运行Angstrom(3.8内核)的Beaglebone Black与9600-N-8-1的半双工RS-485网络上的设备通信。

我正在尝试使用一个RS-485断接板类似于这个:https://www.sparkfun.com/products/10124,除了芯片是一个MAX3485http://www.maximintegrated.com/datasheet/index.mvp/id/1079。我买了预先组装好的电路板,上面有插脚和端子排。我的一个朋友用示波器对它进行了测试,并宣布RS-485板可以工作。电路板有五个插脚连接到BBB。3-5V(电源)、RX-I、TX-O、RTS和GND。

我已经禁用了BBB上的HDMI支持,以便UART4_RTSnUART4_CTSn管脚将可用。

    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 

然后,我找到了一个覆盖图来启用带有RTS/CTS控件的UART-4:

            /*
     * 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";
      };
    };

编译并启用覆盖:

    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

像这样把485板连接到BB上

    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)

在python中,我试图使用如下串行端口:

    import serial
    ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
    ser.write(list_of_byte_dat)

我知道这个程序可以工作,因为当我在/dev/ttyUSB0上使用USB-to-RS-485转换器并设置rtscts=False时,通信在两个方向都可以正常工作。但是我不能用RS-485板让通讯正常工作。

我有两个RS-485板的问题,都是关于RTS的。

  1. 板上的RTS的工作方式与我预期的相反。当我在rs485板的RTS引脚上施加电压时,板上的RTS led熄灭,板不会传输。当我从RTS引脚上卸下电压时,RTS发光二极管亮起,电路板将进行传输。如何反转BBB上UART_RTSn引脚的极性?

    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.

    这似乎是一个糟糕的解决方案,但它确实使RS485板上的RTS在从命令行回显到/dev/ttyO4时在正确的时间启动。

    如何通过调整硬件配置或更改pyserial中的配置来更改UART4_RTSn管脚的极性?

    这就引出了第二期

  2. 如我在问题1中所述,当向tty端口回显一个值时,UART4_RTSn管脚将自动(但向后)工作,如下所示:

    echo -en '\x02\xFD\xCD......' > /dev/ttyO4
    

    这将使数据传输时UART4_RTSnled闪烁。如果我没有上面提到的bonescript设置它,那么它将正常打开并在传输时闪烁。如果我使用我的bonescript黑客,那么它将是正常关闭和闪烁,而传输(这是我想要的)。但是,这仅在使用命令行中的echo时有效。当我使用python并设置串行端口时,UART4_RTSn管脚将变为非活动状态。传输时不会闪烁。我一用python声明:

    ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
    

    销关闭并保持关闭。当使用ser.write(stuff)发送信息时,它不会闪烁。因此,没有启用rs485板进行传输。如何使UART4_RTSnpin在pyserial中自动工作?我试过设置rtscts=False,但没有成功。

    我可以使用ser.setRTS(True)ser.setRTS(False)手动切换pin值,这样我就知道我使用的是正确的pin,并且它被识别。但我不想直接切换UART4_RTSn引脚。我希望它在串行端口传输数据时自动工作,在使用echo时自动工作,但在Python中不这样做。

任何帮助都将不胜感激。


Tags: ofthetodevonpinser管脚
3条回答

使用ioctl更改逻辑级别。。。

98         struct serial_rs485 rs485conf;
 99 
100         /* Enable RS485 mode: */
101         rs485conf.flags |= SER_RS485_ENABLED;
102 
103         /* Set logical level for RTS pin equal to 1 when sending: */
104         rs485conf.flags |= SER_RS485_RTS_ON_SEND;
105         /* or, set logical level for RTS pin equal to 0 when sending: */
106         rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
107 
108         /* Set logical level for RTS pin equal to 1 after sending: */
109         rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
110         /* or, set logical level for RTS pin equal to 0 after sending: */
111         rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
112 
113         /* Set rts delay before send, if needed: */
114         rs485conf.delay_rts_before_send = ...;

RTS通常是一个活动的低信号,我怀疑您看到用echo传输数据的原因是它没有使用RTS/CTS(让它保持高电平),因此只有能够传输数据。

根据http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=29408上的一篇文章

If you enable hardware flow control (CRTSCTS in "man termios", or "stty crtscts -F /dev/ttyAMA0", or pySerial rtscts=True), then sending will take place only when CTS is asserted. RTS will be asserted except when the kernel input buffer is full. The kernel input buffer is about one page or 4KB, so your application has to get well behind with its reads before RTS actually changes.

因此,检查CTS是否被断言(拉到地面)在您的董事会之外。但是我不认为这会给你对RTS的正确控制,你需要的。

因此,对于您的应用程序,您应该禁用硬件流控制(rtscts=False),并在写入之前使用setRTS(1)手动控制RTS,然后使用setRTS(0)

如果您仍然没有看到数据通过设备,请尝试交换A&B电线-A/B标签在RS485设备上不一致(令人沮丧)。如果可能的话,最好在您自己的应用程序中使用D+/D-标记。

  1. 您可以使用pnp晶体管/p通道mosfet/逻辑门,而不是像7404那样的逆变器

  2. 也许在写操作之后必须刷新写缓冲区 序列写入(…) ser.flush()

相关问题 更多 >