ReadSerial of new data requires Delay() ?

Discussion in 'C-Touch/HomeGate/SchedulePlus/PICED Software' started by BradJ, Mar 22, 2006.

  1. BradJ

    BradJ

    Joined:
    Aug 6, 2004
    Messages:
    95
    Likes Received:
    0
    Last night I was debuggung some code in PICED. I have a procedure that sends a string to a modem, then reads back the echo. i.e. a WriteSerial followed by a ReadSerial. The problem was that the ReadSerial never got the echo. I finally got it working only by seperating the "SendData" to the "ReadEcho" parts, and calling them from a module so I could insert a delay in between of them.

    Does the ReadSerial() only pick up new data once a new 'logic loop' has been run? (so only after a delay(), waituntil(), etc).

    The documentation indicates that my initial function should have worked. I'll try some other experiments tonight to make sure code from other modules wasn't interfering and causing the problem.
     
    BradJ, Mar 22, 2006
    #1
  2. BradJ

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    See the logic help file topic "serial io". It exactly describes your problem and the solution.
     
    Darren, Mar 22, 2006
    #2
  3. BradJ

    BradJ

    Joined:
    Aug 6, 2004
    Messages:
    95
    Likes Received:
    0
    Darren,

    Thanks for your reply.

    My apologies, my original post missed an important piece of information which was that my ReadSerial() was in a loop, providing ample time for the request to be transmitted and the response to be received.

    I was actually refering to that section in the help when I was saying that the code I HAD in before I needed to add a delay should have worked according to the help.

    The section you refer to:

    ------ Start Snippet -------
    The WriteSerial procedure does not wait until the command has been sent before continuing with the next line of code. Hence the following code will most probably result in the ReplyString being empty, as there will not be enough time for the TransmitString to be sent, let alone for a reply to have been received :

    WriteSerial(2, TransmitString);
    ReadSerial(2, ReplyString, #13#10);
    if ReplyString <> '' then
    begin
    ...

    The preferred way would be something like :

    WriteSerial(2, TransmitString);
    delay(1);
    ReadSerial(2, ReplyString, #13#10);
    if ReplyString <> '' then
    begin
    ...
    -------- End Snippet --------

    states that the code in the top sample would work if there was enough time for the string to be transmitted and the response to be received. I had put the ReadSerial() into a massive loop and upped the maximum instructions per loop to numbers that left it there polling the serial port for about 30 seconds. My serial port trace showed that the modem had responded well within that.

    So I think you are saying that a delay() is not required for newly received data to be buffered and be available via ReadSerial(). I must have had another problem, possibly another module reading the serial port and stealing the response. I will try to isolate the problem tonight.

    It would be good if you could confirm the above for me.

    Thanks again,
    Brad.
     
    BradJ, Mar 23, 2006
    #3
  4. BradJ

    JohnC

    Joined:
    Apr 6, 2005
    Messages:
    554
    Likes Received:
    1
    Location:
    Sydney
    I haven't done any Cbus Logic coding, but have done heaps for other applications... So I can't specifically solve your problem, but I must say that using a LOOP as a "delay" is very very bad coding...

    With a loop you don't really have control over how long each loop takes, it depends on what else is going on around it (CPU load etc).

    In the example code, CIS say there must be a delay between Writing and Reading - yet in my own experience there might also needs to be a delay between a ReadSerial and checking if there is anything held in the Variable. I am assuming ReadSerial procedure ALSO does not wait for a response before continuing execution... but that might be wrong.

    Delay() is also not particularly reliable, because you are guessing how long you should wait for a response (and while it's a Delay the code execution is paused). But the solution is a combination of the 2...

    Why not do this (not code, just my text description) kind of thing...

    start loop
    ReadSerial(2, ReplyString, #13#10);
    if ReplyString = '' then
    loop again
    else...[ continue ]

    That way, it will only loop as many times as it needs to capture the data. You could also conditionally test if the correct number of characters has been received, so it doens't grab a partial response.

    Also note, if you do that kind of looping, you should include a counter and only let it loop for a certain number of times, or for a certain number of seconds. Otherwise, if there is never a response from the Modem (which DOES happen quite often), then the Logic will hang.

    Hope that helps, although please keep in mind that what I have stated above may NOT apply to the Logic Coding within CIS applications !

    Cheers, John
     
    JohnC, Mar 23, 2006
    #4
  5. BradJ

    BradJ

    Joined:
    Aug 6, 2004
    Messages:
    95
    Likes Received:
    0
    John,

    Thanks for your comments.

    I had actually already done what you are suggesting - loop waiting for a response for a maximum number of times and thats whats not working. No matter how long I leave it looping, the repsonse never comes through unless I move the logic out of a procedure and into a module (because delay() is only allowed in modules) with a delay between the write and the read.

    I want to keep the write and read together in a procedure and Delay() isn't supported in procedures so I have no choice but to employ a loop, and it would work fine and would be the best option in terms of performance if ReadSerial() let the data through.

    I have now changed my implementation to move the logic out of procedures into modules and using delays and it works (with larger delays than I would like, but this is not a time critical application) so I'm not too worried about changing it any more. Being the curious sod I am, I'm still interested to know the answer to my question. I'm sure Darren will comment on it tomorrow. I may go back to test it at some future date if the question is left open.

    In case my question is still not obvious, it is simply:

    "Is a delay() required for newly received data to be buffered and be available via ReadSerial()"

    By the way, I love having Logic.

    Regards,
    Brad.
     
    BradJ, Mar 23, 2006
    #5
  6. BradJ

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    Yes it is. The logic engine needs to complete its run before the serial input data will get updated.

    By the way, do not use loops to cause delays for any reason. It is essential to allow the logic engine to finish completion ASAP, otherwise there are all sorts of undesirable side-effects.
     
    Darren, Mar 23, 2006
    #6
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.