NOECHO problem with fullduplexserial4port v1.01
dbpage
Posts: 217
I am converting multiple fullduplexserial drivers running in 4 cogs to fullduplexserial4port v1.01 (obex.parallax.com/object/248) running in 1 cog. Two channels require Tx/Rx to be on the same one pin to communicate with a Parallax Serial Controller (PSC) and a Digital Output Controller (DC or DC16), both running 2400 baud. I currently communicate with each using FullDuplexSerial_rr004 (obex.parallax.com/object/249) configured as shown below, and there are no Tx issues. With fullduplexserial4port, Tx is unreliable. I have isolated this issue to NOECHO. The behavior is identical on all 4 ports (0 to 3).
With fullduplexserial4port, if there is no cable or device connected to the output pin, Tx/Rx hangs on the Rx that follows Tx when NOECHO is set (see fullduplexserial4port code below). If there is a cable or device connected to the output pin, there is no issue. With NOECHO turned off, Rx receives all Tx characters reliably with or without a cable or device connected. There is no issue with fullduplexserial_rr004. This makes me think there is a timing issue in the fulduplexserial4port code somewhere. As you can see, the fullduplexserial and fullduplexserial4port Tx/Rx spin code are essentially identical, so, perhaps the problem is in PASM. Can you help me find the problem?
Original
New:
FullDuplexSerial_rr004:
fullDuplexSerial4port
With fullduplexserial4port, if there is no cable or device connected to the output pin, Tx/Rx hangs on the Rx that follows Tx when NOECHO is set (see fullduplexserial4port code below). If there is a cable or device connected to the output pin, there is no issue. With NOECHO turned off, Rx receives all Tx characters reliably with or without a cable or device connected. There is no issue with fullduplexserial_rr004. This makes me think there is a timing issue in the fulduplexserial4port code somewhere. As you can see, the fullduplexserial and fullduplexserial4port Tx/Rx spin code are essentially identical, so, perhaps the problem is in PASM. Can you help me find the problem?
Original
OBJ psc : "FullDuplexSerial_rr004" ' Communicate with Parallax Servo Controllers DC16 : "FullDuplexSerial_rr004" ' Communicate with Digital Output Controllers CON PSCcom = 15 ' Pin to transmit to PSC Parallax servo controller PSCmode = %1100 ' PSC Communication Mode: open-drain/source tx/ignore tx echo on rx PSCbaud = 2400 ' PSC Baud Rate DCcom = 14 ' Pin to transmit to DC16 digital controller DCmode = %1100 ' Digital Controller Communication Mode: open-drain/source tx/ignore tx echo on rx DCbaud = 2400 ' Digital Controller Baud Rate PUB i psc.start(PSCcom,PSCcom,PSCmode,PSCbaud) ' Start psc communication service (rxpin,txpin,mode,baudrate) DC16.start(DCcom,DCcom,DCmode,DCbaud) ' Start DC16 communication service (rxpin,txpin,mode,baudrate) ' Display PSC version number psc.str(string("!SCVER?",CR)) ' Send version command to PSCs ' rx routine goes here ' Display DC16 version number repeat i from 0 to 6 ' Send command to DC16 DC16.tx(DC16text[N]) ' rx routine goes here DAT DC16text byte "!DC16",3,"V",0,0 'Comment: 'mode bit 0 = invert rx 'mode bit 1 = invert tx 'mode bit 2 = open-drain/source tx 'mode bit 3 = ignore tx echo on rx 'mode bit 4 = invert cts 'mode bit 5 = invert rts
New:
CON PSCport = 2 ' PSC serial port number DCport = 3 ' Digital controller serial port number OBJ ser : "fullDuplexSerial4port" ' 4 channel serial communication PUB i ser.AddPort(PSCport,PSCcom,PSCcom,-1,-1,0,PSCmode,PSCbaud)' Initialize PSC serial communication port ser.AddPort(DCport,DCcom,DCcom-1,-1,0,DCmode,DCbaud)' Initialize DC serial communication port ' Display PSC version number ser.str(PSCport,string("!SCVER?",CR)) ' Send version command to PSCs ' rx routine goes here ' Display DCversion number repeat i from 0 to 6 ' Send command to DC16 DC16.tx(DC16text[N]) ' rx routine goes here
FullDuplexSerial_rr004:
PUB rx : rxbyte '' Receive byte (may wait for byte) '' returns $00..$FF repeat while (rxbyte := rxcheck) < 0 PUB tx(txbyte) '' Send byte (may wait for room in buffer) repeat until (tx_tail <> (tx_head + 1) & bufmsk) tx_buffer[tx_head] := txbyte tx_head := (tx_head + 1) & bufmsk if rxtx_mode & %1000 rx
fullDuplexSerial4port
CON NOECHO = %001000 PUB rx(port) : rxbyte '' Receive byte (may wait for byte) '' returns $00..$FF repeat while (rxbyte := rxcheck(port)) < 0 PUB tx(port,txbyte) '' Send byte (may wait for room in buffer) if port > 3 abort repeat until (tx_tail[port] <> (tx_head[port] + 1) // txsize[port]) byte[txbuff_ptr[port]+tx_head[port]] := txbyte tx_head[port] := (tx_head[port] + 1) // txsize[port] if rxtx_mode[port] & NOECHO rx(port)
Comments
One thing catches my attention, and thank you for the careful description. The fact that it happens only when the cable is detached might have something to do with the fact that the 4port code discards bytes that have a framing error, that is, those that lack a stop bit. The other program does not reject framing errors and can put out a stream of null bytes when the serial line stays in a BREAK state. A floating cable can be a great source of framing errors. That's just a thought. I haven't tracked through the code to follow how that could explain your observation. Why do you need for this to operate with the cable disconnected? If that is the case, it should have a pullup resistor (or pulldown if inverted) to hold the line in the Stop state so that it can't float.
When I turn NOECHO off, Tx no longer hangs and I get some garbage and then the echo. I am not so sure the problem is isolated to NOECHO, as I so confidently stated before. I pointed the object to the PSC terminal with NOECHO and OCTX, at 2400 and 9600 baud, with separate Tx and Rx pins, and there seems to be an issue receiving characters from the PSC.
I'll have to look into this further to understand the issue. Something else might be going on; however, when I switch back to fullduplexserial_rr004, the behavior returns to normal.
I'll look into it over the next few days. If you spot something, let me know.
I use the attached when connecting a half-duplex device to a full-duplex port.
Hmmm. You have to wonder where the garbage is coming from. With the pullup resistor, the line should be quiet between the tx and the rx. Is it possible that there is electrical noise coming from the servos or valves? This is where an oscilloscope or Saleae can help, to visualize the signal. I can't think at the moment why 4port would react differently than 1port, though, unless it is issue issue of stop bits.
(Love the fountain, by the way. I grew up in Battle Creek MI and my sister still lives in Montague, north of Benton Harbor.)
I fixed an unrelated problem and pointed fulldupexserial4port to the Parallax serial terminal with mode = 0, 9600 baud, separate Tx and Rx pins, and there seems to be *no* issue. Characters are transmitted and received properly.
I pointed fullduplexserial4port to an empty pin with mode = $1100 (NOECHO & OCTX), 2400 baud, Tx/Rx on the same pin, and no pull-up resistor, no cable connected and it hangs on Rx after Tx.
I added a pull-up resistor, and fullduplexserial4port does *not* hang. I connected the cable and the PSC, and fullduplexserial4port does *not* hang, but no characters are received.
My connections, which have been successful with fulldupexserial_rr004, with NOECHO and OCTX, 9600 baud, Tx/Rx on pin, for many years with no issue, follows:
I run without a connection to continue development without a full compliment of peripherals.
Your comments and suggestions will be appreciated. In the meantime, I will continue to look into this further to understand the issue. Something else might be going on, because when I switch back to fullduplexserial_rr004, same connections and settings, the behavior returns to normal.
issue #1:
When you develop without a full complement of peripherals, can you leave a pullup resistor in place? Lacking the resistor, the tx byte you send pulls the line low and leaves it there. fds4port rejects framing errors, puts nothing in the rx buffer, and it hangs when it looks for the echo: The fds-rr004 uart though will not lock, because it ignores the framing error, puts nulls (many of them) in the buffer, and thus, none the wiser, escapes from the trap. I feel that rejection of framing errors is important enough to keep. But I definitely don't like the potential lockup. I'm thinking I should change the rx(port) to rxTime(port, clkfreq*10 / baudrate), allowing it to stick there for just enough time for the tx pasm routine to send all the bits. That is tricky though, because the spin tx(port) routine does not have access to the baudrate parameter. I'll give it some thought but do let me know if you have suggestions about it. In the meantime, be sure to leave a pullup resistor in place for open baud modes.
Issue #2:
I added a pull-up resistor, and fullduplexserial4port does *not* hang. I connected the cable and the PSC, and fullduplexserial4port does *not* hang, but no characters are received.
That I don't understand. I'm not familiar with how the PSC operates. What gets sent to the PSC, and what response are you expecting? It has a built-in pullup resistor for the shared rx/tx?
As a related aside, I've used fds4port successfully for SDI12, which is a single wire common buss protocol, popular for environmental instrumentation.
I considered modifying fullduplexserial4port with rxtime after tx, but I haven't thought through the issues with this. Right now I am more interested in knowing exactly why fullduplexserial4port behaves differently than fullduplexserial_rr004. You explained part of it with a change in the way the stop bit is handled. I wonder if the issue is in PASM or totally unrelated, such as another object stepping on a buffer or something.
When the PSC receives the command "!SCVER?<cr>", it responds with the version number, such as, "1.2".
The Rx routine goes like this:
I'll experiment further and advise the results. Let me know if you think of something else for me to consider.
When fds4port sends a position command such as
"!SC", ch, ra, pw.LOWBYTE, pw.HIGHBYTE, CR
Does the servo actually move to the new position? That is to inquire, is the issue only with receiving chars back from the PSC, or both with sending and receiving?
That's the thing. It started before there. The start up sequence begins by sending a version command, receiving the version number, displaying the version number, then waits for a command from the host (Parallax Serial Terminal). fds4port hung, so we did not get to the point of sending a position command to the PSC.
I began my troubleshooting at the version command, because Tx was hanging. I now know that Tx is working, and it was hanging on the Rx after Tx, so I focused on Rx. Once we got past that, I started getting garbage characters on Rx.
I performed the following experiment tonight:
PST displays "Ready" followed CR followed by a string of garbage characters. If I hit a key, PST displays the key, and continues to receive and display garbage characters. I expect fds4port to wait for a key to be hit, but it doesn't. Pins 30 and 31 are connected to the USB port, so there's no custom circuitry involved.
Let's sum it up so far:
- Use a pull-up resistor for when nothing is connected
- Use rx, not rxcheck
So, now back to the original problem. When I turn on NOECHO (%1000), fds4port does not transmit.
I pointed fds4port to the USB port to see what happens on a Propeller Serial Terminal. It runs fine with PSCmode = 0, and hangs after displaying "R" with PSCmode = %1000. It hangs on the Rx after Tx.
The methods in dataIO4port were part of Tim Moore's original pcFullDuplexSerial4fc, plus methods that come from PST and other sources. I split it off from the core routines of fds4port. When both are used, they are declared as separate objects, or you can use different i/o methods, or you can merge dataIO4port back into fds4port. Is the latter what you have done, and called it "dataIO4port"? Can I surmise that in merger, somehow rx got pointed to rxCheck? A surmise.
"I pointed fds4port to the USB port to see what happens on a Propeller Serial Terminal." I see you changed the pins over to 31 for rx and 30 for tx, and now you are attempting to send data to the computer. The prop transmits the "Ready" just fine when mode=0 but only the "R" when NOECHO is on. I am not sure that PST echos characters back to the prop. Well, I'm pretty sure it does not. I think if you press "R" on the PC keyboard, then the prop should move on to the "e", and so on. Your finger provides the echo. I know there is an "echo" check box on PST, but that turns on and off local echo of what you type at the PC, not echo of what the PC receives from outside. Some terminal programs do have remote echo as an option too. Or, you could make the Prop itself emulate a terminal with echo.
I'll see if I can get ahold of a PSC so that I can follow along better.
You're right. There is no echo to ignore when Tx and Rx are on different pins while using PST. Silly me. The object behaved as designed. I hope this embarrassing feeling dissipates quickly.
I confirmed the following:
- The PSC (aka PSCU) responds to commands typed into the PST when connected directly to the PC. The PST displays "1.4" after typing the command "!SCVER?<cr>"
- fds4port properly receives echo characters when Tx and Rx are on the same pin and mode = 0
- fds4port hangs when Tx and Rx are on the same pin and mode = %1000
I know the echo characters are in the Rx buffer. I don't know why rx(port) is missing them in fds4port. I can read and display the echo characters with rx(port) in my object. It's a mystery why fds4port hangs at the identical rx(port) command (when the "if" statement is true):
Tonight I will add a little delay before the above "if" statement in fds4port to see if there is a timing issue.
The PSC responds properly when directly connected to the PST. The PSC responds to commands issued by fds_rr004. The PSC does *not* respond to commands issued by fds4port.
Next experiment: Take a look at the serial strings with an oscilloscope and compare fds_rr004 and fds4port outputs.
The objects look like this:
Yes. %1100 when Tx/Rx are on the same pin. %0 when Tx/Rx are on separate pins. I may have made a typo.
Here's a summary of what I found communicating with PSC #28830 using either fds4port or fds_rr004:
- Propeller Board of Education (#32900): NG
- Propeller Activity Board #1 (#32910): NG
- Propeller Activity Board #2 (#32910): NG
- Board of Education (#28150) + Spin Stamp (#SS1-IC): No issues
- Propeller Serial Controller USB + Parallax Serial Terminal (direct connection): No issues
All boards are configured as follows:
- I/O Pin #15
- Mode %1100 (NOECHO + OCTX)
- Baud 2400
I will call this problem solved because it looks like my issue is not related to fds4port.
Thank you so much for your help and support.
I asked that because I found a difference in code operation between the two, on my prop code that accesses serial ports.
I just found the source of my problem. I have been using BST for some time, but since starting to use it certain serial related code stopped working.
Turns out it isn't a problem with the serial ports themselves, but the wrapper object I created that used the ObjectBoundHack as documented by jazzed in http://forums.parallax.com/showthread.php/120467-Procedure-variables-or-callbacks-in-spin?p=886310&viewfull=1#post886310. BST seems to be eliminating the fp1, fp2, fp3 object code as 'unused' since it isn't directly referenced. If I compile with Prop Tool, it works fine. If I turn off the "eliminate unused spin methods" compiler option in BST, then it partially works there.
I'll post any followup on the referenced thread, since it isn't related to this thread. I ended up here because the symptoms were similar (serial output stalling, garbage output, etc, etc depending on combinations of things tried).
I will continue to experiment as I'm still seeing non-deterministic behavior.
Thanks for your comments as I will use BST sometime in the future.
I have been experimenting with demo2_FDS4port on my Propeller Activity Board #32910. The demo works as described at 57600 and 2400 baud. I am a bit curious about the Rx bits that are "discarded." I'd like to know where those "not strictly necessary" characters come from.
Then, I changed the demo and circuit as follows, and it does not work:
What am I doing wrong?
Not to leave it hanging. I made a little program to use fullDuplexSerial4port to set up two cogs to talk to one another over one wire, half duplex, using the open baudmode, OCTX+NOECHO. It launches one cog to emulate (weakly) the Parallax Servo Controller command set. So you can type in the command that gave trouble, "!SCVER?"<CR> and that will be transmitted out the master OCTX port to the slave and the slave will respond with "1.2". There are other commands too, fun with parsing.
I added a pull-up resistor and fds4port communicates fine with the PSC on all Propeller board versions over one wire with OCTX+NOECHO and 2400 open-mode baud. I conducted a number of experiments and although I did not determine the exact causes, I am no longer detecting non-deterministic behavior. I re-downloaded fds4port and dataIO4port and am using them as originally designed. I pushed rxtime out to 30ms as the USB PSC seems to respond differently than the serial PSCs. I am now confident that you and others identified the root causes of my various issues. Thank you.
Is there a change I could make to so that fds4port will not hang with a framing error as described in your post #2? I would prefer that system always be responsive and not hang should there be a framing error.
Dennis
In my opinion, the occurrence of framing errors should be handled in the application Spin code. There are very few PSC commands that return feedback, anyway, the lack of return data can be handled with rxCheck or rxTime.
If you really do want to remove the suppression of framing errors, you have to delete a line from the pasm code for each of the receive routines in fullDuplexSerial4port. It's this line: Also with #receive1, 2, 3. That will make it behave more like the other fullDuplexSerial incarnations in that regard.