Shop OBEX P1 Docs P2 Docs Learn Events
Serial communication receive with timeout - howto? — Parallax Forums

Serial communication receive with timeout - howto?

ted1ted1 Posts: 3
edited 2010-06-11 11:51 in Propeller 1
Hi!

I am trying to modify Simple_Serial.spin to allow for timeout-handling (.Rx-call should timeout after 0.5 second of no data)

So I basically need to replace waitpeq() with my own routine for the waiting for a start bit

I was thinking about something like the code shown at the bottom (a modification of the Rx routine)
The problem is that the reception is unstable. Some characters are OK, some are garbage.
So I suspect that the repeat-loop for the start bit is too slow when the baudrate is 19200.
At 9600 baudrate it goes much better.

I was thinking about replacing the repeat-loop with assembly, but don't see how.
Do anyone see something wrong with my code?
Has someone maybe made serial I/O with timeout already?
Thank's!

PUB rxTimeout: rxByte | t
  if rxOkay
    dira[noparse][[/noparse]sin]~                                          ' make rx pin an input

    t := cnt + (clkfreq / 2)                    ' timeout is 0.5 sec
    repeat until (ina[noparse][[/noparse]sin] == 0) OR (cnt > t)   ' repeat until start bit or timeout 

    t := cnt + bitTime >> 1                             ' sync + 1/2 bit
    repeat 8
      waitcnt(t += bitTime)                             ' wait for middle of bit
      rxByte := ina[noparse][[/noparse]sin] << 7 | rxByte >> 1             ' sample bit 
    waitcnt(t + bitTime)                                ' allow for stop bit 
    rxByte := (rxByte ^ inverted) & $FF                 ' adjust for mode and strip off high bits

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-09 16:01
    Simple_Serial is just too slow to add things like timeout handling above 9600 Baud. If you want timeout handling, you need to switch to FullDuplexSerial or one of the other assembler-based serial drivers in the Object Exchange. FullDuplexSerial has an "rxtime(timeOut)" routine that allows for a timeout in milliseconds.
  • AribaAriba Posts: 2,690
    edited 2010-06-09 16:24
    Here is a code to try.

    1. Timeout detection handels also cnt overflows (wrap arounds).
    2. Does not read the bits in if timout
    3. Tries to compensate the delay from the timout detection with reducing the half bit time delay at begin to 1/4 bittime.
    You need to play with this value to hit the right window inside the bit (1/3 or 1/8 or so).

    This is not tested!
    PUB rxTimeout: rxByte | t, d
      if rxOkay
        dira[noparse][[/noparse]sin]~                                          ' make rx pin an input
    
        d := clkfreq / 2                            ' timeout is 0.5 sec
        t := cnt
        repeat until ina[noparse][[/noparse]sin] == 0 OR cnt-t > d     ' repeat until start bit or timeout 
    
        if ina[noparse][[/noparse]sin] == 1                                    ' abort if timout
          return -1
    
        t := cnt + bitTime / 4                              ' sync + 1/4 bit
        repeat 8
          waitcnt(t += bitTime)                             ' wait for middle of bit
          rxByte := ina[noparse][[/noparse]sin] << 7 | rxByte >> 1             ' sample bit 
        waitcnt(t + bitTime)                                ' allow for stop bit 
        rxByte := (rxByte ^ inverted) & $FF                 ' adjust for mode and strip off high bits
    
    



    Andy
  • ted1ted1 Posts: 3
    edited 2010-06-09 20:47
    Thank's a lot!

    FullDuplexSerial really was much better. It works nicely now at 19200 bps.

    Although a little difficult for our RS485 half duplex (2 wire) connection (LTC1487 chip), where we use only one propeller-pin for both Rx and Tx.

    We had to specify an unused pin for the "unused" direction and reset the cog (call FullDuplexSerial.start) in order to switch traffic direction.

    Ariba, your sample code would probably work, but we feel more comfortable with highspeed assembly for this purpose.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-06-09 21:20
    Remember that you need a bit of delay when setting the TX/RX control line to transmit mode. To be safe give yourself at least 10 microseconds before attempting to transmit after you've taken this line high.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-09 22:29
    ted1,
    I've been modifying FullDuplexSerial to be able to handle half duplex stuff. Here's an untested version (I'll be debugging it next week) to think about. There's an extra mode bit (%10000). If that's set, the transmit side of things shuts off when its buffer goes from non-empty to empty. When the buffer goes from empty to non-empty, the transmitter gets turned on again and stays on as long as there's something in the buffer. You need to use mode %1000 also because the receiver side is still running and sees anything that's transmitted. In this version, the buffer size is also adjustable at compile-time.

    Typically, you'd put a string in the buffer and use "txflush" to wait until the buffer is empty and the last character is finished being sent (and the transmit side is turned off).
  • John AbshierJohn Abshier Posts: 1,116
    edited 2010-06-09 23:09
    http://obex.parallax.com/objects/512/ is a driver for Bioloid Dynabus servos. It works in half duplex at 1MB.

    John Abshier
  • AribaAriba Posts: 2,690
    edited 2010-06-10 00:36
    ted1 said...
    Thank's a lot!
    ...
    Ariba, your sample code would probably work, but we feel more comfortable with highspeed assembly for this purpose.

    No problem, I thought you have a reason to use SimpleSerial. An Assembly serial driver is always the way to go, if you have a free cog.

    Andy
  • ted1ted1 Posts: 3
    edited 2010-06-11 11:06
    Hi Mike!

    Your FullDuplexSerialMG.spin, line 120 does not compile. It complains about the reference to randomSeed.
    Is it ok to just remove this line?
    Is seems like some debug stuff.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-11 11:51
    randomSeed is a leftover from a previous version. I thought I had gotten all of them. Sorry. Yes, remove it.
Sign In or Register to comment.