簡體   English   中英

帶有自動RTS的Python PySerial通過使用Beaglebone Black Angstrom的半雙工RS-485分線板

[英]Python PySerial with Auto RTS through Half-Duplex RS-485 breakout board using Beaglebone Black Angstrom

我正在嘗試使用運行Angstrom(3.8內核)的Beaglebone Black與9600-N-8-1的半雙工RS-485網絡上的設備進行通信。

我正在嘗試使用與此類似的RS-485分線板: https ://www.sparkfun.com/products/10124,除了芯片是MAX3485 http://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轉RS-485轉換器並設置rtscts=False ,通信在兩個方向都可以正常工作。 但是我無法使用RS-485板正常工作。

我有兩個問題與RS-485板,都處理RTS。

  1. 電路板上的RTS從我期望的方式向后工作。 當我在rs485板的RTS引腳上施加電壓時,電路板上的RTS指示燈熄滅,電路板不會發送。 當我從RTS引腳移除電壓時,RTS LED導通,電路板將發送。 如何反轉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回顯到/dev/ttyO4的正確時間出現。

    如何通過調整硬件配置或更改pyserial中的配置來更改UART4_RTSn引腳的極性?

    這讓我想到了第二個問題

  2. 正如我在問題1中所述,當我向tty端口回顯一個值時, UART4_RTSn引腳將自動(但向后)工作,如下所示:

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

    這將使UART4_RTSn在數據傳輸過程中閃爍。 如果我沒有上面提到的bonescript進行設置,那么它將正常啟動並在傳輸時閃爍。 如果我使用我的bonescript hack那么它會正常關閉並在傳輸時閃爍(這就是我想要的)。 但是,這僅在從命令行使用echo時才有效。 當我使用python並設置串口時, UART4_RTSn引腳變為無效。 傳輸時不會閃爍。 一旦我在python中發表聲明:

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

    UART4_RTSn引腳關閉並保持關閉狀態。 使用ser.write(stuff)發送信息時不會閃爍。 因此,rs485板無法進行傳輸。 如何讓UART4_RTSn引腳在pyserial中自動工作? 我已經嘗試設置rtscts=False ,但它不起作用。

    我能夠使用ser.setRTS(True)ser.setRTS(False)來手動切換引腳值,因此我知道我正在使用正確的引腳並且它正在被識別。 但我不想直接切換UART4_RTSn引腳。 我希望它在串口傳輸數據時自動工作,而在使用echo時則自動工作,但在Python中則不行。

任何幫助將不勝感激。

RTS通常是一個低電平有效信號,我懷疑你看到數據與echo傳輸的原因是它沒有使用RTS / CTS(保持高電平),因此只能傳輸數據。

根據http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=29408上的帖子

如果啟用硬件流控制(“man termios”中的CRTSCTS,或“stty crtscts -F / dev / ttyAMA0”或pySerial rtscts = True),則僅在CTS置位時才會發送。 除非內核輸入緩沖區已滿,否則將斷言RTS。 內核輸入緩沖區大約是一頁或4KB,因此在RTS實際更改之前,您的應用程序必須遠遠落后於它的讀取。

因此,檢查CTS是否在電路板外部斷言(拉到地)。 但是我不認為這會讓你對你需要的RTS有正確的控制權。

因此,對於您的應用程序,您應該禁用硬件流控制( rtscts=False )並在寫入之前使用setRTS(1)手動控制RTS,然后再使用setRTS(0)

如果您仍未看到數據通過設備,請嘗試更換A和B線 - A / B標簽(令人沮喪地)在RS485設備上不一致。 如果可能,最好在您自己的應用程序中使用D + / D-標記。

使用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 = ...;
  1. 你可以使用pnp晶體管/ p溝道mosfet /邏輯門不 - 像7404這樣的逆變器

  2. 也許你必須在寫操作ser.write(....)ser.flush()之后刷寫寫緩沖區

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM