Shop OBEX P1 Docs P2 Docs Learn Events
Half Duplex Serial Communication: How to control DE-RE/ pins? — Parallax Forums

Half Duplex Serial Communication: How to control DE-RE/ pins?

LutzLutz Posts: 2
edited 2015-10-15 11:24 in Propeller 1
Dear All,

I have a project where two propeller chips communicate over a distance of 100 to 200 m at a speed of 9600 bit/s via RS-485. A few years ago I have used a MAX3488 at both ends, the FullDuplexSerial.spin object and 4-wire full duplex communication. This was working fine, but now I would like to change to a 2-wire half duplex communication in order to reduce the number of wires. Logically this should be no problem since one of the chips behaves as master which sends a request to the other chip which sends the answer back to the master. So there is no situation where the two chips try to send to the same time.

My problem is now that the half-duplex driver chip, a MAX3483, has additional input pins to switch the transmitter (DE) and the receiver (RE/) parts On or Off. In the frame of a trial I switched transmitter and receiver at both sides permanently on and it magically worked but just over a very short cable, not over 100 m. It appears that one can get the full range just if one makes sure that only one of the transmitters is switched on to the same time.

I think the best solution would be if the FullDuplexSerial object would take control of the DE-RE/ pins of the serial driver chip and pull them high as long as there is data in the Tx buffer.

Unfortunately, my programming skills are limited to Spin language and this part of the object is implemented in Assembly language. I tried already to put some wait commands in the Spin section but had only limited success finding the right values.

I am rather sure that someone did face this problem before and might give advice.

Many thanks in advance.

