Shop OBEX P1 Docs P2 Docs Learn Events
RS485 trancseiver — Parallax Forums

RS485 trancseiver

geokonstgeokonst Posts: 48
edited 2008-09-26 23:22 in Propeller 1
Hello everybody!

I run into another problem trying to build my 485 network. What seems to be the problem is that the driver/receiver enable switch needs an unreasonable amount of delay. That is; in order to switch between two modes a 485 half duplex transceiver has two pins (one is NOTed) which are usually short circuited in order to control the chip using one pin.

datasheet:
www.datasheetcatalog.org/datasheet/maxim/MAX1487-MAX491.pdf

This is the test code I am using
CON

  _clkmode = xtal1 + pll16x                             
  _xinfreq = 5_000_000                                  

VAR
   byte aasf
OBJ
    serial : "FullDuplexSerial"             
PUB Main                                                

Serial.Start(24,25,%0000, 9600)    
dira~~
          
 repeat      
       waitcnt(100_000 + cnt)      
       outa:=0         
       aasf:= serial.rx  
       waitcnt(100_000 + cnt)         
       outa:=1   
       serial.tx  (aasf)



If I reduce any of the delays I start getting wrong data and if I further reduce it it just stops working.
I have tried 3 different brands of the same transceiver and using two propeller pins to switch the two enablers separately. Also terminating the other end.

I doubt that it's a propeller thing. I suspect that it's a 3.3V to 5V interfacing problem (They are none interfacing electronics) but how come it work perfectly with the delays then?
Any ideas? All are welcome since I'm stuck for two days trying to solve this.

Thanks for your time and patience

