View Full Version : ReadSerial of new data requires Delay() ?
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.
Darren
23 Mar 06, 09:33 AM
See the logic help file topic "serial io". It exactly describes your problem and the solution.
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.
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
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.
Darren
24 Mar 06, 10:27 AM
"Is a delay() required for newly received data to be buffered and be available via ReadSerial()"
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.
vBulletin® v3.7.4, Copyright ©2000-2012, Jelsoft Enterprises Ltd.