Comments

  • kwinnkwinn Posts: 8,697
    You could add a command to your spin program to control a prop pin that switches the RS485 driver from input to output before sending data and back to input when finished.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-10-15 15:48
    Which serial object are you using?

    I've seen methods which check tx buffers in serial objects. Depending on the object you're using, it may be easy to add a similar method.

    Here's a method I added to a serial object I use. I'm pretty sure I copied this from one of Tracy Allen's objects.
    PUB TxHowFull(port)    ' (DWD) added method
    '' returns number of chars in tx buffer
      return ((tx_head[port] - tx_tail[port]) + txsize[port]) // txsize[port]
    '   tx_head and tx_tail are values in the range 0=< ... < TX_BUFSIZE
    
    

    Here's applicable code to set the line to transmit mode, wait for the message to be sent and set the line back to receive.
      modbusStopWaitTime := MININUM_WAIT #> clkFreq / (modbusBaud / 30)
    
      outa[MODBUS_RT_PIN] := RS485_TRANSMIT ' set to one
    
      repeat currentMessageSize    
        serial.tx(MODBUS_PORT, byte[outputPtr++])
    
      repeat
        result := serial.TxHowFull(MODBUS_PORT)
      while result
    
      waitcnt(modbusStopWaitTime + cnt)
      serial.rxFlush(MODBUS_PORT)
       
      outa[MODBUS_RT_PIN] := RS485_RECEIVE ' set to zero
    
    

    "MININUM_WAIT" was set to 381
  • Mike GreenMike Green Posts: 23,101
    edited 2015-10-15 16:11
    Use the ObEx "Simple Serial" object. It's written completely in Spin and works fine up to 19200 Baud. It doesn't do flow control as written, but it would be trivial to add that. It supplies an "rx" method and both a "tx" and "str" method (which uses "tx"). There's no buffering, but, with a half duplex scheme in use, you want the flow/direction control and buffering on a complete message level.

    Transmit a packet:
    <turn on DE>
    <transmit any characters needed>
    <turn off DE>

    Wait for and receive a packet:
    <turn on RE/>
    <wait a little for things to stabilize>
    <do the reception of a complete message>
    <turn off RE/>

    If you want to do messaging in parallel with your other operations, use a separate cog to do all the message I/O and communicate via a shared buffer (all in Spin).
  • If you want an object dedicated to the purpose, there is one by JonnyMac, jm_hd485.spin

  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-10-16 18:16
    You can also use a standard object (fullDuplexSerial variants) by setting the mode to %0100, which makes it open baud-mode and no-echo. On the hardware Prop side tie together the RO and DI data lines to one Prop pin and add a pullup resistor, and open the port with both rx and tx pointing to that one pin. Also tie together the DE and RE\ enable lines to a second Prop pin.

    The Spin code will take something like the following form. Normally the driver chip is in receive mode, and the rest of the program on both sides will know when it is time to transmit with out mutually clobbering. This code is written for the 4-port object, so it has an RS485_PORT number assigned.
    PRI SendRS485zString(pointer)
    ' sends a zString located at pointer to RS485
      MakeRS485output
      uarts.str(RS485_PORT,pointer)
      uarts.TxFlush(RS485_PORT)
      pause(8)
      MakeRS485input
    
    PRI MakeRS485input
      outa[RS485_DIR] := 0
    
    PRI MakeRS485output
      outa[RS485_DIR] := 1
    
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-10-18 19:08
    Edit: NOECHO may be needed because tx is tied directly to rx and so everything sent is immediately received. NOECHO keeps the rx buffer cleared.
    Also true for other single-wire protocols that use open baud-mode with pullup for half dulpex on one wire. A note on that, I've changed all my drivers so that NOECHO uses rxtime rather than plain rx. Plain rx is a possible lockup point if/when a remote device becomes inactivated.

  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-10-18 07:33
    Edit: The system at the other end may also send back an echo.

    The OP hasn't checked back in, but with a Prop under control at both ends, you can make it behave however you want.

  • Lutz wrote: »
    I think the best solution would be if the FullDuplexSerial object would take control of the DE-RE/ pins of the serial driver chip and pull them high as long as there is data in the Tx buffer.

    Use a pull down resistor ( ~100k ) to ground on the DE-RE/ line. That way the device will always default to receive mode when it's not being powered.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-10-18 18:54
    Use a pull down resistor ( ~100k ) to ground on the DE-RE/ line. That way the device will always default to receive mode when it's not being powered.

    This seems like a reasonable suggestion. Not that I don't trust Sandy's word on this but is this a common standard practice?

    I'm helping with a project which uses a RS485 chip. Should I suggest adding a pull-down on this line? The RS485 could be powered on for a few seconds before the firmware holds the line low. Adding a pull-down resistor just seems like a good idea to prevent the device from causing glitches on the RS485 line.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-10-18 19:20
    Duane, I'd go for the pull-down too. Especially if you are tying into an existing network where a glitch could have consequences. Are you just using two prop pins with the data and enable lines joined, or are you separating it out into 4 prop pins?

  • Are you just using two prop pins with the data and enable lines joined, or are you separating it out into 4 prop pins?

    IIRC, there are three Prop pins. The enable pins are tied together but the tx and rx are separate. I suppose the tx and rx could be joined but I think keeping them separate allows more options with serial drivers.

    I'll make sure and the 100k pull-down resistor. It's possible the device could be attached to an active network.

  • I am grateful for the many suggestions. I have tried a little from everything. Finally I went to Jonny Mac’s object recommended from Tracy Allen, which works very well. But also the solution using the FullDuplexSerial.spin object and adding the handling of the DE-RE/ pin “manually” with some wait commands was also functioning at the end.

    I found out that I have to add a pullup resistor on the A pin and a pull down resistor on the B pin of one of the driver chips. This is because if the tx drivers at both ends are switched off the bus is somehow instable. This leads to a fludding of the receiver buffer with rubbish characters and prevents Jonny Mac’s object from going into transmitting mode.

    This seems to be an issue of the driver chip I am using, the MAX3483. There are others which have a “fail-safe” feature which should avoid the additional resistors.

    Lutz
Sign In or Register to comment.