Comments

  • AribaAriba Posts: 2,687
    edited 2008-09-24 22:17
    When you use the tx method to send a byte, and there is enough space in the tx-buffer, then the byte is only written to the buffer, and the method returns immediatly. Then another cog sends the bits serially out (the Assembly cog of FDSerial), while the Spin cog already continous his code.
    With the first delay you wait until the data is sent, before you switch the Enable Pin.
    I think the second delay is not necessary, because the rx method returns when the byte is fully received.

    To do it right, you can do the Enable switching in the Assembly cog. Or you need a method in FDSerial, to wait until the tx buffer is empty.
    Or you can use the Simple_Serial object, this sends the bits with the Spin cog.

    Andy
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 02:06
    Thanks a lot Ariba. I really appreciate your help! You are probably right! this could be the problem. But I don't know how to fix it. Even if I manage to have the assembly code raise the switching pin when receiving won't I still have problems since I have synchronous R/T trying to feed to a single twisted pair?

    Also I have tried making the simple_serial work, but it just wont (without using any transceiver apart from the built in on my propstick usb).

    CON
      _clkmode = xtal1 + pll16x                             
      _xinfreq = 5_000_000                                  
    
    VAR
       byte aasf
    OBJ
        serial : "simple_serial"             
    PUB Main                                                
    
    Serial.init(31,30, 9600)    
    
    
    repeat
           aasf:= serial.rx
           serial.tx  (aasf)
    


    Why won't this code work? I get the first byte right and the rest wrong no matter what the time interval is. In particular for sending a series of $1A I got:
    1A BB 1A 9B 5B BA FF 1B

    As always any help is very much appreciated as I am really stuck here. Please? Anyone?
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 04:21
    Apparently my problems is the same as this :
    http://forums.parallax.com/forums/default.aspx?f=25&m=288794

    although it seems I downloaded a different version of simple_serial
    Any clues?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-26 04:45
    Assuming you have the current version (1.2) of Simple_Serial, your test program should echo exactly what it receives.
    What do you have your Propeller connected to? What software is running on the other end? How's it configured?
    The software (Simple_Serial) works for other people, so what's different about your situation?
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 05:41
    Hello Mike.
    I am using a propstick usb with just power going in. I am using pins 30 and 31 with simple_serial so I can use the build in usb interface. I am using version 1.2
    The other end is either hyperterminal or more often a program called com port toolkit. 8bit no flow control - 9600.

    And I experience the same problem as the one described on the other thread. I wish I could find what I'm doing different-wrong :/
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-26 06:44
    Well, it's broken for me as well. This is interesting. I don't have time anymore tonight to look into it, but I'm using a Hitt Consulting's Prop Dongle for testing. I've compiled your sample program from 8:06pm along with Simple_Serial 1.2 and downloaded it to the Dongle. I'm using the Propeller Serial Terminal program and I'm getting the same results as you regardless of whether I add additional delays, change the variable to a LONG, add additional output statements. Fortunately the transmit side works fine. I can send the decimal equivalent of the received value to the Propeller Serial Terminal and it matches the displayed character, so the problem is on the receive side. I can't see anything obvious with the Simple_Serial receive method, so I'm befuddled for now.
  • AribaAriba Posts: 2,687
    edited 2008-09-26 07:32
    The solution depends a lot of your concrete implementation of the Network.
    For a half duplex RS-485 Network, you need some kind of protocol. With a Master - Slave protocol all Slaves disables the TX-driver and wait for a frame from the Master. Then the addressed Slave enables his TX-driver, sends a whole frame and then disables the driver again.
    With more then 1 Master you also need Collision detection, which makes it more complicated.

    If you have a free cog, why not use the FullDuplex-Driver, and a short delay after sending the last byte of the frame, before disabling the TX-driver? You can calculate the exact time for the whole frame, from the frame size and baudrate. Store the cnt value when you send the first byte, and wait for cnt - starttime > frametime after the last sent byte, then switch the TX-driver off.

    The FullDuplexSerial is much more reliable than Simple_Serial. And for baudrates > 19200 you anyway need Assembly.

    Andy
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2008-09-26 08:12
    Full duplex would eliminate much of the need for sophisticated transceiver software. As it stands, you likely have to impliment a master-slave relationship in order to avoid data collisions. On the other hand, with the Prop using full duplex, one cog could be independently sending at the same time another cog is receiving. I'd prefer to take advantage of the Prop's ability to do so.

    Of course, this set up requires two twisted pairs and a transmitter chip and receiver chip at each end. Since I can not locate single transmitter and receiver chips, I have ended up using two transceivers at each end. That bit of waste is annoying, but I haven't found a way around it.

    You really don't absolutely need twisted pairs. I find that 4-wire telephone cord is quite good in most cases. I have tested up to 100' of wire with good results, no error over many days of operation. I use RJ-xx connectors for modularity and easy set up.

    Full duplex is generally used between two devices on one cable.

    If you want to have a lot of devices on the same wire, you may be better off staying with the half duplex and developing communications protocols. CANbus already has all the communications problems resolved in firmware and could include a Propeller.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    It's sunny and warm here. It is always sunny and warm here.... (unless a typhoon blows through).

    Tropically, G. Herzog [noparse][[/noparse] 黃鶴 ] in Taiwan
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 12:13
    Dear all thank you so much about your replies.
    to sum up:
    -I am trying to make a net of 50 sensors so importing a delay of 20ms on each one would be affecting the performance quite a lot.

    -Simple serial (half duplex) should work as I probably don't need too high baud rates. Downside: the code doesn't seem to work.

    -I believe I will really need twisted pairs since the bus will be quite long. I will probably use cat 5 cable and probably use two pairs for power. So I'm left with two pairs of which one I was planning to use for data and the other unused.

    -Using two twisted pairs - full duplex would solve a great deal of my problems, but I'd rather do half duplex over one pair.

    Also if someone figures out what's wrong with simple_serial could they please please let me know? Thank you everybody
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 15:57
    By the way running the initialization routine in every RX/TX cycle seems to solve the problem.
  • OwenSOwenS Posts: 173
    edited 2008-09-26 20:11
    Instead of SimpleSerial, perhaps you could try extracting the serial driver from the BS2 object?
  • AribaAriba Posts: 2,687
    edited 2008-09-26 20:38
    geokonst said...
    I am trying to make a net of 50 sensors so importing a delay of 20ms on each one would be affecting the performance quite a lot.

    This is not an additional delay on the bus, it is a delay to 'synchronize' the Spin cog to the FDSerial cog. Because they run in parallel, the Spin cog has to wait until the bytes are sent out, before disabling the Output. I hope the attached diagram makes it clear. It shows the situation when you send 8 bytes. Writing theme in the buffer is fast, but sending out the single bits out takes much longer. The Spin cog have to switch the Enable signal, when the bytes are sent. Instead of just waiting you can also do some useful in this time.

    I had a look at Simple_Serial and found the bug. It is in the RX method, the receiving byte is not cleard before receiving and the bits are ORed !!
    Corrected version:
    PUB rx: rxByte | t, b
    {{ Receive a byte; blocks caller until byte received. }}
    
      if rxOkay
        dira[noparse][[/noparse]sin]~                                          ' make rx pin an input
        b~                                                  '<-- ADD THIS
        waitpeq(inverted & |< sin, |< sin, 0)               ' wait for start bit
        t := cnt + bitTime >> 1                             ' sync + 1/2 bit
        repeat 8
          waitcnt(t += bitTime)                             ' wait for middle of bit
          b := ina[noparse][[/noparse]sin] << 7 | b >> 1                       ' sample bit 
        waitcnt(t + bitTime)                                ' allow for stop bit 
    
        return (b ^ inverted) & $FF                         ' adjust for mode and strip off high bits
    
    



    Andy
    507 x 114 - 2K
  • geokonstgeokonst Posts: 48
    edited 2008-09-26 23:22
    You are right ariba. But I think I going to go with a full duplex 485 instead like Kramer suggested. Thanks for spending time finding the problem with Simple serial, I am sure I'm going to need that in the future.
Sign In or Register to comment.